2013-08-28 48 views
0

我有一个类似于博客的rails项目,这个博客的帖子有一组图片和一个精选图片。该图像集是一个非常直接的HABTM关系,因为几个帖子可以共享相同的图像,一个帖子可以有很多图像,但特色图像更麻烦一些。做has_one和belongs_to_many的最佳途径?

每一个岗位应该有一个且只有一个功能的图像和一个图像可以在几个职位的特色形象,所以我首先想到的是刚刚扭转的关系,并让图像has_many职位和belong_to图像,但似乎有问题以很多不同的方式。首先,它不是很有意义。其次,后控制器需要额外的代码来接受image_id的值,因为Post.new似乎不想接受image_id作为属性。

我的第二个想法 - 并且这是一个我这么会far--是使用上都有了HABTM关系与limit: 1符对这篇文章的has_and_belongs_to_many :featured_images和在迁移上t.belongs_to :post一个unique: true。这个解决方案的工作原理,但它似乎是黑客。此外,这意味着我必须访问像post.featured_images.first这样的精选图片而不是post.featured_image。更糟糕的是,我不禁想到这会损害数据库性能,因为它必须访问三个表而不是两个表,并且它必须在多对多表中搜索帖子ID,而不是通过ID来直接识别柱。

所以,这是正确的方式来做到这一点或有更好的?铁轨是否有类似has_onebelongs_to_many的关系?

回答

1

因为这是你有一个“拥有属于一对多”的关系的情况下,但你想存储额外的信息关于本身的关系(事实上图像是“特色”的职位),我会尝试一个has_many :through排列。类似这样的:

class Post < ActiveRecord::Base 
    has_many :post_images, inverse_of: :post 
    has_many :images, through: :post_images 
    has_one :featured_post_image, class_name: PostImage, 
    inverse_of: :post, conditions: { is_featured: true } 
    has_one :featured_image, through: :featured_post_image 

    accepts_nested_attributes_for :post_images, allow_destroy: true 
    attr_accessible :post_images_attributes 
end 

class PostImage < ActiveRecord::Base 
    belongs_to :post 
    belongs_to :image 

    attr_accessible :image_id 
end 

class Image < ActiveRecord::Base 
    has_many :post_images 
    has_many :posts, through: :post_images 
end 

不幸的是,添加验证以确保帖子永远不会拥有多个精选图像比看起来更复杂。您可以在Post上进行验证,但如果您的应用的某些其他部分直接创建PostImages而不触及其关联的帖子,那么这不会节省您的时间。如果其他读者对这个问题有一些了解,我很乐意听到它。

3

为什么不尝试类似的东西(不HABTM,刚刚的has_many):

class Image < ActiveRecord::Base 
    belongs_to :post 
    attr_accessible :featured 

    after_commit :reset_featured, if: :persisted? 

    protected 
    # garant that featured will be only one 
    def reset_featured 
    Image.where('id <> ?', self.id).update_all(featured: false) if self.featured 
    end 
end 

class Post < ActiveRecord::Base 
    has_many :images, conditions: { featured: false } 
    has_one :featured_image, class_name: 'Image', conditions: { featured: true } 
end 
+0

这看起来不错,但如何区分帖子分享图像?说A后有图像A,B和C,后B有图像A,B。A是后A的精选图像,B是后B的精选图像?图像将如何记录它们的特色,或者,这些帖子将如何确定哪些特色帖子是他们的? –

+0

就我而言,一张图片属于一个帖子,不能属于另一张图片。 –