Frage

I define class methods dynamically in Rails as follows:

class << self
  %w[school1 school2].each do |school|
    define_method("self.find_by_#{school}_id") do |id|
        MyClass.find_by(school: school, id: id)
    end
  end
end

How can I use method missing to call find_by_SOME_SCHOOL_id without having to predefine these schools in %w[school1 school2]?

War es hilfreich?

Lösung

It is not completely clear to me what you want to achieve. If you want to call a method, you naturally have to define it first (as long as ActiveRecord does not handle this). You could do something like this:

class MyClass
  class << self
    def method_missing(m, *args, &block)  
      match = m.to_s.match(/find_by_school([0-9]+)_id/)
      if match
        match.captures.first
      else
        nil
      end
    end  
  end
end

puts MyClass.find_by_school1_id
puts MyClass.find_by_school2_id
puts MyClass.find_by_school22_id
puts MyClass.find_by_school_id

This will output:

1
2
22
nil

You could then do something with the ID contained in the method name. If you are sure that the method is defined, you can also use send(m, args) to call that method on an object/class. Beware though, if you do that on the same class that receives the method missing call and the method is not defined, you will get a stack overflow.

Andere Tipps

I recommend return the super unless you have a match


class MyClass
  class << self
    def method_missing(m, *args, &block)  
      match = m.to_s.match(/find_by_school([0-9]+)_id/)
      match ? match.captures.first : super
    end  
  end
end
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top