How to use the self keyword in rails

regarding the "self" keyword in rails, let's take the code snippet below, for example. I know that the keyword refers to an instance of the class itself, for example, to the expression "self.encrypted_password". In any case, I understood why the password attribute passed as a parameter on the right side also does not have a prefix with the self keyword?

could anyone enlighten me when to use or not to use the self keyword following my example?

class User < ActiveRecord::Base attr_accessor :password attr_accessible :name, :email, :password, :password_confirmation validates :password, :presence => true, :confirmation => true, :length => { :within => 6..40 } before_save :encrypt_password private def encrypt_password self.encrypted_password = encrypt(password) end def encrypt(string) string # Only a temporary implementation! end end 
+4
source share
3 answers

Answer

The answer is simple: visibility visibility.

 def encrypt_password self.encrypted_password = encrypt(password) end 

There is (or rather should be at runtime) something called password . In your case, this is an attribute from the database. But it can also be a local variable. If no such name is found, an error will be raised.

But you need to attach encrypted_password to self to explicitly indicate that you are going to update the instance attribute. Otherwise, a new local variable encrypted_password will be created. Obviously, this is not the effect you need.

Additional Information

Here is a small piece of code

 class Foo attr_accessor :var def bar1 var = 4 puts var puts self.var end end f = Foo.new f.var = 3 f.bar1 

Output

 4 3 

So, as we can see, var is assigned without the keyword self , and because of this, now there are two var names in the scope: a local variable and an instance attribute. The instance attribute is hidden by a local variable, so if you really want to access it, use self .

+8
source

The question has nothing to do with Rails, but with Ruby. When you look at your code:

 def encrypt_password self.encrypted_password = encrypt(password) end 

It will be translated by Ruby into:

  • self.encrypted_password = - method call to encrypted_password= method.
  • This method is generated by Rails on the fly because there is a database column with the same name.
  • encrypt(password) contains 2 method calls.

    • password calls the password method, which is the real attribute of the model as declared by attr_accessor :password . This declaration creates two methods:
      • password : getter attribute
      • password= : setter attribute

    See @Sergio_Tulentsev's explanation of how a getter can be hidden by a local variable (this is not the case in your implementation, there is no local variable).

    • Calls the encrypt method with the return value of the password method call.

So using self. makes it explicit that you have (all the time) a method call, you are not directly accessing the attribute. If you want to do this, you should use @password = <some value> inside the instance method, but I prefer the style with self.password = <some value> .

Hopefully now it’s clear how your code is interpreted.

+2
source

setter method => use self

Use self when you need to write .
In other words, when you need to assign a value.

getter method => do not use self

And without self when you need to read .
When you need to read the meaning.

eg:

 def write_name(name) self.name = name end def read_name name end 

In your case, the virtual password attribute does not have a prefix with the keyword self , because it is only readable (getter).

encrypted_password is what will be stored in the database, it is written in db (setter). So using self .

Edit

Michael HARTL has the same explanation for the same case:

(Of course, as we have already noted, self is not optional when assigning to an attribute, so in this case we must write self.encrypted_password.)

http://ruby.railstutorial.org/chapters/modeling-and-viewing-users-two#sec:an_active_record_callback

(last lines in 7.1.3)

0
source

Source: https://habr.com/ru/post/1390754/


All Articles