在has_and_belongs_to_many关系中保存依赖对象的最佳方法?

时间:2011-05-27 10:12:40

标签: ruby-on-rails-3 activerecord has-and-belongs-to-many

您好我是rails的新手,我想知道在HBTM关系中保存依赖对象的最佳方式是什么。

具体来说,我有两个类Post和Tag

class Post < ActiveRecord::Base
  has_and_belongs_to_many :tags
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :posts
end

我有一个迁移来创建连接表

class AddPostsTagsJoinTable < ActiveRecord::Migration
  def self.up
     create_table :posts_tags, :id => false do |t|
        t.integer :post_id
        t.integer :tag_id
      end
  end

  def self.down
    drop_table :postss_tags
  end
end

一切都很顺利

所以我有一个PostsController,我可以从中处理帖子的创建,更新和删除,我想封装标签,以便通过PostsController创建...就像这样:

class PostsController < ApplicationController

  #... code removed for brevity

  def create
    @post  = current_user.posts.build(params[:post])
    if @post.save

      tag_names = params[:post][:tags].strip.split(' ')
      tag_names.each do |t|   

        #see if the tag already exists
        tag = Tag.find_by_name(t);
        if tag.nil?        
          @post.tags.create!(:name => t)
        else
          @post.tags << tag #just create the association
        end   

      end

      flash[:success] = "Post created."
      redirect_to(user_posts_path(current_user.username))
    else
      @user = current_user
      render 'new'
    end
  end

end

我不知道如何处理我的标签的创建,因为如果我只是打电话

@post.tags.create!(:name => t)

这将在Tags表中创建重复记录(即使在模型中指定了:uniq =&gt; true)。

为了避免重复,我看到标签是否已经存在,然后像这样添加

tag = Tag.find_by_name(t);
if tag.nil?        
  @post.tags.create!(:name => t)
else
  @post.tags << tag #just create the association
end   

这是应该做的吗?

这看起来很昂贵(特别是'因为它在循环中)所以我想知道是否有另一种“更清洁”的方法来做到这一点? (请忘记干活动等等)

是否有一种干净的方式来创建我的标签而无需手动检查重复项?

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

您可以通过在posts模型中添加accepts_nested_attributes_for来自动保存帖子的标签属性

class Post < ActiveRecord::Base
  has_and_belongs_to_many :tags
  accepts_nested_attributes_for :tags
end

下一步是在帖子表格中输出标签字段。