inverse_of는 무엇을합니까? 어떤 SQL을 생성합니까?


143

나는 머리를 들으려고 노력하고 inverse_of있고 그것을 얻지 못한다.

생성 된 SQL은 어떤 모습입니까?

않습니다 inverse_of와 함께 사용하는 경우 옵션은 같은 동작을 나타냅니다 :has_many, :belongs_to그리고 :has_many_and_belongs_to?

이것이 기본적인 질문이라면 죄송합니다.

이 예를 보았습니다.

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

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

답변:


125

에서 문서 등, 그것은 보인다 :inverse_of옵션을 생성하지, SQL 쿼리를 피하기위한 방법이다. 관계를 통해 데이터를 다시 가져 오는 대신 이미로드 된 데이터를 사용하는 것이 ActiveRecord에 대한 힌트입니다.

그들의 예 :

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

이 경우 호출 dungeon.traps.first.dungeondungeon기본적으로 새 객체를로드하는 대신 원래 객체를 반환해야합니다 .


5
문서의 주석을 이해하십니까 : "belongs_to 연관의 경우 has_many 역 연관은 무시됩니다.". 그러나 의사는 정확한 예를 사용합니다. 내가 여기서 무엇을 놓치고 있습니까?
dynex

50
이것은 기본적으로 항상이 동작을 원하고 연관 이름을 유추 할 수없는 경우 : inverse_of 만 사용해야하기 때문에 나에게는 매우 이상합니다. 또한 정의의 불일치가 귀찮지 만 몇 가지 경우에 도움이되었습니다. 내가 어디에나 붙이지 말아야 할 이유가 있습니까?
이브라힘

18
@Ibrahim 이것을 확인하십시오, 그것은 23 일 전에 합병되었습니다! github.com/rails/rails/pull/9522
Hut8

6
레코드 A의 부모 레코드의 하위 레코드 A가 레코드 A 일 수는 보장되지 않기 때문에 belongs_to 연관의 역은 무시되는 것이 합리적입니다. 그러나 레코드 A의 형제 일 수 있습니다. 기록 A를 보장합니다.
David Aldridge

2
미래 독자는이 블로그 에서 도움을받을 수 있습니다 ... : D
Arup Rakshit

42

:inverse_of아직 지속되지 않은 협회와 함께 일할 때 가장 유용 하다고 생각 합니다. 예 :

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

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

이제 콘솔에서 :

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

:inverse_of인수가 없으면 SQL 쿼리를 트리거하고 데이터가 아직 저장되지 않기 때문에을 t.project반환 nil합니다. 으로 :inverse_of인수, 데이터는 메모리에서 검색됩니다.


1
accepts_nested_attributes_for에 문제가있었습니다. 기본적으로 기존의 연관된 객체에 대해 중첩 된 속성 만 표시됩니다 (편집 작업). 예를 들어 3 개의 연결된 객체로 객체를 만들려면 모델에 Model.new (새 작업) 및 : inverse_of가 있어야합니다.
Victor Marconi

Rails 4 이상의 동작에 동의했지만 v3에서는 제대로 작동했습니다 (이전 구문은 v3.2.13에서 다시 작동하지만 이후의 구현은 제외). 그리고 join-model에서 ID의 존재 여부를 더 이상 확인할 수 없으며 모델 객체 만 확인하십시오. v4 'logic'에서 ID가없는 연결을 가질 수 있습니다.
JosephK

정확히 .. :inverse_of같은 형식으로 새 부모 및 자식 엔터티를 만들 때 문제가 해결되었습니다.
WM

16

이 pr 이후 ( https://github.com/rails/rails/pull/9522 ) 대부분의 경우 inverse_of 가 필요하지 않습니다.

Active Record는 표준 이름과의 대부분의 연관에 대해 자동 식별을 지원합니다. 그러나 Active Record는 범위 또는 다음 옵션 중 하나를 포함하는 양방향 연관을 자동으로 식별하지 않습니다.

  • :을 통하여
  • : 외국 _ 키
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

위의 예에서, 동일한 객체에 대한 참조는 변수 a및 속성에 저장됩니다 writer.


Rails 5를 사용하고 있으며 추가 inverse_of여부에 관계없이 결과 a.first_name == b.author.first_name는 항상 ture입니다.
Arslan Ali

@ArslanAli 좋은 의견 주셔서 감사합니다, 나는 대답을 업데이트했습니다.
artamonovdev

5

모든 사람을위한 업데이트 – 방금 연결 한 inverse_of앱 중 하나를 사용 했습니다.has_many :through


기본적으로 "원본"개체를 "자식"개체에서 사용할 수있게합니다.

따라서 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

를 사용 :inverse_of하면 더 이상의 SQL 쿼리를 수행하지 않고도 그 반대의 데이터 객체에 액세스 할 수 있습니다


5

has_many와 belongs_to 관계를 가진 2 개의 모델이있을 때, 항상 reverse_of를 사용하는 것이 좋습니다. 따라서 한쪽의 쿼리가 트리거되면 반대 방향에서 트리거되면 캐시에서 캐시하고 서비스를 제공합니다. 성능이 향상됩니다. Rails 4.1부터는 inverse_of가 자동으로 설정됩니다. foreign_key를 사용하거나 클래스 이름을 변경하면 명시 적으로 설정해야합니다.

자세한 내용과 예를위한 최고의 기사.

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



3

has_many_through사용자와 역할의 두 모델 사이 에 관계 가 있고로 존재하거나 유효하지 않은 항목에 대해 연결 모델 할당의 유효성을 검사하려는 validates_presence of :user_id, :role_id경우 유용합니다. 사용자 @user.role(params[:role_id])를 저장해도 할당 모델의 유효성 검사에 실패하지 않도록 연관을 가진 User @user를 계속 생성 할 수 있습니다 .


-1

2 가지 유용한 자료를 살펴보십시오.

그리고 몇 가지 제한 사항을 기억하십시오 inverse_of.

연결을 통해 작동하지 않습니다.

: 다형성 연관에서는 작동하지 않습니다.

belongs_to 연관들에 대해서는 has_many 역 연관들은 무시된다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.