Module: IsTaggable
- Included in:
- RecurringTodo, Todo
- Defined in:
- lib/is_taggable.rb
Overview
These methods are adapted from has_many_polymorphs’ tagging_extensions
Class Method Summary collapse
Class Method Details
.included(klass) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/is_taggable.rb', line 3 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 to_a.map(&:name).sort.join(Tag::JOIN_DELIMITER) end def all_except_starred to_a.reject { |tag| tag.name == Todo::STARRED_TAG_NAME } end end def tag_list .reload .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 = .to_a.map(&:name) (list - current) (current - list) end self end def has_tag?(tag_name) return .any? { |tag| tag.name == tag_name } 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 (incoming) tag_cast_to_string(incoming).each do |tag_name| # added following check to prevent empty tags from being saved (which will fail) if tag_name.present? begin tag = user..where(:name => tag_name).first_or_create raise Tag::Error, "tag could not be saved: #{tag_name}" if tag.new_record? << 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 (outgoing) outgoing = tag_cast_to_string(outgoing) .destroy(*(user..select { |tag| outgoing.include? tag.name })) end def get_tag_name_from_item(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 item.name when String item else raise "Invalid type" end end def tag_cast_to_string(obj) tag_array_from_obj(obj).flatten.compact.map(&:downcase).uniq end def tag_array_from_obj(obj) case obj when Array obj.map! { |item| get_tag_name_from_item(item) } when String obj.split(Tag::DELIMITER).map { |tag_name| tag_name.strip.squeeze(" ") } else raise "Invalid object of class #{obj.class} as tagging method parameter" end end end end |