penguin libros house facturacion catalogo books ruby ruby-on-rails-3 instance-variables self

ruby - libros - penguin random house uk



Carriles-auto vs. @ (3)

Rails ha agregado automáticamente los elementos de acceso para encrypted_password porque existe un campo con ese nombre en la tabla de users .

Cualquier campo que agregue a una tabla estará disponible automáticamente a través de self.field_name .

Aquí es donde el tutorial de Michael Hartl crea el campo encrypted_password en la tabla de users .

También mire en user_spec.rb (Listado 7.3) en la página vinculada, donde el autor está probando la presencia del campo encrypted_password .

ACTUALIZADO:

Como @mu señala, @ se usa para las variables de instancia de Ruby (también conocidas como "iv"). Pero encrypted_password es un "atributo" definido por Rails, y no es una variable de instancia.

Si ejecuta User.find(1).instance_variables , verá que hay un iv llamado @attributes , que es de tipo Hash .

Dentro de ese iv es donde se almacena la encrypted_password . Rails ha definido los métodos de acceso para encrypted_password , que obtiene / establece los datos para ese atributo en el @attributes atributos.

Tenga en cuenta que también puede obtener / configurar los datos a través de @attributes["encrypted_password"] llamada desde la clase de User (pero los métodos de acceso son una forma conveniente de hacerlo).

Estoy siguiendo el tutorial RoR de Michael Hartl, y cubre los conceptos básicos del cifrado de contraseñas. Este es el modelo de usuario actual.

class User < ActiveRecord::Base attr_accessor :password attr_accessible :name, :email,: password, :password_confirmation email_regex = /^[A-Za-z0-9._+-]+@[A-Za-z0-9._-]+/.[A-Za-z0-9._-]+[A-Za-z]$/ #tests for valid email addresses. validates :name, :presence => true, :length => {:maximum => 50} validates :email, :presence => true, :format => {:with => email_regex}, :uniqueness => {:case_sensitive => false} validates :password, :presence => true, :length => {:maximum => 20, :minimum => 6}, :confirmation => true before_save :encrypt_password private def encrypt_password self.encrypted_password = encrypt(password) end def encrypt(string) string end end

before_save una pregunta anterior acerca de before_save no funciona, y resulta que lo que accidentalmente hice fue escrito en encrypt_password como:

def encrypt_password @encrypted_password = encrypt(password) end

Entiendo que si self.encrypted_password establece el atributo encrypted_password, pero ¿por qué @encrypted_password no hace eso también? En la respuesta a la publicación anterior acerca de before_save no funciona, alguien dijo que la variable de instancia se había "olvidado" después de que el método terminara con la forma en que lo había codificado originalmente: ¿por qué fue este el caso? ¿Puede alguien explicar cómo funcionan de manera diferente yo y @ en el contexto del código anterior?

NOTA: Ya eché un vistazo a las publicaciones here y here , pero las dos dicen que "self" está llamando a attribute = method, y ni siquiera entiendo cómo ese método podría existir aquí ya que nunca lo creé o declaré. encrypted_password w / attr_accessor . Así que todavía estoy confundido, y esto no es una nueva publicación de esas preguntas.


Si me dejas, me gustaría reformular la respuesta.

En esta post expliqué que, tan pronto como cree un modelo (rieles) con el mismo nombre (singular) que uno de los nombres (en plural) de su base de datos, la "magia" de rieles creará emisores y captadores en orden. para modificar los registros de su mesa.

Esto se debe a que su modelo hereda todos los métodos de ActiveRecord :: Base Class, que define los accesores básicos de CRUD (Crear, Leer, Actualizar, Eliminar).

El punto clave relacionado con su pregunta es que no sabe cómo rails implementa la variable de instancia relacionada con la columna de la tabla de su base de datos, y usted no debería. :) Todo lo que debe saber es que, en ese momento, tiene configuradores y receptores disponibles para CRUD (crear, leer, actualizar, eliminar) la columna de la base de datos "encrypted_password".

En su ejemplo, quizás rails usa una variable de instancia llamada @encrypted_password, quizás rails usa una variable de instancia hash llamada @attributes ["encrypted_password"], o tal vez rails usa una variable de instancia llamada @you_will_never_guess_encrypted_password.

-

Y ese es un buen punto que no conoce sobre el comportamiento de los rieles internos con las variables de instancia. En 2019 Rails, un mayor desarrollo puede llevar a la estructura a utilizar la variable @plicity-hash-instance para almacenar el valor de encrypted_password.

De hecho, el mejor enfoque es dejar que Rails administre su "asunto" "privado";) con variables de instancia , y solo use los métodos de obtención y configuración que le proporciona. Por lo tanto, su aplicación seguirá funcionando con encrypted_password en el próximo siglo (espero que sea ^^).

Por lo tanto, si usa @encrypted_password, puede funcionar con algunas versiones "imaginarias" de rieles y ya no funcionará con otras versiones de rieles. En realidad, con una versión actual de rieles no funciona.

-

El segundo punto clave es que cuando quiere usar la secuencia de datos de la base de datos encrypted_password "getter" encrypted_password ", debe prefijar con" self "para que Ruby:" ok, quiero usar el método encrypted_password de mi usuario Instancia variable."

En Ruby, se llama a un método pasando su nombre a un receptor. Lo escribes así:

my_receiver.my_method

En su caso, pasamos el método encrypted_password a la variable de instancia de Usuario . Pero no sabemos cómo se llamará esta variable de instancia, así que usamos la palabra self para decirle a Ruby: "Estoy hablando de cualquier variable de instancia de la clase User que llame al método encrypted_password".

Por ejemplo, podríamos haber llamado a nuestra variable de instancia "toto":

toto = User.new

de modo que toto.encrypted_password mostraría la contraseña encriptada, y en este mismo caso en nuestro código se haría referencia a toto.

Sin embargo, gracias a Ruby, si no le da ningún receptor al llamar a un método , Ruby asumirá que se lo pasa a sí mismo .

Referencia: Guía del programador pragmático.

Así que en tu ejemplo, incluso no necesitas poner "yo". como prefijo Podrías tenerlo escrito así:

class User < ActiveRecord::Base def encrypt_password encrypted_password = encrypt(password) end end

Espero que esto ayude a aclarar este interesante tema.


TL; DR -

Siempre escriba self.widget_count = 123 si tiene la intención de guardar widget_count de nuevo en la base de datos.

(Pero, por favor, lea las respuestas largas, ya que la razón por la cual es valioso saberlo).