1require 'active_support/concern' |
|
3module Taggable |
|
4 extend ActiveSupport::Concern |
|
6 included do |
|
7 validate :tags_exist |
|
8 end |
|
10 class_methods do |
|
|
11 def tagged_with_all(*tags) |
12 where(tags_column.contains(normalize_tags(tags)))
|
|
13 end |
|
14 alias_method :tagged_with, :tagged_with_all |
|
|
16 def tagged_with_any(*tags) |
17 where(tags_column.overlaps(normalize_tags(tags)))
|
|
18 end |
|
|
20 def tagged |
21 where(tags_column.not_eq([]))
|
|
22 end |
|
|
24 def untagged |
25 where(tags_column.eq([]))
|
|
26 end |
|
|
28 def tags_column |
29 arel_table[:tags] |
|
30 end |
|
32 def normalize_tags(tags) |
|
33 Array(tags).flatten.map(&:to_i).compact.reject(&:zero?) |
|
34 end |
|
35 end |
|
|
37 def normalize_tags(tags) |
38 self.class.normalize_tags(tags) |
|
39 end |
|
|
41 def tags=(tags) |
42 super(normalize_tags(tags)) |
|
43 end |
|
|
45 def tag_names |
46 Tag.where(id: tags).pluck(:name) |
|
47 end |
|
|
49 def tags_exist |
50 unless tags.all? { |tag| Tag.exists?(tag) } |
|
51 errors.add :tags, :invalid |
|
52 end |
|
53 end |
|
54end |