From: Josh Cheek Date: 2011-04-25T02:29:49+09:00 Subject: Re: Set attribute of superclass dinamically --001636832dccff7ae104a1ad6f60 Content-Type: text/plain; charset=ISO-8859-1 On Sun, Apr 24, 2011 at 9:29 AM, Jeroen v. wrote: > I have the following code > > class foo > price_per_liter = 1 > price > module bar > def set_price val > self.price_per_liter = val > end > end > end > > In this way I can succesfully set the price per liter of the class. How > can I make it dunamically, so I can also set the attribute 'price'? > > I tried instance_variable_set(@variable, val), but that doesn't work. > Probably because the variables of the class 'foo' and the module 'bar' > lives independent of each other. > > What was the error it gave you? From here, I have a hard time believing you tried setting the ivar, because your code has two syntax errors (classes and modules must be constants) a name error (price is neither a local variable nor a method), and you can not set the price per liter of the class as you say you did, since price_per_liter is a local variable and there is no price_per_liter= method, anyway. Anyway, everything in Ruby is an object, including classes. Every object in Ruby has a singleton class, which is a class just for that one object (they are created lazily). Why is this relevant? Because methods are defined in classes, so defining methods on the object's singleton class will define methods for that one object. This is what class methods are. So what about modules? When you extend an object (and classes are objects) with a module, it gets put in the ancestry chain behind the singleton class. So when you ask the object for its methods, it looks in the singleton class, and when it doesn't find it, it goes up the chain into the module, where it discovers the method. So, we just define the #price= method in the module, then we extend the class with the module, and now the class has access to that method. # define the price method on the # singleton class of Foo class Foo def self.price @price end end # define the price= method as an # instance method of Bar module Bar def price=(new_price) @price = new_price end end # put Bar as an ancestor of # Foo's singleton class Foo.extend Bar # tada, everything works Foo.price # => nil Foo.price = 5 Foo.price # => 5 You also look like you don't understand the difference between local variables, instance variables, and methods. In Ruby, all instance variables are private, and they always begin with the @ sigil. So @price is an instance variable, and price is either a local variable or a method. When you say `price_per_liter = 1` in your code above, you are setting a local variable. If you want to invoke a method on self, you need `self.price_per_liter = 1` to disambiguate. If you want to set the instance variable, you need `@price_per_liter = 1` Note that Ruby has syntactic sugar to turn `self.price = 1` into `self.price=(1)`, that assignment is just a method call. --001636832dccff7ae104a1ad6f60--