1

しばらく取り組んできたプロジェクトに自分のモデルを関連付ける方法を見つけようとしており、以前に数回助けを求めてここに来ましたが、満足のいく答えは得られませんでした. Post と Image の 2 つのモデルがあります。すべての投稿には複数の画像が添付されており、投稿は画像を共有できるため、次のように HABTM 関係が理にかなっています。

class Post < ActiveRecord::Base
  has_and_belongs_to_many :images
end

class Image < ActiveRecord::Base
  has_and_belongs_to_many :posts
end

ここでの問題は、各投稿に 1 つの「注目の画像」を含めることです。どうすればいいですか?頭に浮かぶ最初の考えはhas_one :featured_image、投稿とbelongs_to :post_featured_on画像に関する単純なことですが、それの問題は、同じ画像が複数の投稿で取り上げられる可能性があることです.

そこで私が思いついた次のアイデアはbelongs_to :featured_image、投稿とhas_many :posts_featured_on画像の関係を逆にすることです。それに関する問題は、それがあまりセマンティックではなく、Rails が、コントローラーで次のように、フォームから投稿の注目の画像を設定できるようにしたくないように見えることです。Post.new(:featured_image => Image.find(params[:image_id]))

そこで私に提案された次のアイデアは、次のような 2 番目の HABTM 関係でしたhas_and_belongs_to_many :featured_images。これには明らかな問題があります。複数形です。移行で post_id 列を追加しようとunique: trueしましたが、コード内でこれを実行しなければならないという事実が改善されませんでしたpost.featured_images.first。これは非常にイライラする可能性があります。

私が最後に試したアイデアは、元の HABTM の代わりにhas_many :posts, through: :attachmentandを使用することでしたhas_one :featured_posts, through: :attachmentが、これらは不必要に面倒なようで、Rails は のようにその場で画像を割り当てることを望んでいないようですPost.new(:featured_image => Image.find(params[:image_id]))

これを行う良い方法はありますか?以前の試行で何か間違ったことをしましたか? これは、post テーブルの単純な外部キーであってはなりませんか? なぜそんなに難しくなければならないのですか?

4

2 に答える 2

1

私はあなたの2番目のアイデアが好きです。本格的なアプローチは、@depa が提案したようなトランザクション モデルを使用することです。トランザクション モデルは、特定の投稿で画像が取り上げられたとき (およびおそらくそうでないとき) など、追加の属性を保存する場合に最適です。ただし、そのトランザクション オブジェクトを作成するかどうかに関係なく、注目の画像を投稿オブジェクトにキャッシュしてすばやくアクセスできます。これをやってみてください:

class Post < ActiveRecord::Base
  has_and_belongs_to_many :images
  belongs_to :featured_image, class_name: 'Image'
end

class Image < ActiveRecord::Base
  has_and_belongs_to_many :posts
  # Purposefully not defining an inverse relationship back to Post.
  # You can if you need or want it but you may not.
end

次に、コントローラーでお勧めします。

@post = Post.find_by_id(params[:id])
@post.featured_image = Image.find(params[:image_id])
@post.save

attr_accessible :featured_image_idPost モデルを使用していなかったため、以前はこれで成功しなかった可能性があります。および/または間違った属性名を使用していたためです。(だったはずPost.new(featured_image_id: Image.find(params[:image_id]))です。) いずれにせよ、コードをもう少しオブジェクト指向にしておくのは良いことです。上で説明したように、データベース内の列名について考える必要はなく、扱っているオブジェクトについて考えるだけで済みます。つまり、Image を Post の feature_image 参照に割り当てるだけです。これを念頭に置いて、attr_accessible可能な限り外部キーを設定しないことを好みます。

于 2013-09-01T23:27:36.950 に答える