Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a method like ".find_by_something_and_something_else" using Ruby?

Using Ruby I know you can get pretty creative with how you name your methods. For instance in rails you have .find_by_this_and_that.

How can I do this?

Example:

def get_persons_with_5_things
  res = []
  persons.each do |person|
    if person.number_of_things == %MAGICALLY GET THE NUMBER 5 FROM FUNCTION NAME%
      res << person
    end
  end
  return res
end

I'm not even sure how you call this kind of things so any pointers would be appreciated.

like image 408
marcgg Avatar asked Aug 03 '26 03:08

marcgg


1 Answers

I'm a little confused by your example. If you define the method with the hardcoded 5 in the method name, then you don't need to magically figure it out inside the body of the method. If you want to do something dynamic with method missing, it would be something like this:

def method_missing(name, *args)
  if name.to_s =~ /get_persons_with_(\d+)_things/
    number_of_things = $1.to_i
    res = []
    persons.each do |person|
      if person.number_of_things == number_of_things
        res << person
      end
    end
    return res
  else
    return super(name, *args)
  end
end

[EDIT (Jörg W Mittag)]: This is a more Rubyish way of implementing that same method:

def method_missing(name, *args)
  return super unless name.to_s =~ /get_persons_with_(\d+)_things/
  number_of_things = $1.to_i
  return persons.select {|person| person.number_of_things == number_of_things }
end
  • super without any arguments just passes the original arguments along, no need to pass them explicitly
  • an early return guarded by a trailing if or unless expression greatly clears up control flow
  • all the each iterator does, is select items according to a predicate; however, there already is an iterator for selecting items: select
like image 133
ottobar Avatar answered Aug 05 '26 16:08

ottobar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!