1

我一直在试图弄清楚如何将我的模型与我一直在从事的项目相关联,并且我之前曾多次来这里寻求帮助,但我从未得到令人满意的答案。我有两个模型:帖子和图像。每个帖子都附有几张图片,并且帖子可以共享图片,因此 HABTM 关系对此很有意义,如下所示:

class Post < ActiveRecord::Base
  has_and_belongs_to_many :images
end

class Image < ActiveRecord::Base
  has_and_belongs_to_many :posts
end

现在的问题是我希望每个帖子都有一个“特色图片”。我该怎么做呢?想到的第一个想法是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]))

所以向我建议的下一个想法是第二个 HABTM 关系,如下所示:has_and_belongs_to_many :featured_images. 这有一个明显的问题,它是复数形式。我尝试unique: true在迁移中添加 post_id 列,但这无济于事,因为我一直不得不在我的代码中这样做:post.featured_images.first这可能非常令人沮丧。

has_many :posts, through: :attachment我尝试的最后一个想法是has_one :featured_posts, through: :attachment代替原始的 HABTM,但这些似乎不必要地麻烦,并且 rails 似乎不想让我以这种方式动态分配图像Post.new(:featured_image => Image.find(params[:image_id]))

有什么好的方法可以做到这一点吗?我在之前的尝试中做错了什么吗?这不应该只是 post 表上的一个简单外键吗?为什么一定要这么难?

4

2 回答 2

1

我喜欢你的第二个想法就好了。完整的方法是使用事务模型,例如 @depa 建议的。当您想要存储其他属性时,事务模型非常有用,例如图像何时为给定帖子提供特色(可能也不是)。但是,无论您是否也构建了该事务对象,您都可以将特色图像缓存在 post 对象上以便快速访问。尝试这样做:

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_id由于没有Post 模型,您之前可能没有成功。和/或因为您使用了错误的属性名称。(它应该是Post.new(featured_image_id: Image.find(params[:image_id]))。)无论哪种方式,最好让代码比所有这些都更面向对象。我在上面列出的方式,您不必考虑数据库中的列名,而只需考虑您正在处理的对象。即,只需将 Image 分配给 Post 的 feature_image 参考。记住这一点,我宁愿尽可能不设置外键attr_accessible

于 2013-09-01T23:27:36.950 回答
0

您可以使用 has_one :through 关联来做您想做的事。

class Post < ActiveRecord::Base
  has_and_belongs_to_many :images
  has_one                 :featured_image, 
                          :through => :feature,
                          :class_name => 'Image'
  has_one                 :feature
end

class Image < ActiveRecord::Base
  has_and_belongs_to_many :images
  has_many                :featured_images,
                          :through => :features,
                          :class_name => 'Image',
                          :foreign_key => :featured_image_id
  has_many                :features
end

class Feature < ActiveRecord::Base
  belongs_to              :featured_image,
                          :class_name => 'Image'
  belongs_to              :post
end
于 2013-09-01T22:59:28.420 回答