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.