2

ととの 3 つのモデルがPoemあります。ユーザーは、任意の数の詩や歌に投票できます。SongUser

1 つの解決策は、2 つの関連付けモデルを作成PoemVoteし、SongVote

class PoemVote
  attr_accessible :poem_id, :user_id
  belongs_to :poem
  belongs_to :user
end

class SongVote
  attr_accessible :song_id, :user_id
  belongs_to :song
  belongs_to :user
end

私は電話をかけることができsome_poem_vote.poemますsome_song_vote.song

ただし、PoemVoteSongVoteは本質的に同じです。Vote単一のテーブル継承を使用して、1 つの親クラスから 2 つを拡張するにはどうすればよいですか?

私はこれらの線に沿って何かを考えています:

class Vote
  attr_accessible :resource_id, :user_id
end

class PoemVote < Vote
  ...not sure what goes here...
end

class SongVote < Vote
  ...not sure what goes here...
end

some_poem_vote.poemPoemVotes と SongVotes が 1 つのデータベース テーブルを共有できるようにするにはどうすればよいですか? または、私の問題に対するより良い解決策はありますか?

4

1 に答える 1

4

Rails では、STI は単純です。テーブルにtype文字列列を作成するだけvotesで、あとは Rails が処理します。適切な関連付けを作成するには、次のようなことができます。

class Vote
  attr_accessible :user, :votable
  belongs_to :user
  belongs_to :votable, polymorphic: true
end

votable_id...テーブルに aと avotable_type列を追加する必要がありvotesます。必ず追加してください

has_many :votes, as: :votable, class_name: 'PoemVote' # or 'SongVote'

関連するモデルで。ただし、このアプローチの問題は、用心深く、Vote投票を作成するために直接使用しないようにする必要があることです。そうしないと、間違ったタイプの投票が関連付けられることになります。これを強制するには、ハックの可能性があります:

class Vote
  attr_accessible :resource_id, :user_id

  def self.inherited( subclass )
    super( subclass )
    subclass.send :belongs_to, :votable,
                  class:  "#{subclass.name.gsub('Vote','')}"
  end
end

...しかし、継承によって引き起こされる多くの問題を解決する必要があるため(スコープの動作が奇妙で、一部のライブラリはSTIを適切に管理していないため)、コードホラーの扉を開くことは確かです(私は同じ問題に苦労しました)。など)。

問題は、性感染症が本当に必要かということです。投票が同じように動作する場合は、わざわざ STI を使用するのではなく、 polymorphicbelongs_toを使用するだけで、多くの頭痛の種から解放されます。

于 2012-12-02T10:00:49.597 に答える