active_queryable 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5bf4db93e62b6ef9584ed59ac624d983debc4a7792dc4debc252fe4958c0e3ac
4
- data.tar.gz: 38bd3b1e7b4e9138be78e1cfed968b9dc499894c5d6aa5d1710bf5d1aa032d26
3
+ metadata.gz: ca76d46d098d260a1f59a1fd6e50d59cbab69eb95ba87f25470ccb08aa3050f2
4
+ data.tar.gz: 9562f2b4d7a4cce6ba1ba6bb070c6e6d9cf031d6205bf1006e5b5c1f21566ed4
5
5
  SHA512:
6
- metadata.gz: fe31f1bacbd161809ede6ad71b12793f1515a4b189b59006b5558ef7d4b9cdd5c43bb905bd2e932d8d087f15e014efce399c7ce13631277265522e9fb3c6a589
7
- data.tar.gz: 4f0b563933703484579689cee4fbabe5445ad021115c73bc863f76f9db3ee61df511fa29bd9041aabb81ffbfa1020215005a916cf6de0cc6e4905573c209d2f6
6
+ metadata.gz: 5ec24780124afa2fd02e2d6bdf9a4f54f6dd980c8852adc43c4ae37144f887d54eccbdebf5e8d50765b3cc3e051762f4c1e62f7006a3a5385d5ed6962e3ce22f
7
+ data.tar.gz: aaf987e005a9f87b39ae00f63adaf7791a11b0facc962ae2f9b70e541e74f7b0281e1d71e6428ba71b97c7ba924dd20cf08b126e960430f9ecf8ef88d0ec9d0d
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveQueryable
2
- VERSION = '0.3.0'
4
+ # @return [String] the version of the gem
5
+ VERSION = '0.3.1'
3
6
  end
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/concern'
4
+ require 'active_record'
4
5
  require 'kaminari/activerecord'
5
6
 
7
+ # A light and simple gem for sorting / filtering / paginating a model in Rails.
6
8
  module ActiveQueryable
7
- extend ActiveSupport::Concern
9
+ extend ActiveSupport::Concern
8
10
 
9
- QUERYABLE_VALID_PARAMS = [:filter, :sort, :page, :per].freeze
11
+ # @private
12
+ QUERYABLE_VALID_PARAMS = %i[filter sort page per].freeze
10
13
 
11
14
  included do
12
15
  class_attribute :_queryable_default_order
@@ -14,34 +17,94 @@ module ActiveQueryable
14
17
  class_attribute :_queryable_default_per
15
18
  class_attribute :_queryable_filter_keys
16
19
  class_attribute :_queryable_expandable_filter_keys
17
- end
20
+ end
18
21
 
19
- module Initializer
22
+ # @private
23
+ module Initializer
24
+ # Enables ActiveQueryable for the model
25
+ # @example
26
+ # class User < ApplicationRecord
27
+ # as_queryable
28
+ # end
29
+ #
30
+ # @!parse include ActiveQueryable
31
+ # @return [void]
20
32
  def as_queryable
21
- send :include, ActiveQueryable
22
- end
23
- end
33
+ send :include, ActiveQueryable
34
+ end
35
+ end
24
36
 
37
+ # Extension methods for ActiveRecord::Base
38
+ # @!method query_by(params)
39
+ # Runs a query with the given params
40
+ # @example
41
+ # User.query_by(sort: '-name', filter: { name: 'John' })
42
+ # @param params [Hash,ActionController::Parameters]
43
+ # @option params [String] :sort
44
+ # @option params [Hash] :filter
45
+ # @option params [String] :page
46
+ # @option params [String] :per
47
+ # @option params [Hash] :page
48
+ # @return [ActiveRecord::Relation]
49
+ # @!method of_not(ids)
50
+ # @example
51
+ # User.of_not([1, 2, 3]) # => equivalent of: User.where.not(id: [1, 2, 3])
52
+ # Returns a scope with the given ids excluded
53
+ # @param ids [Array<Integer,String>]
54
+ # @return [ActiveRecord::Relation]
25
55
  module ClassMethods
56
+ # Configures the model to be queryable
57
+ # @example
58
+ # class User < ApplicationRecord
59
+ # as_queryable
60
+ # queryable order: { name: :asc }, page: 1, per: 25, filter: %i[name email]
61
+ # end
62
+ #
63
+ # @param options [Hash]
64
+ # @option options [Hash<Symbol,Symbol>] :order { id: :asc }
65
+ # @option options [Integer] :page 1
66
+ # @option options [Integer] :per 25
67
+ # @option options [Array<Symbol,String>] :filter []
68
+ # @return [void]
26
69
  def queryable(options)
27
- self._queryable_default_order = options[:order] || { id: :asc }
28
- self._queryable_default_page = options[:page] || 1
29
- self._queryable_default_per = options[:per] || 25
30
- self._queryable_filter_keys = (((options[:filter] || [])).map(&:to_sym))
70
+ queryable_configure_options(options)
31
71
 
32
72
  scope :query_by, ->(params) { queryable_scope(params) }
33
73
  scope :of_not, ->(ids) { where.not(id: ids) }
34
74
  end
35
75
 
76
+ # A method to expand the filterable keys, useful to allow class inheritance
77
+ # @example
78
+ # class BaseItem < ApplicationRecord
79
+ # as_queryable
80
+ # queryable order: { name: :asc }, page: 1, per: 25, filter: %i[name email]
81
+ # end
82
+ # class AdvancedItem < BaseItem
83
+ # expand_queryable filter: %i[phone]
84
+ # end
85
+ #
86
+ #
87
+ # @param options [Hash]
88
+ # @option options [Array<Symbol,String>] :filter []
89
+ # @return [void]
36
90
  def expand_queryable(options)
37
91
  self._queryable_expandable_filter_keys ||= []
38
- self._queryable_expandable_filter_keys += (((options[:filter] || [])).map(&:to_sym))
92
+ self._queryable_expandable_filter_keys += ((options[:filter] || [])).map(&:to_sym)
39
93
  end
40
94
 
95
+ # @param params [Hash,ActionController::Parameters]
96
+ # @option params [String] :sort
97
+ # @option params [Hash] :filter
98
+ # @option params [String] :page
99
+ # @option params [String] :per
100
+ # @option params [Hash] :page
101
+ # @return [ActiveRecord::Relation]
41
102
  def queryable_scope(params)
42
103
  params = params.to_unsafe_h if params.respond_to? :to_unsafe_h
43
104
  params = params.with_indifferent_access if params.respond_to?(:with_indifferent_access)
44
- params.each_key { |k| QUERYABLE_VALID_PARAMS.include?(k.to_sym) || Rails.logger.error("Invalid key #{k} in queryable") }
105
+ params.each_key do |k|
106
+ QUERYABLE_VALID_PARAMS.include?(k.to_sym) || Rails.logger.error("Invalid key #{k} in queryable")
107
+ end
45
108
 
46
109
  order_params = queryable_validate_order_params(params[:sort])
47
110
  query = queryable_parse_order_scope(order_params, self)
@@ -51,6 +114,26 @@ module ActiveQueryable
51
114
 
52
115
  private
53
116
 
117
+ # @option options [Hash<Symbol,Symbol>] :order { id: :asc }
118
+ # @option options [Integer] :page 1
119
+ # @option options [Integer] :per 25
120
+ # @option options [Array<Symbol,String>] :filter []
121
+ # @return [void]
122
+ def queryable_configure_options(options)
123
+ self._queryable_default_order = options[:order] || { id: :asc }
124
+ self._queryable_default_page = options[:page] || 1
125
+ self._queryable_default_per = options[:per] || 25
126
+ self._queryable_filter_keys = (((options[:filter] || [])).map(&:to_sym))
127
+ end
128
+
129
+ # @param params [Hash,ActionController::Parameters]
130
+ # @option params [String] :sort
131
+ # @option params [Hash] :filter
132
+ # @option params [String] :page
133
+ # @option params [String] :per
134
+ # @option params [Hash] :page
135
+ # @param query [ActiveRecord::Relation]
136
+ # @return [ActiveRecord::Relation]
54
137
  def queryable_filtered_scope(params, query)
55
138
  filter_params = queryable_validate_filter_params(params[:filter])
56
139
 
@@ -67,10 +150,17 @@ module ActiveQueryable
67
150
  scope
68
151
  end
69
152
 
153
+ # @param params [String,nil]
154
+ # @return [Hash]
70
155
  def queryable_validate_order_params(params)
71
156
  queryable_parse_order_params(params) || _queryable_default_order
72
157
  end
73
158
 
159
+ # @param params [Hash,ActionController::Parameters]
160
+ # @option params [String] :page
161
+ # @option params [String] :per
162
+ # @option params [Hash] :page
163
+ # @return [Hash]
74
164
  def queryable_validate_page_params(params)
75
165
  page_params = {}
76
166
  if params[:page].respond_to?(:dig)
@@ -83,16 +173,20 @@ module ActiveQueryable
83
173
  page_params
84
174
  end
85
175
 
176
+ # @param filter_params [Hash,ActionController::Parameters,nil]
177
+ # @return [Hash]
86
178
  def queryable_validate_filter_params(filter_params)
87
179
  return nil if filter_params.nil?
88
180
 
89
- filters = (((self._queryable_filter_keys || []) | (self._queryable_expandable_filter_keys || [])) + ['not']).map(&:to_sym)
181
+ filters = (((_queryable_filter_keys || []) | (self._queryable_expandable_filter_keys || [])) + ['not']).map(&:to_sym)
90
182
  unpermitted = filter_params.except(*filters)
91
183
  Rails.logger.warn("Unpermitted queryable parameters: #{unpermitted.keys.join(', ')}") if unpermitted.present?
92
184
 
93
185
  filter_params.slice(*filters)
94
186
  end
95
187
 
188
+ # @param params [String,nil]
189
+ # @return [Hash]
96
190
  def queryable_parse_order_params(params)
97
191
  return nil unless params.is_a? String
98
192
 
@@ -102,6 +196,9 @@ module ActiveQueryable
102
196
  end.to_h
103
197
  end
104
198
 
199
+ # @param params [Hash,ActionController::Parameters,nil]
200
+ # @param query [ActiveRecord::Relation]
201
+ # @return [ActiveRecord::Relation]
105
202
  def queryable_parse_order_scope(params, query)
106
203
  return query unless params
107
204
 
@@ -116,13 +213,15 @@ module ActiveQueryable
116
213
  end || query
117
214
  end
118
215
 
216
+ # @param params [Hash,ActionController::Parameters,nil]
217
+ # @param query [ActiveRecord::Relation]
218
+ # @return [ActiveRecord::Relation]
119
219
  def queryable_parse_filter_scope(params, query)
120
220
  return query unless params
121
221
 
122
222
  params.inject(query) do |current_query, (k, v)|
123
223
  scope = "of_#{k}"
124
224
 
125
-
126
225
  if current_query.respond_to?(scope, true)
127
226
  current_query.public_send(scope, v)
128
227
  else
@@ -132,4 +231,7 @@ module ActiveQueryable
132
231
  end
133
232
  end
134
233
  end
135
- ActiveRecord::Base.send :extend, ActiveQueryable::Initializer
234
+
235
+ # rubocop:disable Lint/SendWithMixinArgument
236
+ ActiveRecord::Base.send(:extend, ActiveQueryable::Initializer)
237
+ # rubocop:enable Lint/SendWithMixinArgument
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_queryable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mònade