Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I define_method in rails models?

Tags:

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 
like image 726
salt.racer Avatar asked Nov 19 '08 17:11

salt.racer


People also ask

What is Define_method in Ruby?

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.

What is meta programming in Ruby on Rails?

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.

What is a model in a Rails application?

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.

What are Ruby on Rails models?

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.


1 Answers

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"?

Part 1: Yes you can.

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.

Part 2: What do you do if you want to define a method from within an instance method?

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.

Part 3: What do you do if you want to define a method for only 1 object, not all objects of that class?

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 :-)

like image 90
Orion Edwards Avatar answered Feb 04 '23 20:02

Orion Edwards