Module: LcpRuby::Widgets::ScopeApplicator

Included in:
DataResolver, PresenterZoneResolver, RecordSourceResolver
Defined in:
lib/lcp_ruby/widgets/scope_applicator.rb

Class Method Summary collapse

Class Method Details

.apply_date_range_filter(scope, model_class, field, value) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/lcp_ruby/widgets/scope_applicator.rb', line 168

def apply_date_range_filter(scope, model_class, field, value)
  return scope unless value.is_a?(Hash)
  return scope unless model_class.column_names.include?(field.to_s)

  from_date = value["from"] || value[:from]
  to_date   = value["to"]   || value[:to]
  if from_date && to_date
    scope.where(field => from_date..to_date)
  elsif from_date
    scope.where(model_class.arel_table[field].gteq(from_date))
  elsif to_date
    scope.where(model_class.arel_table[field].lteq(to_date))
  else
    scope
  end
end

.apply_filter_form(scope, model_class, filter_form) ⇒ Object

Applies a ‘Pages::FilterForm` to an AR scope. Reads typed AM::Attributes from the synthetic VirtualForm instance. Used by the dashboard + index-composite controllers. Spec § 5 step 13.

Dispatch by input_type:

* association_select / select / multi_select →
  `where(field => value)` if column exists, else
  `filter_<field>(scope, value)` host hook if defined.
* date_range → from/to via `arel_table[field].gteq/lteq`.
* Empty arrays are no-ops (never `WHERE field IN ()`).


92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/lcp_ruby/widgets/scope_applicator.rb', line 92

def apply_filter_form(scope, model_class, filter_form)
  return scope unless filter_form&.any?

  filter_form.each_field do |vfield|
    value = resolve_filter_value(filter_form, vfield)
    next if blank_filter_value?(value)

    scope = dispatch_filter_value(scope, model_class, vfield, value)
  end

  scope
end

.apply_scope_filters(scope, model_class, scope_filter_set) ⇒ Object

Applies a ‘Pages::ScopeFilterSet` to an AR scope. For each declared scope_filter the selected value is a scope name; if the model class responds_to the scope, dispatch via public_send. ScopeFilterSet’s enumerator already filtered out attacker values, so we trust the input here.



128
129
130
131
132
133
134
135
136
137
# File 'lib/lcp_ruby/widgets/scope_applicator.rb', line 128

def apply_scope_filters(scope, model_class, scope_filter_set)
  return scope unless scope_filter_set&.any?

  scope_filter_set.each do |_name, scope_key, _definition|
    next if scope_key.blank?
    scope = scope.public_send(scope_key) if model_class.respond_to?(scope_key)
  end

  scope
end

.apply_value_filter(scope, model_class, field, value) ⇒ Object



157
158
159
160
161
162
163
164
165
# File 'lib/lcp_ruby/widgets/scope_applicator.rb', line 157

def apply_value_filter(scope, model_class, field, value)
  if model_class.column_names.include?(field.to_s)
    scope.where(field => value)
  elsif model_class.respond_to?("filter_#{field}")
    model_class.public_send("filter_#{field}", scope, value)
  else
    scope
  end
end

.blank_filter_value?(value) ⇒ Boolean

Returns:

  • (Boolean)


140
141
142
143
144
# File 'lib/lcp_ruby/widgets/scope_applicator.rb', line 140

def blank_filter_value?(value)
  return true if value.nil?
  return true if value.respond_to?(:empty?) && value.empty?
  false
end

.dispatch_filter_value(scope, model_class, vfield, value) ⇒ Object



147
148
149
150
151
152
153
154
# File 'lib/lcp_ruby/widgets/scope_applicator.rb', line 147

def dispatch_filter_value(scope, model_class, vfield, value)
  case vfield.input_type
  when "date_range"
    apply_date_range_filter(scope, model_class, vfield.name, value)
  else
    apply_value_filter(scope, model_class, vfield.name, value)
  end
end

.resolve_filter_value(filter_form, vfield) ⇒ Object

Range inputs (‘date_range`, future `numeric_range`) decompose into paired `_from`/`_to` synthetic attributes on VirtualForm (see VirtualField#attribute_names). Build the `to:` Hash the dispatch path expects from those two attributes, instead of reading a single attribute named after the field.



111
112
113
114
115
116
117
118
119
120
# File 'lib/lcp_ruby/widgets/scope_applicator.rb', line 111

def resolve_filter_value(filter_form, vfield)
  if vfield.input_type == "date_range"
    from = filter_form.attributes["#{vfield.name}_from"]
    to   = filter_form.attributes["#{vfield.name}_to"]
    return nil if from.blank? && to.blank?
    { "from" => from, "to" => to }
  else
    filter_form.attributes[vfield.name]
  end
end