İnverse_of ne yapıyor? Hangi SQL'i üretir?


143

Başımı döndürmeye çalışıyorum inverse_ofve anlamıyorum.

Oluşturulan sql, neye benziyor?

Does inverse_ofbirlikte kullanılırsa seçeneği aynı davranışı gösteren :has_many, :belongs_tove :has_many_and_belongs_to?

Bu çok basit bir soru ise özür dilerim.

Bu örneği gördüm:

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

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

Yanıtlar:


125

Gönderen belgelerine gibi görünüyor :inverse_ofseçenek bunları üreten değil, SQL sorguları kaçınmak için bir yöntemdir. ActiveRecord'un önceden yüklenmiş verileri bir ilişki yoluyla tekrar almak yerine kullanması için bir ipucu.

Onların örneği:

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

Bu durumda, çağrı varsayılan olarak olduğu gibi yeni bir nesne yüklemek yerine dungeon.traps.first.dungeonorijinal dungeonnesneyi döndürmelidir .


5
Belgelerdeki yorumu anlıyor musunuz: "belongs_to dernekleri için has_many ters dernekler göz ardı edilir.". Yine de doktor bu tam örneği kullanıyor. Burada ne eksik?
dynex

50
Bu benim için çok garip, çünkü bana göre bu davranışı her zaman varsayılan olarak isteyeceksiniz ve sadece ilişkilendirme adı çıkartılamadığında inverse_of kullanmanız gerekiyor. Ayrıca tanımdaki tutarsızlıklar rahatsız edicidir, ancak birkaç durumda bana yardımcı oldu. Sadece her yere yapışmamam için bir sebep var mı?
İbrahim

18
@Ibrahim Şuna bir bak, 23 gün önce birleştirildi! github.com/rails/rails/pull/9522
Hut8

6
Bir A girişinin alt kaydının alt öğesinin A kaydı olacağı garanti edilmediğinden, bir A ait ilişkinin tersinin göz ardı edilmesi mantıklıdır - A kaydının bir kardeşi olabilir. , A kaydı garantilidir.
David Aldridge

2
Gelecek okuyucu bu blogdan yardım alabilir ...: D
Arup Rakshit

42

Bence :inverse_of, henüz devam etmeyen dernekler ile çalışırken çok faydalıdır. Örneğin:

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

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

Şimdi, konsolda:

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

Bağımsız :inverse_ofdeğişkenler olmadan t.projectdönecektir nil, çünkü bir sql sorgusunu tetikler ve veriler henüz saklanmaz. Bağımsız :inverse_ofdeğişkenlerle veriler bellekten alınır.


1
Kabul etmeyi kabul etmem gereken bir sorun yaşadım. Varsayılan olarak, yalnızca ilişkilendirilmiş varolan nesneler için iç içe öznitelikler gösterilir (düzenleme eylemi). Örneğin, 3 ilişkili nesneye sahip bir nesne OLUŞTURMAK istiyorsanız, modellerinizde Model.new (yeni eylem) ve: inverse_of olmalıdır.
Victor Marconi

Rails 4 ve sonrasındaki davranışlar üzerinde anlaşmaya vardı, ancak v3'te gayet iyi çalıştı (eski sözdizimi v3.2.13'te tekrar çalışıyor olsa da, bazı daha sonraki enkarnasyonlar hariç). Ve birleştirme modelinde, kimliğin varlığını artık doğrulayamayacağına dikkat edin - sadece model nesnesi. Görünüşe göre v4 'mantık' içinde, kimliği olmayan bir ilişkilendirme olabilir.
JosephK

:inverse_ofAynı formda yeni ebeveyn ve çocuk varlıkları oluştururken benim için bir sorunu çözdüm .
WM

16

Bu pr'den sonra ( https://github.com/rails/rails/pull/9522 ) çoğu durumda ters_ve gerekli değildir.

Aktif Kayıt, standart adlara sahip çoğu ilişkilendirme için otomatik tanımlamayı destekler. Ancak, Aktif Kayıt, bir kapsam veya aşağıdaki seçeneklerden herhangi birini içeren çift yönlü ilişkileri otomatik olarak tanımlamaz:

  • :vasıtasıyla
  • :yabancı anahtar
class Author < ApplicationRecord
  has_many :books, inverse_of: 'writer'
end

class Book < ApplicationRecord
  belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
end

a = Author.first
b = a.books.first
a.first_name == b.writer.first_name # => true
a.first_name = 'David'
a.first_name == b.writer.first_name # => true

Yukarıdaki örnekte, aynı nesneye yapılan bir başvuru değişkente saklanır a ve özniteliktewriter .


Rails 5 kullanıyorum ve ya ekleyin inverse_ofya da eklemeyin , sonuç a.first_name == b.author.first_nameher zaman ture.
Arslan Ali

@ArslanAli harika yorum için teşekkürler, cevabı güncelledim.
artamonovdev

5

Yalnızca herkes için bir güncelleme - inverse_ofbir has_many :throughilişkilendirmeyle uygulamalarımızdan biriyle kullandık


Temel olarak "origin" nesnesini "child" nesnesi için kullanılabilir hale getirir

Raylar örneğini kullanıyorsanız:

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

Kullanmak :inverse_of, başka SQL sorguları gerçekleştirmeden tersi olan veri nesnesine erişmenizi sağlar


5

Has_many ve be__ ilişkisine sahip 2 modelimiz olduğunda, ActiveRecod'u ilişkilendirmenin aynı tarafına ait olduklarını bildiren inverse_of kullanmak her zaman daha iyidir. Dolayısıyla, bir taraftan bir sorgu tetiklenirse, ters yönden tetiklenirse önbellek ve önbellekten sunulur. Hangi performansı artırır. Rails 4.1'den, ters_of otomatik olarak ayarlanacaktır, foreign_key veya sınıf adında değişiklikler kullanırsak, açıkça ayarlamamız gerekir.

Ayrıntılar ve örnek için en iyi makale.

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



3

has_many_throughKullanıcı ve Rol arasındaki iki model arasında bir ilişkiniz varsa ve bağlanan model Atamasını mevcut olmayan veya geçersiz girişlerle doğrulamak istiyorsanız validates_presence of :user_id, :role_id, bu yararlıdır. Yine de ilişkisini içeren bir User @ kullanıcısı oluşturabilirsiniz, @user.role(params[:role_id])böylece kullanıcının kaydedilmesi Atama modelinin başarısız bir doğrulamasına neden olmaz.


-1

Lütfen bir göz atın 2 faydalı kaynak

Ve bazı sınırlamaları unutmayın inverse_of:

ile çalışmaz: dernekler aracılığıyla.

ile çalışmaz: polimorfik dernekler.

be have_man dernekleri için has_many ters dernekler yok sayılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.