rails ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.1 self

ruby-on-rails - self rails



Cuándo usar self en Model? (4)

Pregunta: ¿cuándo necesito usar self en mis modelos en Rails?

Tengo un método set en uno de mis modelos.

class SomeData < ActiveRecord::Base def set_active_flag(val) self.active_flag = val self.save! end end

Cuando hago esto, todo funciona bien. Sin embargo, cuando hago esto:

class SomeData < ActiveRecord::Base def set_active_flag(val) active_flag = val save! end end

El valor de active_flag no cambia, sino que falla silenciosamente. ¿Alguien puede explicar?

No puedo encontrar ningún duplicado, pero si alguien encuentra uno también está bien.


Cuando estás haciendo una acción en la instancia que llama al método, utilizas self.

Con este código

class SocialData < ActiveRecord::Base def set_active_flag(val) active_flag = val save! end end

Está definiendo una nueva variable local de ámbito local llamada active_flag, configurándola en el valor aprobado, no está asociada a nada, por lo que se desecha rápidamente cuando el método finaliza como nunca antes.

self.active_flag = val

Sin embargo, le dice a la instancia que modifique su propio atributo llamado active_flag, en lugar de una nueva variable. Es por eso que funciona.


Cuando use active_flag = val ruby piensa que está definiendo una variable local, la mejor manera es self.active_flag = val , si lo tiene, espero que sepa que send(:active_flag=, val) también funcionará.


Es para asegurarse de que está utilizando el método setter y no explora una nueva variable. Es un detalle de uso de Ruby y AR que a menudo hace tropezar a las personas (el otro es el (mal) uso de una variable de instancia).

Tenga en cuenta que ya hay update_attributes! aunque entiendo el deseo de abstraer.

¡También hay toggle! , lo que podría ser aún más agradable, dependiendo de su interfaz para la bandera.


Esto sucede debido al alcance. Cuando estás dentro de un método e intentas establecer una nueva variable como esta:

class SomeData < ActiveRecord::Base def set_active_flag(val) active_flag = val end end

Está creando una nueva variable que vive dentro de set_active_flag. Tan pronto como se ejecuta, se va, sin alterar self.active_flag (la variable de instancia real) de ninguna manera.

SIN EMBARGO (esto fue una fuente de confusión para mí): cuando tratas de leer una variable de instancia en ruby, así:

class SomeData < ActiveRecord::Base def whats_my_active_flag puts active_flag end end

De hecho, obtendrás self.active_flag (la variable de instancia real) devuelta.

Este es el por qué:

Ruby hará lo que pueda para evitar devolver nil .

  1. Inicialmente pregunta "¿ active_flag existe dentro del alcance de whats_my_active_flag ?
  2. Busca y se da cuenta de que la respuesta es "nope", por lo que salta un nivel, a la instancia de SomeData
  3. Pregunta lo mismo otra vez: "¿ active_flag existe dentro de este alcance?
  4. La respuesta es "yup" y dice "Tengo algo para ti" y ¡eso lo devuelve!

Sin embargo, si define active_flag dentro de whats_my_active_flag , y luego lo solicita, sigue los pasos de nuevo:

  1. Pregunta "¿ active_flag existe dentro del alcance de whats_my_active_flag ?
  2. La respuesta es "yup", por lo que devuelve ese valor

En cualquier caso, no cambiará el valor de self.active_flag menos que explícitamente se lo indique.

Una manera fácil de describir este comportamiento es "no quiere decepcionarte" y devolver nada, por lo que hace todo lo posible para encontrar lo que pueda.

Al mismo tiempo, "no quiere confundir datos que no tenía la intención de modificar", por lo que no altera la variable de instancia en sí.

¡Espero que esto ayude!