Class: Plucky::CriteriaHash

Inherits:
Object show all
Defined in:
lib/plucky/criteria_hash.rb

Constant Summary collapse

SimpleIdQueryKeys =

Internal: Used to determine if criteria keys match simple id lookup.

[:_id].to_set
SimpleIdAndTypeQueryKeys =

Internal: Used to determine if criteria keys match simple id and type lookup (for single collection inheritance).

[:_id, :_type].to_set
SimpleQueryMaxSize =

Internal: Used to quickly check if it is possible that the criteria hash is simple.

[SimpleIdQueryKeys.size, SimpleIdAndTypeQueryKeys.size].max

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hash = {}, options = {}) ⇒ CriteriaHash

Public



26
27
28
29
# File 'lib/plucky/criteria_hash.rb', line 26

def initialize(hash={}, options={})
  @source, @options = {}, options
  hash.each { |key, value| self[key] = value }
end

Instance Attribute Details

#optionsObject (readonly)

Private: The Hash that stores options



12
13
14
# File 'lib/plucky/criteria_hash.rb', line 12

def options
  @options
end

#sourceObject (readonly)

Private: The Hash that stores query criteria



9
10
11
# File 'lib/plucky/criteria_hash.rb', line 9

def source
  @source
end

Instance Method Details

#==(other) ⇒ Object

Public



71
72
73
# File 'lib/plucky/criteria_hash.rb', line 71

def ==(other)
  @source == other.source
end

#[](key) ⇒ Object

Public



41
42
43
# File 'lib/plucky/criteria_hash.rb', line 41

def [](key)
  @source[key]
end

#[]=(key, value) ⇒ Object

Public The contents of this make me sad…need to clean it up



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/plucky/criteria_hash.rb', line 47

def []=(key, value)
  normalized_key = normalized_key(key)

  if key.is_a?(SymbolOperator)
    operator = :"$#{key.operator}"
    normalized_value = normalized_value(normalized_key, operator, value)
    @source[normalized_key] ||= {}
    @source[normalized_key][operator] = normalized_value
  else
    if key == :conditions
      value.each { |k, v| self[k] = v }
    else
      normalized_value = normalized_value(normalized_key, normalized_key, value)
      @source[normalized_key] = normalized_value
    end
  end
end

#array(value) ⇒ Object

Private: Array(BSON::ObjectId) returns the byte array or what not instead of the object id. This makes sure it is an array of object ids, not the guts of the object id.



130
131
132
# File 'lib/plucky/criteria_hash.rb', line 130

def array(value)
  value.is_a?(BSON::ObjectId) ? [value] : Array(value)
end

#initialize_copy(original) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/plucky/criteria_hash.rb', line 31

def initialize_copy(original)
  super
  @options = @options.dup
  @source  = @source.dup
  @source.each do |key, value|
    self[key] = value.clone if value.duplicable?
  end
end

#key_normalizerObject

Private



174
175
176
177
178
# File 'lib/plucky/criteria_hash.rb', line 174

def key_normalizer
  @key_normalizer ||= @options.fetch(:key_normalizer) {
    Normalizers::CriteriaHashKey.new
  }
end

#keysObject

Public



66
67
68
# File 'lib/plucky/criteria_hash.rb', line 66

def keys
  @source.keys
end

#merge(other) ⇒ Object

Public and completely disgusting



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/plucky/criteria_hash.rb', line 81

def merge(other)
  target = @source.dup
  other.source.each_key do |key|
    value, other_value = target[key], other[key]
    target[key] =
      if target.key?(key)
        value_is_hash = value.is_a?(Hash)
        other_is_hash = other_value.is_a?(Hash)

        if value_is_hash && other_is_hash
          value.update(other_value) do |key, old_value, new_value|
            if old_value.is_a?(Hash) && new_value.is_a?(Hash)
              self.class.new(old_value).merge(self.class.new(new_value)).to_hash
            else
              merge_values_into_array(old_value, new_value)
            end
          end
        elsif value_is_hash && !other_is_hash
          if modifier_key = value.keys.detect { |k| Plucky.modifier?(k) }
            current_value = value[modifier_key]
            value[modifier_key] = current_value.concat(array(other_value)).uniq
          else
            # kaboom! Array(value).concat(Array(other_value)).uniq
          end
        elsif other_is_hash && !value_is_hash
          if modifier_key = other_value.keys.detect { |k| Plucky.modifier?(k) }
            current_value = other_value[modifier_key]
            other_value[modifier_key] = current_value.concat(array(value)).uniq
          else
            # kaboom! Array(value).concat(Array(other_value)).uniq
          end
        else
          merge_values_into_array(value, other_value)
        end
      else
        other_value
      end
  end
  self.class.new(target)
end

#merge!(other) ⇒ Object

Public



135
136
137
138
139
140
# File 'lib/plucky/criteria_hash.rb', line 135

def merge!(other)
  merge(other).to_hash.each do |key, value|
    self[key] = value
  end
  self
end

#merge_values_into_array(value, other_value) ⇒ Object

Private



123
124
125
# File 'lib/plucky/criteria_hash.rb', line 123

def merge_values_into_array(value, other_value)
  array(value).concat(array(other_value)).uniq
end

#normalized_key(key) ⇒ Object

Private



169
170
171
# File 'lib/plucky/criteria_hash.rb', line 169

def normalized_key(key)
  key_normalizer.call(key)
end

#normalized_value(parent_key, key, value) ⇒ Object

Private



181
182
183
# File 'lib/plucky/criteria_hash.rb', line 181

def normalized_value(parent_key, key, value)
  value_normalizer.call(parent_key, key, value)
end

#object_id?(key) ⇒ Boolean

Returns:

  • (Boolean)


164
165
166
# File 'lib/plucky/criteria_hash.rb', line 164

def object_id?(key)
  object_ids.include?(key.to_sym)
end

#object_idsObject

Private



143
144
145
# File 'lib/plucky/criteria_hash.rb', line 143

def object_ids
  @options[:object_ids] ||= []
end

#object_ids=(value) ⇒ Object

Private

Raises:

  • (ArgumentError)


148
149
150
151
# File 'lib/plucky/criteria_hash.rb', line 148

def object_ids=(value)
  raise ArgumentError unless value.is_a?(Array)
  @options[:object_ids] = value.flatten
end

#simple?Boolean

Public: The definition of simple is querying by only _id or _id and _type. If this is the case, you can use IdentityMap in library to not perform query and instead just return from map.

Returns true or false

Returns:

  • (Boolean)


158
159
160
161
162
# File 'lib/plucky/criteria_hash.rb', line 158

def simple?
  return false if keys.size > SimpleQueryMaxSize
  key_set = keys.to_set
  key_set == SimpleIdQueryKeys || key_set == SimpleIdAndTypeQueryKeys
end

#to_hashObject

Public



76
77
78
# File 'lib/plucky/criteria_hash.rb', line 76

def to_hash
  @source
end

#value_normalizerObject

Private



186
187
188
189
190
# File 'lib/plucky/criteria_hash.rb', line 186

def value_normalizer
  @value_normalizer ||= @options.fetch(:value_normalizer) {
    Normalizers::CriteriaHashValue.new(self)
  }
end