mirror of
https://github.com/TracksApp/tracks.git
synced 2026-03-03 03:20:15 +01:00
restore all associations for tags. All tests are passing
This commit is contained in:
parent
b2e34d4694
commit
b2e6253b4c
8 changed files with 107 additions and 41 deletions
91
lib/is_taggable.rb
Normal file
91
lib/is_taggable.rb
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# These methods are adapted from has_many_polymorphs' tagging_extensions
|
||||
|
||||
module IsTaggable
|
||||
|
||||
def self.included(klass)
|
||||
klass.class_eval do
|
||||
|
||||
# Add tags associations
|
||||
has_many :taggings, :as => :taggable
|
||||
has_many :tags, :through => :taggings do
|
||||
def to_s
|
||||
self.map(&:name).sort.join(Tag::JOIN_DELIMITER)
|
||||
end
|
||||
def all_except_starred
|
||||
self.reject{|tag| tag.name == Todo::STARRED_TAG_NAME}
|
||||
end
|
||||
end
|
||||
|
||||
def tag_list
|
||||
tags.reload
|
||||
tags.to_s
|
||||
end
|
||||
|
||||
def tag_list=(value)
|
||||
tag_with(value)
|
||||
end
|
||||
|
||||
# Replace the existing tags on <tt>self</tt>. Accepts a string of tagnames, an array of tagnames, or an array of Tags.
|
||||
def tag_with list
|
||||
list = tag_cast_to_string(list)
|
||||
|
||||
# Transactions may not be ideal for you here; be aware.
|
||||
Tag.transaction do
|
||||
current = tags.map(&:name)
|
||||
_add_tags(list - current)
|
||||
_remove_tags(current - list)
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
# Add tags to <tt>self</tt>. Accepts a string of tagnames, an array of tagnames, or an array of Tags.
|
||||
#
|
||||
# We need to avoid name conflicts with the built-in ActiveRecord association methods, thus the underscores.
|
||||
def _add_tags incoming
|
||||
tag_cast_to_string(incoming).each do |tag_name|
|
||||
# added following check to prevent empty tags from being saved (which will fail)
|
||||
unless tag_name.blank?
|
||||
begin
|
||||
tag = Tag.find_or_create_by_name(tag_name)
|
||||
raise Tag::Error, "tag could not be saved: #{tag_name}" if tag.new_record?
|
||||
tags << tag
|
||||
rescue ActiveRecord::StatementInvalid => e
|
||||
raise unless e.to_s =~ /duplicate/i
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Removes tags from <tt>self</tt>. Accepts a string of tagnames, an array of tagnames, or an array of Tags.
|
||||
def _remove_tags outgoing
|
||||
outgoing = tag_cast_to_string(outgoing)
|
||||
tags.delete(*(tags.select{|tag| outgoing.include? tag.name}))
|
||||
end
|
||||
|
||||
def tag_cast_to_string obj
|
||||
case obj
|
||||
when Array
|
||||
obj.map! do |item|
|
||||
case item
|
||||
# removed next line as it prevents using numbers as tags
|
||||
# when /^\d+$/, Fixnum then Tag.find(item).name # This will be slow if you use ids a lot.
|
||||
when Tag then item.name
|
||||
when String then item
|
||||
else
|
||||
raise "Invalid type"
|
||||
end
|
||||
end
|
||||
when String
|
||||
obj = obj.split(Tag::DELIMITER).map do |tag_name|
|
||||
tag_name.strip.squeeze(" ")
|
||||
end
|
||||
else
|
||||
raise "Invalid object of class #{obj.class} as tagging method parameter"
|
||||
end.flatten.compact.map(&:downcase).uniq
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue