从输入字段中删除标签时从这个`tag_names`属性中删除标签?

时间:2012-03-05 02:51:30

标签: ruby-on-rails

我有一个标记模型:

class Tag < ActiveRecord::Base
  has_many :taggings, :dependent => :destroy  
  has_many :posts, :through => :taggings
  has_many :subscriptions
  has_many :subscribed_users, :source => :user, :through => :subscriptions
end

发布模型:

class Post < ActiveRecord::Base
  attr_accessible :title, :content, :tag_names

  belongs_to :user

  has_many :taggings, :dependent => :destroy
  has_many :tags, :through => :taggings

  attr_writer :tag_names
  after_save :assign_tags

  def tag_names
    @tag_names || tags.map(&:name).join(' ')
  end

  private

  def assign_tags
    return if @tag_names.blank?
    @tag_names.split(" ").each do |name|
      tag = Tag.find_or_create_by_name(name)
      self.tags << tag unless tags.include?(tag)
    end
  end
end

assign_tags方法将保存的标记存储在:tag_names中,并以这种方式将其显示在输入字段中:tag1 tag2 tag3(值以空格分隔)。

视图/帖/ _form.html.erb:

  <div class="field">
    <%= f.label :tag_names %><br />  
    <%= f.autocomplete_field :tag_names, autocomplete_tag_name_posts_path, :"data-delimiter" => ' '%>
  </div>

正如您所见,assign_tags,我可以将标记添加/推送到tag_names。但是如果我从输入字段中删除一个标签并保存。标签仍会显示。

有什么建议可以帮我解决这个问题吗?

(也许tag_names应该在推入标签之前将其自身清空。但不知道如何编写代码。

1 个答案:

答案 0 :(得分:1)

在分配标签之前,您需要清除该项目的标签。 e.g。

def assign_tags
  self.tags = []
  return if @tag_names.blank?
  @tag_names.split(" ").each do |name|
    tag = Tag.find_or_create_by_name(name)
    self.tags << tag unless tags.include?(tag)
  end
end

更新

或者,这种方法会使数据库少一点:

def assign_tags
  ntags = []
  @tag_names.to_s.split(" ").each do |name|
    ntags << Tag.find_or_create_by_name(name)
  end
  self.tags = ntags
end

如果你想在无写可做的范例中变得非常疯狂,你可以这样做:

def assign_tags
  self.tags = @tag_names.to_s.split(" ").inject([]) do |arr, name|
    arr << Tag.find_or_create_by_name(name)
    arr
  end
end

或者,我建议您查看acts-as-taggable-on gem。