4

アソシエーションを効果的に使用する「レールの方法」をどのように行うべきかについて、私は完全に混乱しています。

Rails 4 アプリのモデル構成の例を次に示します。

class Film < ActiveRecord::Base
  # A movie, documentary, animated short, etc
  has_many :roleships
  has_many :participants, :through => :roleships
  has_many :roles, :through => :roleships
  # has_many :writers........ ?
end

class Participant < ActiveRecord::Base
  # A human involved in making a movie
  has_many :roleships
end

class Role < ActiveRecord::Base
  # A person's role in a film. i.e. "Writer", "Actor", "Extra" etc
  has_many :roleships
end

class Roleship < ActiveRecord::Base
  # The join for connecting different people
  # to the different roles they have had in
  # different films
  belongs_to :participant
  belongs_to :film
  belongs_to :role
end

上記のモデル構成を考えると、私が望んでいたコードは、作家を映画に直接追加し、最終的に結合を正しく設定できるようにすることを望みます。

たとえば、次のようなことができるようになりたいと思います。

## The Code I WISH I Had
Film.create!(name: "Some film", writers: [Participant.first])

これが完全に間違っていると考えているかどうかはわかりませんが、それは不可能に思えます。これを達成する正しい方法は何ですか?ネストされたリソース? カスタム セッター + スコープ? 他の何か?仮想属性?ありがとう!

4

2 に答える 2

3

あなたの質問に基づいてサンプルアプリを作成しました。 https://github.com/szines/hodor_filmdb

Participant と Role Model で関連付けを設定すると便利だと思いますが、これがなくても機能します。このデータベースを後でどのように使用するかによって異なります。このクエリを使用しないと機能しません。Participant.find(1).films

class Participant < ActiveRecord::Base
  has_many :roleships
  has_many :films, through: :roleships
end

class Role < ActiveRecord::Base
  has_many :roleships
  has_many :films, through: :roleships
end

film_controller.rb で追加のフィールド (strong_parameters) を許可することを忘れないでください。

def film_params
  params.require(:film).permit(:title, :participant_ids, :role_ids)
end

奇妙なことに、参加者と役割で新しい映画を作成すると、結合テーブルに 2 つのレコードが作成されます。

アップデート:

モデルに一種の仮想属性を作成できます。例えば:

def writers=(participant)
  @writer_role = Role.find(1)
  self.roles << @writer_role
  self.participants << participant
end

そして、あなたは使用することができます:Film.create(title: 'The Movie', writers: [Participant.first])

于 2013-06-13T07:35:27.267 に答える
0

映画と参加者の間に通常の関係があった場合はhas_and_belongs_to_many、例と一緒に映画を作成できます。

参加モデルがより複雑になるため、ロールシップを個別に構築する必要があります。

writer= Roleship.create(
          participant: Participant.find_by_name('Spielberg'),
          role: Role.find_by_name('Director')
        )
main_actor= Roleship.create(
          participant: Participant.find_by_name('Willis'),
          role: Role.find_by_name('Actor')
        )

Film.create!(name: "Some film", roleships: [writer, main_actor])

そのためには、ロールシップと映画を構築するために使用するすべての属性を一括割り当て可能にする必要があるため、Rails 3.2 では次のように記述する必要があります。

class Roleship < ActiveRecord::Base
   attr_accessible :participant, :role
   ...
end

class Film < ActiveRecord::Base
   attr_accessible :name, :roleships
   ...
end

roleship_ids を使用する場合は、次のように記述する必要があります。

class Film < ActiveRecord::Base
   attr_accessible :name, :roleship_ids
   ...
end

補遺:

もちろん、セッターメソッドを書くことができます

class Film ...

  def writers=(part_ids)
     writer_role=Role.find_by_name('Writer')
     # skiped code to delete existing writers
     part_ids.each do |part_id|
        self.roleships << Roleship.new(role: writer_role, participant_id: part_id)
     end
  end
end

しかし、それはあなたのコードをあなたのDBのデータ( table の内容)に依存させますroles。これは悪い考えです。

于 2013-06-12T23:25:35.803 に答える