问题见:
http://yuan.iteye.com/blog/575569#comments 2楼
下面是过程。
入口是tag_list=
grep 'def tag_list=' ./ -r
在vendor/plugins/acts_as_taggable_on_steroids/lib/acts_as_taggable.rb文件中。
定义在ActiveRecord::Acts:Taggable::InstanceMethods里。只有一行代码:
def tag_list=(value)
@tag_list = TagList.from(value)
end
接着找class TagList:
grep 'class TagList' ./ -r
位置:vendor/plugins/acts_as_taggable_on_steroids/lib/tag_list.rb
class << self
# Returns a new TagList using the given tag string.
#
# tag_list = TagList.from("One , Two, Three")
# tag_list # ["One", "Two", "Three"]
def from(source)
returning new do |tag_list|
case source
when Array
tag_list.add(source)
else
string = source.to_s.dup
# Parse the quoted tags
[
/\s*#{delimiter}\s*(['"])(.*?)\1\s*/,
/^\s*(['"])(.*?)\1\s*#{delimiter}?/
].each do |re|
string.gsub!(re) { tag_list << $2; "" }
end
tag_list.add(string.split(delimiter))#分隔符就在这处理了
end
end
end
end
add方法:
# Add tags to the tag_list. Duplicate or blank tags will be ignored.
#
# tag_list.add("Fun", "Happy")
#
# Use the <tt>:parse</tt> option to add an unparsed tag string.
#
# tag_list.add("Fun, Happy", :parse => true)
def add(*names)
extract_and_apply_options!(names)
concat(names)
clean!
self
end
嗯,原来add可以带个参数:parse=> false|true。
怎么没看到数据库操作……哦,对了,调用tag_list=的时候不保存的。应该是在save的时候。
Module ClassMethods
#................
after_create :save_tags
after_update :save_tags
#.............
end
Module InstanceMethods
#......
def save_tags
return unless @tag_list
new_tag_names = @tag_list - tags.map(&:name)
old_tags = tags.reject { |tag| @tag_list.include?(tag.name) }
self.class.transaction do
if old_tags.any?
taggings.find(:all, :conditions => ["tag_id IN (?)", old_tags.map(&:id)]).each(&:destroy)
taggings.reset
end
new_tag_names.each do |new_tag_name|
tags << Tag.find_or_create_with_like_by_name(new_tag_name)
end
end
true
end
#......
end
嗯,在transaction里边加点东西:
self.class.transaction do
if old_tags.any?
taggings.find(:all, :conditions => ["tag_id IN (?)", old_tags.map(&:id)]).each(&:destroy)
taggings.reset
Tag.clear_unused old_tags ####加这么一句
end
new_tag_names.each do |new_tag_name|
tags << Tag.find_or_create_with_like_by_name(new_tag_name)
end
end
然后找到Tag类,添加一个方法:
class Tag < ActiveRecord::Base
#......
class << self
#......
def clear_unused(tags=[])
if tags.empty?
find(:all).select{|tag| tag.taggings.empty?}.each(&:destroy)
else
find(:all, :conditions => ['id IN (?)', tags.map(&:id)]).select{|tag| tag.taggings.empty?}.each(&:destroy)
end
end
#......
end
#......
end
大功告成。
代码不知道还能改好看些不