[ruby-on-rails] inverse_of는 무엇을합니까? 어떤 SQL을 생성합니까?

나는 머리를 들으려고 노력하고 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



답변

에서 문서 등, 그것은 보인다 :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기본적으로 새 객체를로드하는 대신 원래 객체를 반환해야합니다 .


답변

: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인수, 데이터는 메모리에서 검색됩니다.


답변

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


답변

모든 사람을위한 업데이트 – 방금 연결 한 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 쿼리를 수행하지 않고도 그 반대의 데이터 객체에 액세스 할 수 있습니다


답변

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


답변


답변

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