¿Qué hace reverse_of do? ¿Qué SQL genera?

inverse_of girar la cabeza de manera inverse_of y no lo entiendo.

¿Cómo se ve el sql generado, si hay alguno?

¿ inverse_of opción inverse_of exhibe el mismo comportamiento si se usa con :has_many :belongs_to , y :has_many_and_belongs_to ?

Lo siento si esta es una pregunta tan básica.

Vi este ejemplo:

 class Player  :player end class Card  :cards end 

De la documentación , parece que la opción :inverse_of es un método para evitar consultas SQL, no generarlas. Es una sugerencia para que ActiveRecord use datos ya cargados en lugar de recuperarlos nuevamente a través de una relación.

Su ejemplo:

 class Dungeon < ActiveRecord::Base has_many :traps, :inverse_of => :dungeon has_one :evil_wizard, :inverse_of => :dungeon end class Trap < ActiveRecord::Base belongs_to :dungeon, :inverse_of => :traps end class EvilWizard < ActiveRecord::Base belongs_to :dungeon, :inverse_of => :evil_wizard end 

En este caso, si llama a dungeon.traps.first.dungeon debe devolver el objeto de dungeon original en lugar de cargar uno nuevo, como sería el caso de forma predeterminada.

Creo que :inverse_of es más útil cuando trabajas con asociaciones que aún no se han conservado. P.ej:

 class Project < ActiveRecord::Base has_many :tasks, :inverse_of=>:project end class Task < ActiveRecord::Base belongs_to :project, :inverse_of=>:tasks end 

Ahora, en la consola:

 irb> p = Project.new => # irb> t = p.tasks.build => # irb> t.project => # 

Sin los argumentos: reverse_of, t.project devolvería nil, porque desencadena una consulta sql y los datos aún no se almacenan. Con el argumento: reverse_of, los datos se recuperan de la memoria.

De la documentación de Rails 5.0 y excelente.

Guía

Asociaciones bidireccionales

Es normal que las asociaciones trabajen en dos direcciones, lo que requiere una statement sobre dos modelos diferentes:

 class Author < ApplicationRecord has_many :books end class Book < ApplicationRecord belongs_to :author end 

Por defecto, Active Record no sabe acerca de la conexión entre estas asociaciones. Esto puede llevar a que dos copias de un objeto no se sincronicen:

 a = Author.first b = a.books.first a.first_name == b.author.first_name # => true a.first_name = 'Manny' a.first_name == b.author.first_name # => false 

Esto sucede porque a y b.author son dos representaciones en memoria diferentes de los mismos datos, y ninguno se actualiza automáticamente de los cambios a la otra. Active Record proporciona la opción: inverse_of para que pueda informarle de estas relaciones:

 class Author < ApplicationRecord has_many :books, inverse_of: :author end class Book < ApplicationRecord belongs_to :author, inverse_of: :books end 

Con estos cambios, Active Record solo cargará una copia del objeto de autor, lo que evitará inconsistencias y hará que su aplicación sea más eficiente:

 a = Author.first b = a.books.first a.first_name == b.author.first_name # => true a.first_name = 'Manny' a.first_name == b.author.first_name # => true 

Hay algunas limitaciones para reverse_of support:

No trabajan con: a través de asociaciones. No funcionan con: asociaciones polimórficas. No trabajan con: como asociaciones.

Para las asociaciones belongs_to, las asociaciones inversas has_many se ignoran. Cada asociación intentará encontrar automáticamente la asociación inversa y establecer la opción: Inverse_of de manera heurística (en función del nombre de la asociación). La mayoría de las asociaciones con nombres estándar serán compatibles. Sin embargo, las asociaciones que contienen las siguientes opciones no tendrán sus inversos configurados automáticamente:

  • : condiciones
  • :mediante
  • :polimórfico
  • :clave externa

Solo una actualización para todos: acabamos de usar inverse_of con una de nuestras aplicaciones con has_many :through asociación


Básicamente hace que el objeto “origen” esté disponible para el objeto “niño”

Entonces, si estás usando el ejemplo de Rails:

 class Dungeon < ActiveRecord::Base has_many :traps, :inverse_of => :dungeon has_one :evil_wizard, :inverse_of => :dungeon end class Trap < ActiveRecord::Base belongs_to :dungeon, :inverse_of => :traps validates :id, :presence => { :message => "Dungeon ID Required", :unless => :draft? } private def draft? self.dungeon.draft end end class EvilWizard < ActiveRecord::Base belongs_to :dungeon, :inverse_of => :evil_wizard end 

El uso de :inverse_of le permitirá acceder al objeto de datos que es el inverso de, sin realizar más consultas SQL

Cuando tenemos 2 modelos con relaciones has_many y belongs_to, siempre es mejor usar reverse_of que informen a ActiveRecod que pertenecen al mismo lado de la asociación. Por lo tanto, si se activa una consulta desde un lado, se almacenará en caché y servirá desde el caché si se activa desde la dirección opuesta. Lo cual mejora en el rendimiento. Desde Rails 4.1, inverse_of se configurará automáticamente, si utilizamos foreign_key o cambiamos el nombre de clase, debemos establecerlo explícitamente.

Mejor artículo para detalles y ejemplo.

http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations

Si tiene una relación has_many_through entre dos modelos, Usuario y Función, y desea validar la Asignación del modelo de conexión con entradas no válidas o no válidas con validates_presence of :user_id, :role_id , es útil. Aún puede generar un User @user con su asociación @user.role(params[:role_id]) para que guardar al usuario no @user.role(params[:role_id]) resultado una validación fallida del modelo de Asignación.

Por favor, eche un vistazo a 2 dos recursos útiles

Y recuerda algunas limitaciones de inverse_of :

no funciona con: a través de asociaciones.

no funciona con: asociaciones polimórficas.

para las asociaciones belongs_to has_many se ignoran las asociaciones inversas.