Module: ConcernsOnRails::Models::Taggable

Extended by:
ActiveSupport::Concern
Defined in:
lib/concerns_on_rails/models/taggable.rb

Overview

Lightweight, dependency-free tagging over a single string column. Tags are stored delimiter-joined in one column — no join tables, no tagging engine — so it works on any database, including SQLite.

class Article < ApplicationRecord
include ConcernsOnRails::Taggable

taggable_by :tags                       # default column :tags
# taggable_by :skills, downcase: true   # custom column, case-folded
end

a = Article.new
a.tag_list = "Ruby, Rails, Ruby"          # accepts a String or an Array
a.tag_list                                 # => ["Ruby", "Rails"]  (stripped + de-duped)
a.add_tags("api"); a.remove_tags("Rails")
a.tagged_with?("ruby")                     # membership predicate
a.save!

Article.tagged_with("ruby", "rails")          # records carrying BOTH tags
Article.tagged_with("ruby", "go", any: true)  # records carrying ANY tag
Article.all_tags                               # sorted unique tags in use

Notes:

* Matching is boundary-safe ("rail" does not match "rails").
* A tag cannot contain the delimiter (default ",") — input containing
it is split into multiple tags on the spot (`add_tags("a,b")` adds
"a" and "b"), everywhere, so what you read back always matches what
a save would have produced.
* Reach for acts-as-taggable-on when you need tag contexts, ownership,
tag counts/clouds, or polymorphic tags shared across models.

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

LABEL =
"ConcernsOnRails::Models::Taggable".freeze
DEFAULT_FIELD =
:tags
DEFAULT_DELIMITER =
",".freeze

Instance Method Summary collapse

Instance Method Details

#add_tags(*names) ⇒ Object Also known as: add_tag



145
146
147
148
# File 'lib/concerns_on_rails/models/taggable.rb', line 145

def add_tags(*names)
  self.tag_list = tag_list + names.flatten
  tag_list
end

#remove_tags(*names) ⇒ Object Also known as: remove_tag



151
152
153
154
155
# File 'lib/concerns_on_rails/models/taggable.rb', line 151

def remove_tags(*names)
  drop = taggable_coerce(names.flatten)
  self.tag_list = tag_list.reject { |t| drop.include?(t) }
  tag_list
end

#tag_listObject

---- instance methods ----



136
137
138
# File 'lib/concerns_on_rails/models/taggable.rb', line 136

def tag_list
  self.class.taggable_split(self[self.class.taggable_field])
end

#tag_list=(value) ⇒ Object



140
141
142
143
# File 'lib/concerns_on_rails/models/taggable.rb', line 140

def tag_list=(value)
  tags = taggable_coerce(value)
  self[self.class.taggable_field] = tags.empty? ? nil : tags.join(self.class.taggable_delimiter)
end

#tagged_with?(tag) ⇒ Boolean Also known as: has_tag?

AND semantics for delimiter-containing input, mirroring the class-level tagged_with default: tagged_with?("a,b") is true when BOTH tags are set.

Returns:

  • (Boolean)


160
161
162
163
# File 'lib/concerns_on_rails/models/taggable.rb', line 160

def tagged_with?(tag)
  parts = self.class.taggable_split(tag.to_s)
  parts.any? && (parts - tag_list).empty?
end