我正在使用rails编写博客引擎,并设置了一个标签模型和一个具有have_and_belongs_to_many关系的帖子模型。标记添加工作正常,在查找具有特定标记的所有帖子时会出现问题:
如果我将标签“test”添加到帖子A,然后将标签“test”添加到帖子B,则有两个标签对象,两者都具有名称“test”但具有不同的ID,两者都引用不同的帖子。现在,如果我有一个控制器动作indexTagPosts,它接受参数“tag”并查找带有该标签的所有帖子,它将只返回一个帖子,因为另一个标签具有不同的ID并且没有真正关联。我应该以某种方式限制添加新标签,还是应该操纵我以不同方式拉出所有相关标签的方式?
以下是控制器操作,它应该根据参数'tag'获取所有相关帖子:
def indexTagPosts
@tag = Tag.find(params[:tag])
@posts = @tag.posts.all
end
以下是保存标记的操作:
def create
@post = Post.find(params[:post_id])
@tag = @post.tags.create(params[:tag])
respond_to do |format|
if @tag.save
format.html { redirect_to edit_post_path(@post),:notice => "Success" }
end
end
end
提前致谢并对冗余或不良措辞道歉。
答案 0 :(得分:9)
我希望我知道每个人都有使用has_and_belongs_to_many
的想法,因为这是一个非常难以管理的事情,即使它在开始时看起来很简单。更好的方法是建立has_many ..., :through
类型关系,因为您可以轻松管理各个链接并向其添加元数据。
例如,这是一个简单的双向连接和一个中间模型,你会发现一个经常发生的模式:
class Post < ActiveRecord::Base
has_many :post_tags
has_many :tags, :through => :post_tags
end
class Tag < ActiveRecord::Base
has_many :post_tags
has_many :posts, :through => :post_tags
end
class PostTag < ActiveRecord::Base
belongs_to :post
belongs_to :tag
end
此时添加和删除标记链接很简单:
@post = Post.find(params[:post_id])
if (params[:tags].present?)
@post.tags = Tag.where(:name => params[:tags].split(/\s*,\s*/))
else
@post.tags = [ ]
end
has_many
关系管理器将根据需要创建,更新或销毁PostTag
关联模型。
通常,您会发展Post模型,以包含一个实用程序方法,用于使用您喜欢的任何分隔符检索和分配标记:
class Post
def tags_used
self.tags.collect(&:name).join(',')
end
def tags_used=(list)
self.tags = list.present? ? Tag.where(:name => list.split(/\s*,\s*/)) : [ ]
end
end