self.variable vs. @variable

Hi everybody,

I am studying Ruby on Rails Tutorial: Learn Rails by Example at railstutorial.org and currently i am studying chapter 7. There are some issues make me confused. It will be great if you help me on these issues.

1). We are creating virtual attributes via attr_accessor and making it accessible via attr_accessible. Is this statement correct? I mean if we create a virtual attribute via attr_accessor cant we use it without declaring it with attr_accessible?

2). What is the difference between self.variable and @variable? Is it something like that we are using self.variable for variables not mentioned in attr_accesible and @variable for variables mentioned in attr_accesible. Is that true?

Best regards... Rushen

Hi everybody,

I am studying Ruby on Rails Tutorial: Learn Rails by Example at railstutorial.org and currently i am studying chapter 7. There are some issues make me confused. It will be great if you help me on these issues.

1). We are creating virtual attributes via attr_accessor and making it accessible via attr_accessible. Is this statement correct? I mean if we create a virtual attribute via attr_accessor cant we use it without declaring it with attr_accessible?

virtual attributes don't differ from normal attributes when it comes to attr_accessible: if you've gone the whitelist approach (ie you've used attr_accessible elsewhere), then attributes (virtual or not) are protected from mass assignment unless you call attr_accessible on them.

2). What is the difference between self.variable and @variable? Is it something like that we are using self.variable for variables not mentioned in attr_accesible and @variable for variables mentioned in attr_accesible. Is that true?

self.variable calls the method called variable (which may or may not be backed by an instance variable), whereas @variable access the instance variable of that named directly. @variable won't work for an active record attribute, since those aren't stored in individual instance variables (AR stores a hash of all the database attributes in one place(

Fred

Thank you for your reply, As i understand i always need to use self in spite of @ in a model file. I have no information about mass assignment so i am searching for it... Best Regards... Rushen

Thank you for your reply, As i understand i always need to use self in spite of @ in a model

Not always, but sometimes you need to in order to resolve an ambiguity eg, if you have a local variable called foo and an accessor method called foo and you write

foo

then ruby needs to decide whether you wanted to call the method foo or just get the local variable. self.foo or foo() tells ruby you wanted to call the acessor method

if you write foo=123, ruby will always assume you wanted to set the local variable foo, so you need to write self.foo = 123

Fred

Ok then, as an example what does the code mean below

def encrypt_password   self.encrypted_password = encrypt(self.password) end

Best Regards

Rushen

Ok then, as an example what does the code mean below

def encrypt_password self.encrypted_password = encrypt(self.password) end

Well it's calling encrypted_password= with the result of encrypting self.password. In this particular pattern password is normally a virtual attribute, and the encrypted version of it is stored in the encrypted_password column

Fred

Thank you Fred for your answers. It is a big gain for me to learn that we can not use @variable for AR attributes.

Frederick Cheung wrote in post #975681:

Ok then, as an example what does the code mean below

def encrypt_password self.encrypted_password = encrypt(self.password) end

Well it's calling encrypted_password= with the result of encrypting self.password. In this particular pattern password is normally a virtual attribute, and the encrypted version of it is stored in the encrypted_password column

I think it's also important to understand the distinction between "calling" and "messaging."

In a procedural language such as C, functions are called directly and contain a list of arguments that are passed into the function.

In Ruby (as an object-oriented programming language) "encryped_password=" represents a message that takes one argument. A "message" in OOP contains three basic parts. 1. A receiver, 2. The message, and 3. The argument list. Messages are generally back by "methods" which are very similar to functions, but are scoped (encapsulated) within the context of the class containing the method. Methods are not called directly, as in the case of functions, but rather are "called" indirectly by the runtime virtual machine, based on the combination of receiver and message.

In the case above there are actually three separate messages, where all three are sent to "self" as the receiver. The three messages are "encrypted_password=", "encrypt", and "password". In the case of the "encrypt" message "self" is assumed, since a receiver is not specified. The first message sent to "self" is "password". The result of that message is then passed as an argument to the message "encrypt". Finally the result of the "encrypt" message is passed as the argument to "encrypted_password=".

I hope that doesn't confuse you further, but I do think it is important to understand this basic OOP principal. Methods don't behave exactly like functions. No matter how many classes may implement a given method (like "add" for example) there is only one "add" message. The same "add" message can be sent to any object that implements an "add" method. This is called "polymorphism" in OOP terminology, because each receiver of "add" can provide different behavior to this same message.