Instance variable: self vs @
Writing @age
directly accesses the instance variable @age
. Writing self.age
tells the object to send itself the message age
, which will usually return the instance variable @age
— but could do any number of other things depending on how the age
method is implemented in a given subclass. For example, you might have a MiddleAgedSocialite class that always reports its age 10 years younger than it actually is. Or more practically, a PersistentPerson class might lazily read that data from a persistent store, cache all its persistent data in a hash.
ruby should I use self. or @
When you use @lines
, you are accessing the instance variable itself. self.lines
actually goes through the lines
method of the class; likewise, self.lines = x
goes through the lines=
method. So use @
when you want to access the variable directly, and self.
when you want to access via the method.
To directly answer your question, normally you want to set the instance variables directly in your initialize
method, but it depends on your use-case.
Rails -- self vs. @
The accessors for encrypted_password
have been automatically added by Rails for you because a field by that name exists in the users
table.
Any field you add to a table will be automatically made available via self.field_name
.
Here is where Michael Hartl's tutorial creates the encrypted_password
field in the users
table.
Also look at the user_spec.rb
(Listing 7.3) in the linked page, where the author is testing for the presence of the encrypted_password
field.
UPDATED:
As @mu points out, the @
is used for Ruby instance variables (aka "iv"). But encrypted_password
is an "attribute" defined by Rails, and is not an instance variable.
If you run User.find(1).instance_variables
, you will see that there is an iv called @attributes
, which is of type Hash
.
Inside that iv is where the encrypted_password
is stored. Rails has defined accessor methods for encrypted_password
, which gets/sets the data for that
attribute in the @attributes
Hash
.
Note that you could also get/set the data via @attributes["encrypted_password"]
called from within the User
class (but the accessor methods are convenient way to do just that).
class self vs self.method with Ruby: what's better?
class << self
is good at keeping all of your class methods in the same block. If methods are being added in def self.method
form then there's no guarantee (other than convention and wishful thinking) that there won't be an extra class method tucked away later in the file.
def self.method
is good at explicitly stating that a method is a class method, whereas with class << self
you have to go and find the container yourself.
Which of these is more important to you is a subjective decision, and also depends on things like how many other people are working on the code and what their preferences are.
What's the difference between using self.attribute and attribute in a model?
The difference in your examples is that the first one works, the second doesn't.
Your second version isn't doing anything (at least nothing meaningful). Writing my_attr = 123
is not equivalent to self.my_attr = 123
. Instead it's creating a local variable called my_attr
and setting it to 123
, and then immediately reaching the end of the method and throwing my_attr
away. The whole method is essentially a no-op, and it doesn't affect the model's my_attr
value in any way.
class User < ActiveRecord::Base
def do_another_thing!
my_attr = 456
puts self.my_attr # nil (or whatever value it was before)
end
end
Conversely, if you want to access a method defined on an object, you can (and should) omit self
:
class User
def name=(value)
@name = value
end
def name
@name
end
def age=(value)
@age = value
end
def age
@age
end
def do_something
self.name = "bob" # self is required
puts name # bob (self.name)
age = 47 # @age is unaffected
age # 47 (local variable), but self.age is nil
end
end
Note that, this isn't a Rails question, it's a Ruby question. There is no Rails-specific code here, this behaviour is part of how Ruby's syntax works.
Ruby self. vs @ in initialize
They are the same thing.
self.username =
calls the username=
function which is defined by attr_accessor. That function looks like this:
def username=(value)
@username = value
end
As you can see, it is identical to the "alternative" you mentioned.
EDIT Using an accessor (i.e. calling the function defined by attr_accessor/reader/etc) is significantly faster than other forms of access. There are a few links in the comments which elaborate more on this.
Rails: difference between self.function and self.class.function
def self.function2
is your class method that can not be called with instance of class. It call like TestClass.function2
. While def function3
is instance method. You are calling it right.
myvar = TestClass.new
myvar.function3
So if we follow flow. Under function3
self will become instance that is calling that function.
var3 = self.class.function2 # Here self is myvar
# self.class == TestClass
# self.class.function2 == TestClass.function2 # No error
# self.function2 == myvar.function2 # error, Calling class method with instance of class.
Now if you try to call class method with instance it will surely through error.
Rails Model method self. vs plain
self.method_name indicates a class method; method_name indicates an instance method.
You can read a lot more about class and instance methods at this blog post or, if you'd prefer something a bit more official, the Programming Ruby class section.
Rails, activerecord: self[:attribute] vs self.attribute
They're both just methods to get to the attribute - they're both just getters. self.attribtue
is a more "traditional" getter, whereas self[:attribute]
is basically just the []
method. Switching between using either has no ramifications.
I'd recommend using only the self.attribute
method because it's syntactically nicer. However, using the self[:attribute]
can come in handy when something else overrides the self.attribute
method.
For example, suppose you have a User model with a name
database column, so you'd get user.name
. But let's say you install a gem that adds a #name
method to each of your models. To avoid the complication, one option is to use user[:name]
to access it directly without going through the compromised method.
Related Topics
I Need to Generate Uuid for My Rails Application. What Are the Options(Gems) I Have
Ubuntu 12 - How to Install Ruby and Rails Correctly
Rails, Ruby, How to Sort an Array
How to Send Mail with Rails Without a Template
Finding All the Users That Have Duplicate Names
How to Dynamically Define a Class Method Which Will Refer to a Local Variable Outside
How to Install Rvm Without Root Access
How to Return a Value from a Thread in Ruby
$ Bundle Exec Rake Db:Reset Command Raising Couldn't Drop Db/Development.Sqlite3
How to Open Files Relative to Home Directory
Reading the First Line of a File in Ruby
Capistrano & Bash: Ignore Command Exit Status
Bundle Install Could Not Fetch Specs from Https://Rubygems.Org/
How to Read the Body Text of an Email Using Ruby's Net/Imap Library