7

Person、Position、および Directory の 3 つのクラスがあります。

  • Person has_many :directories, :through => :position.
  • ディレクトリ has_many :people, :through => :position.
  • Person と Directory の両方に has_many :positions があります。
  • Position モデルには、id、person_id、および directory_id に加えて、1 つ以上の追加フィールド (たとえば、タイトル) があります。

私ができるようにしたいのは、Directory.people コレクションに人物を追加するたびに、タイトル フィールドなどのデータを結合モデルに追加することです。通常の << 演算子では切り捨てられません。推定値:

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
directory.people << person

これにより、Directory オブジェクトの人物コレクションに人物が追加されますが、結合モデルにデータを割り当てる機会はありません。そのため、このサイトで多くの調査を行った後、Person コレクションに Person を追加し、Person と Directory id est をリンクする Position にデータを追加する別の方法を見つけました。

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
position = person.positions.build(:directory_id => directory.id, :title => "Administrative Assistant") 
position.save

これは面倒です。同様に面倒な方法は次のとおりです。

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
position = Position.new(directory_id: directory.id, person_id: person.id, title: "Administrative Assistant")

繰り返しますが、私は Person と Directory の関係を強調したいので、間違っているようです。

私ができるようにしたいのは、 << 演算子を使用して、追加のデータを渡すだけです。

directory = Directory.last # Let's assume that retrieves a Directory object
person = Person.last # Let's assume that retrieves a Person object
directory.people << person, :position => {:title => "Administrative Assistant"}

次のように、 has_many :through 宣言で << 演算子をオーバーロードしました。

has_many :people, :through => :positions do
  def << *args
    arg = args.first
    if arg.is_a?(Person)
      self.push([arg]) 
    elsif arg.is_a?(Hash)
      # Don't know what to do in here (see below)
    else
      raise "Invalid Value" # There's a better error to raise here, but good enough for now.
    end
  end
end

これを機能させる利点は、構文的にうまく機能し、Directory オブジェクトの people コレクションに Person を追加しながら、結合オブジェクト (Position) にデータを簡潔に割り当てることができることです。

しかし、Position を作成してデータベースに保存するには、 << 演算子の左側にある people コレクションが属性である Directory オブジェクトにアクセスできる必要があるため、それを機能させることはできません。

だから、私の質問は次のとおりです。

  1. オブジェクトの属性からオブジェクトにアクセスする方法はありますか?
  2. 別の方法として、1 つのオブジェクトをコレクションに追加するときに結合モデルにデータを簡単に割り当てることができるように、 << 演算子をオーバーロードする別の方法はありますか?

あなたの助けと思慮深い回答に感謝します。私はこれを半日無駄にハッキングしてきました。

回答 この質問に答えてくれた PinnyM のおかげで、この実装を思いつくことができました。

module AddToPeopleAndPositionExtension
  def << *args
    arg = args.first
      if arg.is_a?(Person)
        self.push([arg]) 
        return self
      elsif arg.is_a?(Hash)
        directory = proxy_association.owner
        person = arg[:person]
        position = person.positions.build(:directory_id => directory.id, :title => arg[:position][:title]) 
        position.save
      else
        raise "Invalid Value"
      end
  end
end

class Directory < ActiveRecord::Base  
  # Relationships
  has_many :positions
  has_many :people, :through => :positions, :extend => AddToPeopleAndPositionExtension
end

これにより、次のように、結合モデルで何が起こるかを気にしなければ、標準的な方法で << 演算子を呼び出すことができました。

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
directory.people << person

また、次のような結合モデルの属性を指定する方法で呼び出すこともできます。

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
directory.people << {:person => person, :position => {:title => "Administrative Assistant"}}
4

1 に答える 1

11

proxy_associationブロック内のヘルパーを使用して、関連付けproxy_association.ownerを取得し、Directoryオブジェクト自体を取得できます。詳細については、こちらをご覧ください。

于 2012-10-11T19:28:22.750 に答える