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
.
- Inicialmente pregunta "¿
active_flag
existe dentro del alcance dewhats_my_active_flag
? - Busca y se da cuenta de que la respuesta es "nope", por lo que salta un nivel, a la instancia de SomeData
- Pregunta lo mismo otra vez: "¿
active_flag
existe dentro de este alcance? - 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:
- Pregunta "¿
active_flag
existe dentro del alcance dewhats_my_active_flag
? - 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!