Class: Ransack::Nodes::Condition

Inherits:
Node
  • Object
show all
Defined in:
lib/ransack/nodes/condition.rb,
lib/ransack/adapters/mongoid/ransack/nodes/condition.rb,
lib/ransack/adapters/active_record/ransack/nodes/condition.rb

Instance Attribute Summary collapse

Attributes inherited from Node

#context

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Node

i18n_alias, i18n_word, #initialize, #translate

Constructor Details

This class inherits a constructor from Ransack::Nodes::Node

Instance Attribute Details

#predicateObject

Returns the value of attribute predicate


8
9
10
# File 'lib/ransack/nodes/condition.rb', line 8

def predicate
  @predicate
end

Class Method Details

.extract(context, key, values) ⇒ Object


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/ransack/nodes/condition.rb', line 11

def extract(context, key, values)
  attributes, predicate, combinator =
    extract_values_for_condition(key, context)

  if attributes.size > 0 && predicate
    condition = self.new(context)
    condition.build(
      :a => attributes,
      :p => predicate.name,
      :m => combinator,
      :v => predicate.wants_array ? Array(values) : [values]
    )
    # TODO: Figure out what to do with multiple types of attributes,
    # if anything. Tempted to go with "garbage in, garbage out" here.
    if predicate.validate(condition.values, condition.default_type)
      condition
    else
      nil
    end
  end
end

Instance Method Details

#arel_predicateObject


219
220
221
# File 'lib/ransack/nodes/condition.rb', line 219

def arel_predicate
  raise "not implemented"
end

#arel_predicate_for_attribute(attr) ⇒ Object


246
247
248
249
250
251
252
253
254
255
256
# File 'lib/ransack/nodes/condition.rb', line 246

def arel_predicate_for_attribute(attr)
  if predicate.arel_predicate === Proc
    values = casted_values_for_attribute(attr)
    unless predicate.wants_array
      values = values.first
    end
    predicate.arel_predicate.call(values)
  else
    predicate.arel_predicate
  end
end

#attributesObject Also known as: a


74
75
76
# File 'lib/ransack/nodes/condition.rb', line 74

def attributes
  @attributes ||= []
end

#attributes=(args) ⇒ Object Also known as: a=


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/ransack/nodes/condition.rb', line 79

def attributes=(args)
  case args
  when Array
    args.each do |name|
      build_attribute(name)
    end
  when Hash
    args.each do |index, attrs|
      build_attribute(attrs[:name], attrs[:ransacker_args])
    end
  else
    raise ArgumentError,
      "Invalid argument (#{args.class}) supplied to attributes="
  end
end

#build(params) ⇒ Object


173
174
175
176
177
178
179
180
181
# File 'lib/ransack/nodes/condition.rb', line 173

def build(params)
  params.with_indifferent_access.each do |key, value|
    if key.match(/^(a|v|p|m)$/)
      self.send("#{key}=", value)
    end
  end

  self
end

#build_attribute(name = nil, ransacker_args = []) ⇒ Object

build_attribute

This method was originally called from Nodes::Grouping#new_condition
only, without arguments, without #valid? checking, to build a new
grouping condition.

After refactoring in 235eae3, it is now called from 2 places:

1. Nodes::Condition#attributes=, with +name+ argument passed or +name+
   and +ransacker_args+. Attributes are included only if #valid?.

2. Nodes::Grouping#new_condition without arguments. In this case, the
   #valid? conditional needs to be bypassed, otherwise nothing is
   built. The `name.nil?` conditional below currently does this.

TODO: Add test coverage for this behavior and ensure that `name.nil?`
isn't fixing issue #701 by introducing untested regressions.

149
150
151
152
153
154
155
156
157
# File 'lib/ransack/nodes/condition.rb', line 149

def build_attribute(name = nil, ransacker_args = [])
  Attribute.new(@context, name, ransacker_args).tap do |attribute|
    @context.bind(attribute, attribute.name)
    self.attributes << attribute if name.nil? || attribute.valid?
    if predicate && !negative?
      @context.lock_association(attribute.parent)
    end
  end
end

#build_value(val = nil) ⇒ Object


159
160
161
162
163
# File 'lib/ransack/nodes/condition.rb', line 159

def build_value(val = nil)
  Value.new(@context, val).tap do |value|
    self.values << value
  end
end

#casted_values_for_attribute(attr) ⇒ Object


227
228
229
# File 'lib/ransack/nodes/condition.rb', line 227

def casted_values_for_attribute(attr)
  validated_values.map { |v| v.cast(predicate.type || attr.type) }
end

#combinatorObject Also known as: m


120
121
122
# File 'lib/ransack/nodes/condition.rb', line 120

def combinator
  @attributes.size > 1 ? @combinator : nil
end

#combinator=(val) ⇒ Object Also known as: m=


124
125
126
# File 'lib/ransack/nodes/condition.rb', line 124

def combinator=(val)
  @combinator = Constants::AND_OR.detect { |v| v == val.to_s } || nil
end

#default_typeObject


259
260
261
# File 'lib/ransack/nodes/condition.rb', line 259

def default_type
  predicate.type || (attributes.first && attributes.first.type)
end

#eql?(other) ⇒ Boolean Also known as: ==

Returns:

  • (Boolean)

192
193
194
195
196
197
198
# File 'lib/ransack/nodes/condition.rb', line 192

def eql?(other)
  self.class == other.class &&
  self.attributes == other.attributes &&
  self.predicate == other.predicate &&
  self.values == other.values &&
  self.combinator == other.combinator
end

#formatted_values_for_attribute(attr) ⇒ Object


231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/ransack/nodes/condition.rb', line 231

def formatted_values_for_attribute(attr)
  formatted = casted_values_for_attribute(attr).map do |val|
    if attr.ransacker && attr.ransacker.formatter
      val = attr.ransacker.formatter.call(val)
    end
    val = predicate.format(val)
    val
  end
  if predicate.wants_array
    formatted
  else
    formatted.first
  end
end

#hashObject


201
202
203
# File 'lib/ransack/nodes/condition.rb', line 201

def hash
  [attributes, predicate, values, combinator].hash
end

#inspectObject


263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/ransack/nodes/condition.rb', line 263

def inspect
  data = [
    ['attributes'.freeze, a.try(:map, &:name)],
    ['predicate'.freeze, p],
    [Constants::COMBINATOR, m],
    ['values'.freeze, v.try(:map, &:value)]
  ]
  .reject { |e| e[1].blank? }
  .map { |v| "#{v[0]}: #{v[1]}" }
  .join(', '.freeze)
  "Condition <#{data}>"
end

#keyObject


187
188
189
190
# File 'lib/ransack/nodes/condition.rb', line 187

def key
  @key ||= attributes.map(&:name).join("_#{combinator}_") +
    "_#{predicate.name}"
end

#negative?Boolean

Returns:

  • (Boolean)

276
277
278
# File 'lib/ransack/nodes/condition.rb', line 276

def negative?
  predicate.negative?
end

#persisted?Boolean

Returns:

  • (Boolean)

183
184
185
# File 'lib/ransack/nodes/condition.rb', line 183

def persisted?
  false
end

#predicate_nameObject Also known as: p


214
215
216
# File 'lib/ransack/nodes/condition.rb', line 214

def predicate_name
  predicate.name if predicate
end

#predicate_name=(name) ⇒ Object Also known as: p=


205
206
207
208
209
210
211
# File 'lib/ransack/nodes/condition.rb', line 205

def predicate_name=(name)
  self.predicate = Predicate.named(name)
  unless negative?
    attributes.each { |a| context.lock_association(a.parent) }
  end
  @predicate
end

#valid?Boolean

Returns:

  • (Boolean)

65
66
67
68
# File 'lib/ransack/nodes/condition.rb', line 65

def valid?
  attributes.detect(&:valid?) && predicate && valid_arity? &&
    predicate.validate(values, default_type) && valid_combinator?
end

#valid_arity?Boolean

Returns:

  • (Boolean)

70
71
72
# File 'lib/ransack/nodes/condition.rb', line 70

def valid_arity?
  values.size <= 1 || predicate.wants_array
end

#validated_valuesObject


223
224
225
# File 'lib/ransack/nodes/condition.rb', line 223

def validated_values
  values.select { |v| predicate.validator.call(v.value) }
end

#valueObject


165
166
167
168
169
170
171
# File 'lib/ransack/nodes/condition.rb', line 165

def value
  if predicate.wants_array
    values.map { |v| v.cast(default_type) }
  else
    values.first.cast(default_type)
  end
end

#valuesObject Also known as: v


96
97
98
# File 'lib/ransack/nodes/condition.rb', line 96

def values
  @values ||= []
end

#values=(args) ⇒ Object Also known as: v=


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/ransack/nodes/condition.rb', line 101

def values=(args)
  case args
  when Array
    args.each do |val|
      val = Value.new(@context, val)
      self.values << val
    end
  when Hash
    args.each do |index, attrs|
      val = Value.new(@context, attrs[:value])
      self.values << val
    end
  else
    raise ArgumentError,
      "Invalid argument (#{args.class}) supplied to values="
  end
end