我有一个标记模型:
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
应该在推入标签之前将其自身清空。但不知道如何编写代码。
答案 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。