My rails model has code that is attempting to define_method(method_name)
inside the model.
I keep getting:
NoMethodError: undefined method `define_method'
What am I doing wrong? Am I doing this in the wrong place. I need this method attached to this model. Where else can I define this method?
EDIT: For those asking to see the code:
for field in rdev_fields next if self.attributes.include?(field) count = count + 1 rdev_hash[field.to_sym] = self.attributes["attribute#{count}"] if !self.respond_to?(field) then define_method("#{field}") do self.send("attribute#{count}".to_sym) end end end
define_method is a method defined in Module class which you can use to create methods dynamically. To use define_method , you call it with the name of the new method and a block where the parameters of the block become the parameters of the new method.
Metaprogramming is a technique in which code operates on code rather than on data. It can be used to write programs that write code dynamically at run time. MetaProgramming gives Ruby the ability to open and modify classes, create methods on the fly and much more.
A model is a Ruby class that is used to represent data. Additionally, models can interact with the application's database through a feature of Rails called Active Record.
A Rails Model is a Ruby class that can add database records (think of whole rows in an Excel table), find particular data you're looking for, update that data, or remove data.
There's nothing magical or about a rails model, it's just a normal class with a bunch of pre-existing methods,
So, the question is "can I define_method in a class"?
The important distinction is than you can define method in a class not in an instance method
For example:
class Cow define_method "speak" do "MOOOO" end end Cow.new.speak => "MOOOO"
This should work fine. Note you're defining it on the class Cow, so any other Cows that you already have will automatically get that method added.
You can't define methods from an instance method, so you have to grab the class, and use that to define the method. Like this:
class Cow def add_speak self.class.send(:define_method, :speak) do "MOOOO added" end end end Cow.new.speak NoMethodError: undefined method 'speak' for #<Cow:0xb7c48530> Cow.new.add_speak Cow.new.speak => "MOOOO added"
Problem solved. Astute readers will note that in this example I'm using send(:define_method)
- this is needed because define_method
is private, and private methods are only accessible to the thing they're in. In this case, define_method
is in the class, we are in the instance, so we can't directly access it.
As above though, we're adding the method directly to the class, so all other Cows which already exist will automatically also get the speak method added.
Example:
class Cow def add_speak_just_me class << self define_method "speak" do "MOOOO added for just me" end end end end Cow.new.speak NoMethodError: undefined method 'speak' for #<Cow:0xb7c72b78> c = Cow.new c.add_speak_just_me c.speak => "MOOOO added for just me" # it works, hooray Cow.new.speak # this new cow doesn't have the method, it hasn't been automatically added NoMethodError: undefined method `speak' for #<Cow:0xb7c65b1c>
How does this work? Down the rabbithole you go!
Read this: http://dannytatom.me/metaid/ and good luck. It helps when you realise that 'adding a method' to an instance isn't actually adding it to the instance at all :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With