Module: HasArrayScopes::Taggable::ClassMethod

Defined in:
lib/has_array_scopes/taggable.rb

Instance Method Summary collapse

Instance Method Details

#has_array_scopes(tag_name) ⇒ Object



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
# File 'lib/has_array_scopes/taggable.rb', line 17

def has_array_scopes(tag_name, *)
  quoted_tag = connection.quote_column_name(tag_name)
  quoted_table = connection.quote_table_name(table_name)
  tag_array_type_fetcher = lambda {
    col_type = columns_hash[tag_name.to_s]&.type
    TYPE_MATCHER.fetch(col_type) do
      raise ArgumentError, "Unsupported column type #{col_type.inspect} for has_array_scopes :#{tag_name}"
    end
  }
  parser = HasArrayScopes::Parser.new

  scope :"with_any_#{tag_name}", ->(tags) { where("#{quoted_table}.#{quoted_tag} && ARRAY[?]::#{tag_array_type_fetcher.call}[]", parser.parse(tags)) }
  scope :"with_all_#{tag_name}", ->(tags) { where("#{quoted_table}.#{quoted_tag} @> ARRAY[?]::#{tag_array_type_fetcher.call}[]", parser.parse(tags)) }
  scope :"without_any_#{tag_name}", ->(tags) { where.not("#{quoted_table}.#{quoted_tag} && ARRAY[?]::#{tag_array_type_fetcher.call}[]", parser.parse(tags)) }
  scope :"without_all_#{tag_name}", ->(tags) { where.not("#{quoted_table}.#{quoted_tag} @> ARRAY[?]::#{tag_array_type_fetcher.call}[]", parser.parse(tags)) }

  define_singleton_method :"all_#{tag_name}" do |options = {}, &block|
    subquery_scope = unscoped.select("unnest(#{quoted_table}.#{quoted_tag}) as tag").order(1).distinct
    subquery_scope = subquery_scope.instance_eval(&block) if block
    unscope(:where).from(subquery_scope).pluck("tag")
  end

  define_singleton_method :"#{tag_name}_cloud" do |options = {}, &block|
    subquery_scope = unscoped.select("unnest(#{quoted_table}.#{quoted_tag}) as tag")
    subquery_scope = subquery_scope.instance_eval(&block) if block
    unscope(:where).from(subquery_scope).group("tag").order("tag").pluck(Arel.sql("tag, count(*) as count"))
  end
end