Module: BitwiseAttribute::ActiveRecordMethods

Included in:
ClassMethods
Defined in:
lib/bitwise_attribute/active_record_methods.rb

Instance Method Summary collapse

Instance Method Details

#cleanup_keys(keys, mapping) ⇒ Object



71
72
73
74
75
76
77
# File 'lib/bitwise_attribute/active_record_methods.rb', line 71

def cleanup_keys(keys, mapping)
  return [] unless keys

  clean = keys.flatten.map(&:to_sym).compact.uniq

  clean & mapping.keys # only roles that we know about
end

#define_named_scopes(name, column_name, mapping) ⇒ Object



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
# File 'lib/bitwise_attribute/active_record_methods.rb', line 5

def define_named_scopes(name, column_name, mapping)
  define_singleton_method("with_#{name}") do |*keys|
    keys = cleanup_keys(keys, mapping)

    return [] unless keys&.any?

    records = where("#{column_name} & #{mapping[keys.first]} = #{mapping[keys.first]}")

    keys[1..-1].each do |key|
      records = records.where("#{column_name} & #{mapping[key]} = #{mapping[key]}")
    end

    records
  end

  define_singleton_method("with_any_#{name}") do |*keys|
    keys = cleanup_keys(keys, mapping)

    return where.not(column_name => nil) unless keys&.any?

    records = where("#{column_name} & #{mapping[keys.first]} = #{mapping[keys.first]}")

    keys[1..-1].each do |key|
      records = records.or(where("#{column_name} & #{mapping[key]} = #{mapping[key]}"))
    end

    records
  end

  define_singleton_method("with_exact_#{name}") do |*keys|
    keys = cleanup_keys(keys, mapping)

    return [] unless keys&.any?

    records = send("with_#{name}", keys)

    (mapping.keys - keys).each do |key|
      records = records.where("#{column_name} & #{mapping[key]} != #{mapping[key]}")
    end

    records
  end

  define_singleton_method("without_#{name}") do |*keys|
    keys = cleanup_keys(keys, mapping)

    return where(column_name => nil).or(where(column_name => 0)) unless keys&.any?

    records = where("#{column_name} & #{mapping[keys.first]} != #{mapping[keys.first]}")

    keys[1..-1].each do |key|
      records = records.where("#{column_name} & #{mapping[key]} != #{mapping[key]}")
    end

    records
  end

  # Defines a class method for each key of the mapping, returning records that have *at least*
  # the corresponding value.
  mapping.keys.each do |key|
    define_singleton_method(key) do
      send("with_#{name}", key)
    end
  end
end