web-dev-qa-db-fra.com

Que fait inverse_of? Quel code SQL génère-t-il?

J'essaie de comprendre inverse_of Et je ne comprends pas.

À quoi ressemble le SQL généré, le cas échéant?

L'option inverse_of Présente-t-elle le même comportement si elle est utilisée avec :has_many, :belongs_to Et :has_many_and_belongs_to?

Désolé si c'est une question aussi fondamentale.

J'ai vu cet exemple:

class Player < ActiveRecord::Base
  has_many :cards, :inverse_of => :player
end

class Card < ActiveRecord::Base
  belongs_to :player, :inverse_of => :cards
end
128
Federico

D'après la documentation , il semble que l'option :inverse_of Soit une méthode permettant d'éviter les requêtes SQL sans les générer. ActiveRecord suggère d'utiliser des données déjà chargées au lieu de les récupérer à nouveau via une relation.

Leur exemple:

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

Dans ce cas, l'appel de dungeon.traps.first.dungeon Devrait renvoyer l'objet dungeon d'origine au lieu d'en charger un nouvel, comme ce serait le cas par défaut.

114
tadman

Je pense :inverse_of est particulièrement utile lorsque vous travaillez avec des associations qui n'ont pas encore été conservées. Par exemple.:

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

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

Maintenant, dans la console:

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, ...>

Sans le :inverse_of arguments, t.project retournera nil, car il déclenche une requête SQL et les données ne sont pas encore stockées. Avec le :inverse_of arguments, les données sont extraites de la mémoire.

38
KenB

De la documentation de Rails 5.0 et super.

Guide

Associations bidirectionnelles

Il est normal que les associations travaillent dans deux directions, nécessitant une déclaration selon deux modèles différents:

class Author < ApplicationRecord
  has_many :books
end

class Book < ApplicationRecord
  belongs_to :author
end

Par défaut, Active Record ne connaît pas la connexion entre ces associations. Cela peut entraîner la désynchronisation de deux copies d'un objet:

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

Cela est dû au fait que a et b.author sont deux représentations différentes en mémoire des mêmes données et qu’aucune des deux n’est automatiquement actualisée à partir des modifications apportées à l’autre. Active Record fournit l'option: inverse_of pour que vous puissiez l'informer de ces relations:

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

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

Avec ces modifications, Active Record ne chargera qu'une copie de l'objet auteur, évitant les incohérences et rendant votre application plus efficace:

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

Le support de inverse_of comporte quelques limitations:

Ils ne travaillent pas avec: par le biais d'associations. Ils ne fonctionnent pas avec: les associations polymorphes. Ils ne travaillent pas avec: comme des associations.

Pour les associations d'appartements à, de nombreuses associations inverses sont ignorées. Chaque association essaiera de trouver automatiquement l'association inverse et de définir l'option: inverse_of de manière heuristique (en fonction du nom de l'association). La plupart des associations avec des noms standard seront supportées. Toutefois, les inverses des associations contenant les options suivantes ne seront pas définies automatiquement:

  • :conditions
  • :à travers
  • : polymorphe
  • :clé étrangère
13
artamonovdev

Juste une mise à jour pour tout le monde - nous venons d'utiliser inverse_of avec l'une de nos applications avec un has_many :through association


Fondamentalement, l'objet "Origin" est disponible pour l'objet "enfant"

Donc, si vous utilisez l'exemple 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

En utilisant :inverse_of vous permettra d'accéder à l'objet de données dont il est l'inverse, sans effectuer d'autres requêtes SQL

5
Richard Peck

Lorsque nous avons deux modèles avec une relation has_many et une relation Appartient à, il est toujours préférable d'utiliser inverse_of qui informe ActiveRecod qu'ils appartiennent au même côté de l'association. Ainsi, si une requête d'un côté est déclenchée, elle se mettra en cache et servira de cache si elle est déclenchée de la direction opposée. Ce qui améliore les performances. A partir de Rails 4.1, inverse_of sera défini automatiquement, si nous utilisons foreign_key ou si le nom de la classe est modifié, nous devons le définir explicitement.

Meilleur article pour plus de détails et exemple.

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

4
Gurudath BN
3
Samuel G. P.

Si vous avez une relation has_many_through Entre deux modèles, Utilisateur et Rôle, et que vous souhaitez valider l'affectation de modèle de connexion avec des entrées non existantes ou invalides avec validates_presence of :user_id, :role_id, Cela est utile. Vous pouvez toujours générer un utilisateur @ utilisateur avec son association @user.role(params[:role_id]) afin que l'enregistrement de l'utilisateur n'entraîne pas l'échec de la validation du modèle d'affectation.

3
Informatom