Class: Plutonium::Resource::QueryObject

Inherits:
Object
  • Object
show all
Defined in:
lib/plutonium/resource/query_object.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(resource_class, params, request_path) {|_self| ... } ⇒ QueryObject

Initializes a QueryObject with the given resource_class and parameters.

Parameters:

  • resource_class (Object)

    The resource class.

  • params (Hash)

    The parameters for initialization.

Yields:

  • (_self)

Yield Parameters:



11
12
13
14
15
16
17
18
19
20
# File 'lib/plutonium/resource/query_object.rb', line 11

def initialize(resource_class, params, request_path, &)
  @resource_class = resource_class
  @params = params
  @request_path = request_path

  define_standard_queries
  yield self if block_given?
  extract_filter_params
  extract_sort_params
end

Instance Attribute Details

#default_scope_nameObject

Returns the value of attribute default_scope_name.



5
6
7
# File 'lib/plutonium/resource/query_object.rb', line 5

def default_scope_name
  @default_scope_name
end

#default_sort_configObject

Returns the value of attribute default_sort_config.



5
6
7
# File 'lib/plutonium/resource/query_object.rb', line 5

def default_sort_config
  @default_sort_config
end

#search_filterObject (readonly)

Returns the value of attribute search_filter.



4
5
6
# File 'lib/plutonium/resource/query_object.rb', line 4

def search_filter
  @search_filter
end

#search_queryObject (readonly)

Returns the value of attribute search_query.



4
5
6
# File 'lib/plutonium/resource/query_object.rb', line 4

def search_query
  @search_query
end

Instance Method Details

#active_filter_descriptionsObject

Returns an array of hashes describing each currently active filter. Each hash has: name, label, value_label, clear_url



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/plutonium/resource/query_object.rb', line 133

def active_filter_descriptions
  filter_definitions.filter_map do |name, filter|
    name = name.to_sym
    filter_params = params[name]
    next unless filter_params.present?

    value_label = case filter_params
    when Hash, ActionController::Parameters
      entries = filter_params.to_h.reject { |_, v| v.blank? }
      next if entries.empty?
      # Single-input filters defer to the filter's `humanize_value`
      # (e.g. Association resolves ids to labels, Boolean translates
      # "true" -> "Yes"). Multi-input filters keep input-name
      # qualifiers (e.g. "from 2024, to 2025").
      if entries.size == 1
        humanized = filter.humanize_value(entries.values.first)
        next if humanized.blank?
        humanized
      else
        entries.map { |k, v| "#{k.to_s.humanize.downcase} #{v}" }.join(", ")
      end
    when Array
      entries = filter_params.reject(&:blank?)
      next if entries.empty?
      humanized = filter.humanize_value(entries)
      next if humanized.blank?
      humanized
    else
      next if filter_params.to_s.blank?
      humanized = filter.humanize_value(filter_params)
      next if humanized.blank?
      humanized
    end

    {
      name: name,
      label: name.to_s.humanize,
      value_label: value_label,
      clear_url: build_url(name => nil)
    }
  end
end

#all_scope_selected?Boolean

Returns true if user explicitly selected “All” scope (no filtering)

Returns:

  • (Boolean)


122
# File 'lib/plutonium/resource/query_object.rb', line 122

def all_scope_selected? = @all_scope_selected

#apply(scope, params, context: nil) ⇒ Object

Applies the defined filters and sorts to the given scope.

Parameters:

  • scope (Object)

    The initial scope to which filters and sorts are applied.

  • params (Hash)

    The query parameters.

  • context (Object) (defaults to: nil)

    Optional context (e.g., controller) for executing scope blocks.

Returns:

  • (Object)

    The modified scope.



109
110
111
112
113
114
115
116
117
# File 'lib/plutonium/resource/query_object.rb', line 109

def apply(scope, params, context: nil)
  params = deep_compact(params.with_indifferent_access)
  scope = search_filter.apply(scope, search: params[:search]) if search_filter && params[:search]
  # Use selected_scope which includes the default when no explicit selection
  effective_scope = @selected_scope_filter
  scope = scope_definitions[effective_scope].apply(scope, context:) if effective_scope && scope_definitions[effective_scope]
  scope = apply_sorts(scope, params)
  apply_filters(scope, params)
end

#build_url(**options) ⇒ String

Builds a URL with the given options for search and sorting.

Parameters:

  • options (Hash)

    The options for building the URL.

Options Hash (**options):

  • :replace (Boolean)

    When true, clears all existing sorts before applying the new one

Returns:

  • (String)

    The constructed URL with query parameters.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/plutonium/resource/query_object.rb', line 68

def build_url(**options)
  q = {}

  q[:search] = options.key?(:search) ? options[:search].presence : search_query
  q[:scope] = if options.key?(:scope)
    options[:scope].presence
  else
    selected_scope_filter
  end

  if options.delete(:replace)
    q[:sort_directions] = {}
    q[:sort_fields] = []
  else
    q[:sort_directions] = selected_sort_directions.dup
    q[:sort_fields] = selected_sort_fields.dup
  end
  handle_sort_options!(q, options)

  filter_keys = filter_definitions.keys.map(&:to_sym)
  filter_overrides = options.slice(*filter_keys).stringify_keys
  q.merge! params.with_indifferent_access.slice(*filter_definitions.keys)
  q.merge!(filter_overrides)
  compacted = deep_compact({q: q})

  # Preserve explicit "All" selection (scope: nil in options means show all)
  if options.key?(:scope) && options[:scope].nil?
    compacted[:q] ||= {}
    compacted[:q][:scope] = ""
  end

  query_params = compacted.to_param
  "#{@request_path}?#{query_params}"
end

#define_filter(name, body) ⇒ Object

Defines a filter with the given name and body.

Parameters:

  • name (Symbol)

    The name of the filter.

  • body (Proc, nil)

    The body of the filter.



26
27
28
# File 'lib/plutonium/resource/query_object.rb', line 26

def define_filter(name, body, &)
  filter_definitions[name] = build_query(body, &)
end

#define_scope(name, body = nil) ⇒ Object

Defines a scope with the given name and body.

Parameters:

  • name (Symbol)

    The name of the scope.

  • body (Proc, nil) (defaults to: nil)

    The body of the scope.



34
35
36
37
# File 'lib/plutonium/resource/query_object.rb', line 34

def define_scope(name, body = nil, **)
  body ||= name
  scope_definitions[name] = build_query(body)
end

#define_search(body) ⇒ Object

Defines a search filter with the given body.

Parameters:

  • body (Proc, Symbol)

    The body of the search filter.



57
58
59
60
61
# File 'lib/plutonium/resource/query_object.rb', line 57

def define_search(body)
  @search_filter = build_query(body) do |query|
    query.input :search
  end
end

#define_sorter(name, body = nil, using: nil) ⇒ Object

Defines a sort with the given name and body.

Parameters:

  • name (Symbol)

    The name of the sort.

  • body (Proc, nil) (defaults to: nil)

    The body of the sort.



43
44
45
46
47
48
49
50
51
52
# File 'lib/plutonium/resource/query_object.rb', line 43

def define_sorter(name, body = nil, using: nil)
  if body.nil?
    sort_field = using || determine_sort_field(name)
    body = ->(scope, direction:) { scope.order(sort_field => direction) }
  end

  sort_definitions[name] = build_query(body) do |query|
    query.input :direction
  end
end

#filter_definitionsObject



127
# File 'lib/plutonium/resource/query_object.rb', line 127

def filter_definitions = @filter_definitions ||= {}.with_indifferent_access

#scope_definitionsObject



119
# File 'lib/plutonium/resource/query_object.rb', line 119

def scope_definitions = @scope_definitions ||= {}.with_indifferent_access

#selected_scopeObject

Returns the currently selected scope (may be default if none explicitly selected)



125
# File 'lib/plutonium/resource/query_object.rb', line 125

def selected_scope = @selected_scope_filter

#sort_definitionsObject



129
# File 'lib/plutonium/resource/query_object.rb', line 129

def sort_definitions = @sort_definitions ||= {}.with_indifferent_access

#sort_params_for(name) ⇒ Hash?

Provides sorting parameters for the given field name.

Parameters:

  • name (Symbol, String)

    The name of the field to sort.

Returns:

  • (Hash, nil)

    The sorting parameters including URL, multi_url, direction, position and multi flag.



180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/plutonium/resource/query_object.rb', line 180

def sort_params_for(name)
  return unless sort_definitions[name]

  multi = selected_sort_fields.size > 1 && selected_sort_fields.include?(name.to_s)

  {
    url: build_url(sort: name, replace: true),
    multi_url: build_url(sort: name),
    reset_url: build_url(sort: name, reset: true),
    position: selected_sort_fields.index(name.to_s),
    direction: selected_sort_directions[name],
    multi: multi
  }
end