rails active ruby-on-rails activerecord

ruby-on-rails - active record rails



¿Qué hace reverse_of do? ¿Qué SQL genera? (8)

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 < ActiveRecord::Base has_many :cards, :inverse_of => :player end class Card < ActiveRecord::Base belongs_to :player, :inverse_of => :cards end



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 => #<Project id: nil, name: nil, ...> irb> t = p.tasks.build => #<Task id: nil, project_id: nil, ...> irb> t.project => #<Project id: nil, name: nil, ...>

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.


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.

blog


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.


De la documentación de Rails 5.0 y excelente.

Guide

Asociaciones bidireccionales

Es normal que las asociaciones trabajen en dos direcciones, lo que requiere una declaración 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

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.


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.


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