改个bug

问题见:[url]http://yuan.iteye.com/blog/575569#comments[/url] 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 :parse 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

大功告成。
代码不知道还能改好看些不 :oops:

你可能感兴趣的:(Rails2)