fetcheable_on_api 0.4.1 → 0.5.0

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.
@@ -1,113 +1,274 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FetcheableOnApi
4
- # Sortable implements `pagination` support.
4
+ # Sortable implements support for JSONAPI-compliant sorting via `sort` query parameters.
5
+ #
6
+ # This module enables controllers to process sort parameters in the format:
7
+ # `sort=field1,-field2,+field3` where:
8
+ # - No prefix or `+` prefix means ascending order
9
+ # - `-` prefix means descending order
10
+ # - Multiple fields are comma-separated and applied in order
11
+ #
12
+ # It supports:
13
+ # - Single and multiple field sorting
14
+ # - Ascending and descending sort directions
15
+ # - Association sorting with custom class names
16
+ # - Case-insensitive sorting with the `lower` option
17
+ # - Field aliasing for different database column names
18
+ #
19
+ # @example Basic sorting setup
20
+ # class UsersController < ApplicationController
21
+ # sort_by :name, :email, :created_at
22
+ #
23
+ # def index
24
+ # users = apply_fetcheable(User.all)
25
+ # render json: users
26
+ # end
27
+ # end
28
+ #
29
+ # # GET /users?sort=name,-created_at (name asc, created_at desc)
30
+ #
31
+ # @example Association sorting
32
+ # class PostsController < ApplicationController
33
+ # sort_by :title, :created_at
34
+ # sort_by :author, class_name: User, as: 'name'
35
+ #
36
+ # def index
37
+ # posts = apply_fetcheable(Post.joins(:author))
38
+ # render json: posts
39
+ # end
40
+ # end
41
+ #
42
+ # # GET /posts?sort=author,-created_at (by author name asc, then created_at desc)
43
+ #
44
+ # @example Case-insensitive sorting
45
+ # class UsersController < ApplicationController
46
+ # sort_by :name, lower: true # Sort by lowercase name
47
+ # sort_by :email, :created_at
48
+ #
49
+ # def index
50
+ # users = apply_fetcheable(User.all)
51
+ # render json: users
52
+ # end
53
+ # end
54
+ #
55
+ # # GET /users?sort=name (sorts by LOWER(users.name))
56
+ #
57
+ # @see https://jsonapi.org/format/#fetching-sorting JSONAPI Sorting Specification
5
58
  module Sortable
59
+ # Maps sort direction prefixes to Arel sort methods.
60
+ # Used to parse the sort parameter and determine ascending vs descending order.
6
61
  #
7
- # Map of symbol to sorting direction supported by the module.
8
- #
62
+ # @example
63
+ # # "+name" or "name" -> :asc (ascending)
64
+ # # "-name" -> :desc (descending)
9
65
  SORT_ORDER = {
10
- "+" => :asc,
11
- "-" => :desc,
66
+ '+' => :asc, # Explicit ascending (same as no prefix)
67
+ '-' => :desc, # Explicit descending
12
68
  }.freeze
13
69
 
70
+ # Hook called when Sortable is included in a class.
71
+ # Sets up the class to support sort configuration and provides
72
+ # the sort_by class method.
14
73
  #
15
- # Public class methods
16
- #
74
+ # @param base [Class] The class including this module
75
+ # @private
17
76
  def self.included(base)
18
77
  base.class_eval do
19
78
  extend ClassMethods
79
+ # Store sort configurations per class to avoid conflicts between controllers
20
80
  class_attribute :sorts_configuration, instance_writer: false
21
81
  self.sorts_configuration = {}
22
82
  end
23
83
  end
24
84
 
25
- # Class methods made available to your controllers.
85
+ # Class methods made available to controllers when Sortable is included.
26
86
  module ClassMethods
27
- # Define one ore more sortable attribute configurations.
87
+ # Define one or more sortable attributes for the controller.
88
+ #
89
+ # This method configures which model attributes can be sorted via query parameters
90
+ # and how those sorts should be processed.
91
+ #
92
+ # @param attrs [Array<Symbol>] List of attribute names to make sortable
93
+ # @param options [Hash] Configuration options for the sorts
94
+ # @option options [String, Symbol] :as Alias for the database column name
95
+ # @option options [Boolean] :lower Whether to sort on the lowercase version of the attribute
96
+ # @option options [Class] :class_name Model class for association sorting (defaults to collection class)
97
+ # @option options [Symbol] :association Association name when different from inferred name
98
+ #
99
+ # @example Basic attribute sorting
100
+ # sort_by :name, :email, :created_at
101
+ # # Allows: sort=name,-email,created_at
102
+ #
103
+ # @example Case-insensitive sorting
104
+ # sort_by :name, lower: true
105
+ # # Generates: ORDER BY LOWER(users.name)
106
+ #
107
+ # @example Association sorting
108
+ # sort_by :author, class_name: User, as: 'name'
109
+ # # Allows: sort=author (sorts by users.name)
28
110
  #
29
- # @param attrs [Array] options to define one or more sorting
30
- # configurations.
31
- # @option attrs [String, nil] :as Alias the sorted attribute
32
- # @option attrs [true, false, nil] :with Wether to sort on the lowercase
33
- # attribute value.
111
+ # @example Association sorting with custom association name
112
+ # sort_by :author_name, class_name: User, as: 'name', association: :author
113
+ # # Allows: sort=author_name (sorts by users.name via author association)
114
+ # # Note: Make sure your collection is joined: Book.joins(:author)
115
+ #
116
+ # @example Field aliasing
117
+ # sort_by :full_name, as: 'name'
118
+ # # Maps sort=full_name to ORDER BY users.name
34
119
  def sort_by(*attrs)
35
120
  options = attrs.extract_options!
36
121
  options.symbolize_keys!
37
122
 
123
+ # Validate that only supported options are provided
124
+ options.assert_valid_keys(:as, :class_name, :lower, :association)
125
+
126
+ # Create a new configuration hash to avoid modifying parent class config
38
127
  self.sorts_configuration = sorts_configuration.dup
39
128
 
40
129
  attrs.each do |attr|
130
+ # Initialize default configuration for this attribute
41
131
  sorts_configuration[attr] ||= {
42
- as: attr,
132
+ as: attr
43
133
  }
44
134
 
135
+ # Merge in the provided options, overriding defaults
45
136
  sorts_configuration[attr] = sorts_configuration[attr].merge(options)
46
137
  end
47
138
  end
48
139
  end
49
140
 
50
- #
51
- # Public instance methods
52
- #
141
+ # Protected instance methods for sorting functionality
53
142
 
54
- #
55
- # Protected instance methods
56
- #
57
143
  protected
58
144
 
145
+ # Apply sorting to the collection based on sort query parameters.
146
+ # This is the main method that processes the sort parameter and
147
+ # applies ordering to the ActiveRecord relation.
148
+ #
149
+ # @param collection [ActiveRecord::Relation] The collection to sort
150
+ # @return [ActiveRecord::Relation] The sorted collection
151
+ # @raise [FetcheableOnApi::ArgumentError] When sort parameters are invalid
152
+ #
153
+ # @example
154
+ # # With params: { sort: 'name,-created_at' }
155
+ # sorted_users = apply_sort(User.all)
156
+ # # Generates: ORDER BY users.name ASC, users.created_at DESC
59
157
  def apply_sort(collection)
158
+ # Return early if no sort parameters are provided
60
159
  return collection if params[:sort].blank?
61
160
 
161
+ # Validate that sort parameter is a string
62
162
  foa_valid_parameters!(:sort, foa_permitted_types: [String])
63
163
 
164
+ # Parse the sort parameter and build Arel ordering expressions
64
165
  ordering = format_params(params[:sort]).map do |attr_name, sort_method|
65
166
  arel_sort(attr_name, sort_method, collection)
66
167
  end
67
168
 
169
+ # Apply the ordering, filtering out any nil values (unconfigured sorts)
68
170
  collection.order(ordering.compact)
69
171
  end
70
172
 
71
173
  private
72
174
 
175
+ # Build an Arel ordering expression for the given attribute and sort direction.
176
+ # Returns nil if the attribute is not configured for sorting or doesn't exist on the model.
177
+ #
178
+ # @param attr_name [Symbol] The attribute name to sort by
179
+ # @param sort_method [Symbol] The sort direction (:asc or :desc)
180
+ # @param collection [ActiveRecord::Relation] The collection being sorted
181
+ # @return [Arel::Node, nil] An Arel ordering node or nil if invalid
182
+ # @private
73
183
  def arel_sort(attr_name, sort_method, collection)
184
+ # Skip if this attribute is not configured for sorting
74
185
  return if sorts_configuration[attr_name].blank?
75
186
 
76
187
  klass = class_for(attr_name, collection)
77
188
  field = field_for(attr_name)
189
+
190
+ # Skip if the field doesn't exist on the model
78
191
  return unless belong_to_attributes_for?(klass, field)
79
192
 
193
+ # Build the Arel attribute reference using the appropriate table
80
194
  attribute = klass.arel_table[field]
81
- attribute = attribute.lower if sorts_configuration[attr_name].fetch(:lower, false)
82
195
 
196
+ # Apply lowercase transformation if configured
197
+ config = sorts_configuration[attr_name] || {}
198
+ attribute = attribute.lower if config.fetch(:lower, false)
199
+
200
+ # Apply the sort direction (asc or desc)
83
201
  attribute.send(sort_method)
84
202
  end
85
203
 
204
+ # Determine the model class to use for this sort attribute.
205
+ # Uses the configured class_name or falls back to the collection's class.
206
+ #
207
+ # @param attr_name [Symbol] The attribute name
208
+ # @param collection [ActiveRecord::Relation] The collection being sorted
209
+ # @return [Class] The model class to use
210
+ # @private
86
211
  def class_for(attr_name, collection)
87
- sorts_configuration[attr_name].fetch(:class_name, collection.klass)
212
+ config = sorts_configuration[attr_name] || {}
213
+ config.fetch(:class_name, collection.klass)
88
214
  end
89
215
 
216
+ # Get the database field name for this sort attribute.
217
+ # Uses the configured alias (:as option) or the attribute name itself.
218
+ #
219
+ # @param attr_name [Symbol] The attribute name
220
+ # @return [String] The database column name
221
+ # @private
90
222
  def field_for(attr_name)
91
- sorts_configuration[attr_name].fetch(:as, attr_name).to_s
223
+ config = sorts_configuration[attr_name] || {}
224
+ config.fetch(:as, attr_name).to_s
92
225
  end
93
226
 
227
+ # Check if the given field exists as an attribute on the model class.
228
+ # This prevents SQL errors from trying to sort by non-existent columns.
229
+ #
230
+ # @param klass [Class] The model class
231
+ # @param field [String] The field name to check
232
+ # @return [Boolean] True if the field exists on the model
233
+ # @private
94
234
  def belong_to_attributes_for?(klass, field)
95
235
  klass.attribute_names.include?(field)
96
236
  end
97
237
 
238
+ # Parse the sort parameter string into a hash of attributes and directions.
98
239
  #
99
- # input: "-email,first_name"
100
- # return: { email: :desc, first_name: :asc }
240
+ # This method takes a comma-separated string of sort fields (with optional
241
+ # direction prefixes) and converts it into a hash mapping field names to
242
+ # sort directions.
101
243
  #
244
+ # @param params [String] The sort parameter string
245
+ # @return [Hash{Symbol => Symbol}] Hash mapping attribute names to sort directions
246
+ #
247
+ # @example
248
+ # format_params("-email,first_name,+last_name")
249
+ # # => { email: :desc, first_name: :asc, last_name: :asc }
250
+ #
251
+ # format_params("name")
252
+ # # => { name: :asc }
253
+ #
254
+ # @private
102
255
  def format_params(params)
103
- res = {}
256
+ result = {}
257
+
104
258
  params
105
- .split(",")
259
+ .split(',') # Split on commas to get individual fields
106
260
  .each do |attribute|
107
- sort_sign = attribute =~ /\A[+-]/ ? attribute.slice!(0) : "+"
108
- res[attribute.to_sym] = SORT_ORDER[sort_sign]
261
+ # Trim whitespace
262
+ attribute = attribute.strip
263
+
264
+ # Extract the direction prefix (+ or -) or default to +
265
+ sort_sign = attribute =~ /\A[+-]/ ? attribute.slice!(0) : '+'
266
+
267
+ # Map the field name to its sort direction
268
+ result[attribute.to_sym] = SORT_ORDER[sort_sign]
109
269
  end
110
- res
270
+
271
+ result
111
272
  end
112
273
  end
113
274
  end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FetcheableOnApi
4
- VERSION = '0.4.1'.freeze
4
+ # Current version of the FetcheableOnApi gem.
5
+ # Follows semantic versioning (semver.org) principles.
6
+ #
7
+ # @return [String] The version string in format "MAJOR.MINOR.PATCH"
8
+ VERSION = '0.5.0'.freeze
5
9
  end
@@ -1,49 +1,96 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fetcheable_on_api/configuration"
4
- require "fetcheable_on_api/filterable"
5
- require "fetcheable_on_api/pageable"
6
- require "fetcheable_on_api/sortable"
7
- require "fetcheable_on_api/version"
8
- require "active_support"
9
- require "date"
3
+ require 'fetcheable_on_api/configuration'
4
+ require 'fetcheable_on_api/filterable'
5
+ require 'fetcheable_on_api/pageable'
6
+ require 'fetcheable_on_api/sortable'
7
+ require 'fetcheable_on_api/version'
8
+ require 'active_support'
9
+ require 'date'
10
10
 
11
11
  # FetcheableOnApi provides standardized sorting, filtering and pagination for
12
- # you API controllers.
12
+ # Rails API controllers following the JSONAPI specification.
13
13
  #
14
+ # This gem automatically adds support for query parameters like:
15
+ # - `filter[attribute]=value` for filtering data
16
+ # - `sort=attribute1,-attribute2` for sorting (- prefix for descending)
17
+ # - `page[number]=1&page[size]=25` for pagination
18
+ #
19
+ # @example Basic usage in a controller
20
+ # class UsersController < ApplicationController
21
+ # # Configure allowed filters and sorts
22
+ # filter_by :name, :email, :status
23
+ # sort_by :name, :created_at, :updated_at
24
+ #
25
+ # def index
26
+ # users = apply_fetcheable(User.all)
27
+ # render json: users
28
+ # end
29
+ # end
30
+ #
31
+ # @example Using with associations
32
+ # class PostsController < ApplicationController
33
+ # filter_by :title
34
+ # filter_by :author, class_name: User, as: 'name'
35
+ # sort_by :title, :created_at
36
+ # sort_by :author, class_name: User, as: 'name'
37
+ #
38
+ # def index
39
+ # posts = apply_fetcheable(Post.joins(:author).includes(:author))
40
+ # render json: posts
41
+ # end
42
+ # end
43
+ #
44
+ # @author Fabien Piette
45
+ # @since 0.1.0
14
46
  module FetcheableOnApi
15
- #
16
- # Global configuration settings for FetcheableOnApi
47
+ # Global configuration settings for FetcheableOnApi.
48
+ # This method provides access to the singleton configuration instance
49
+ # that can be used to customize default behavior across the application.
17
50
  #
18
51
  # @example Set default pagination size
19
52
  # FetcheableOnApi.configuration.pagination_default_size = 25
20
53
  #
21
54
  # @return [Configuration] The global configuration instance
55
+ # @see Configuration
22
56
  def self.configuration
23
57
  @configuration ||= Configuration.new
24
58
  end
25
59
 
26
60
  # Configure FetcheableOnApi using a block.
61
+ # This is the recommended way to set up configuration in an initializer.
27
62
  #
28
- # @example Set default pagination size
63
+ # @example Set default pagination size in config/initializers/fetcheable_on_api.rb
29
64
  # FetcheableOnApi.configure do |config|
30
- # config.pagination_default_size = 25
65
+ # config.pagination_default_size = 50
31
66
  # end
32
67
  #
33
- # @yield [Configuration] Gives the global instance to the block.
68
+ # @yield [Configuration] Gives the global configuration instance to the block
69
+ # @see Configuration
34
70
  def self.configure
35
71
  yield(configuration)
36
72
  end
37
73
 
38
- #
39
- # Supports
40
- #
74
+ # Custom exception classes for FetcheableOnApi-specific errors.
75
+ # These inherit from standard Ruby exceptions but allow for more
76
+ # specific error handling in applications using this gem.
77
+
78
+ # Raised when invalid parameters are provided to filtering, sorting, or pagination
79
+ # @example
80
+ # raise FetcheableOnApi::ArgumentError, "Invalid filter parameter type"
41
81
  ArgumentError = Class.new(ArgumentError)
82
+
83
+ # Raised when a feature is not yet implemented or supported
84
+ # @example
85
+ # raise FetcheableOnApi::NotImplementedError, "Custom predicate not supported"
42
86
  NotImplementedError = Class.new(NotImplementedError)
43
87
 
88
+ # Hook called when this module is included in a class.
89
+ # Automatically includes the three main concern modules that provide
90
+ # filtering, sorting, and pagination functionality.
44
91
  #
45
- # Public class methods
46
- #
92
+ # @param klass [Class] The class that is including FetcheableOnApi
93
+ # @private
47
94
  def self.included(klass)
48
95
  klass.class_eval do
49
96
  include Filterable
@@ -52,60 +99,131 @@ module FetcheableOnApi
52
99
  end
53
100
  end
54
101
 
102
+ # Protected instance methods available to controllers that include this module
103
+
104
+ protected
105
+
106
+ # Apply filters, sorting, and pagination to a collection in sequence.
107
+ # This is the main entry point for processing JSONAPI query parameters.
55
108
  #
56
- # Public instance methods
109
+ # The operations are applied in this specific order:
110
+ # 1. Filtering (apply_filters) - reduces the dataset
111
+ # 2. Sorting (apply_sort) - orders the results
112
+ # 3. Pagination (apply_pagination) - limits and offsets for page
57
113
  #
58
-
114
+ # @param collection [ActiveRecord::Relation] The base collection to process
115
+ # @return [ActiveRecord::Relation] The processed collection with filters, sorting, and pagination applied
59
116
  #
60
- # Protected instance methods
117
+ # @example Basic usage
118
+ # def index
119
+ # users = apply_fetcheable(User.all)
120
+ # render json: users
121
+ # end
61
122
  #
62
- protected
63
-
64
- # Apply filters, sort and page on a collection.
123
+ # @example With joins for association filtering/sorting
124
+ # def index
125
+ # posts = apply_fetcheable(Post.joins(:author).includes(:author))
126
+ # render json: posts
127
+ # end
65
128
  def apply_fetcheable(collection)
129
+ # Apply filtering first to reduce dataset size
66
130
  collection = apply_filters(collection)
131
+
132
+ # Apply sorting to the filtered results
67
133
  collection = apply_sort(collection)
68
134
 
135
+ # Apply pagination last to get the final page
69
136
  apply_pagination(collection)
70
137
  end
71
138
 
72
- # Checks if the type of arguments is included in the permitted types
73
- def foa_valid_parameters!(
74
- *keys, foa_permitted_types: foa_default_permitted_types)
75
- return if foa_valid_params_types(
76
- *keys,
77
- foa_permitted_types: foa_permitted_types,
78
- )
139
+ # Validates that the specified parameter keys contain values of permitted types.
140
+ # This is used internally by the filtering, sorting, and pagination modules
141
+ # to ensure that malformed or malicious parameters don't cause errors.
142
+ #
143
+ # @param keys [Array<Symbol>] Path to the parameter to validate (e.g., [:filter], [:page, :number])
144
+ # @param foa_permitted_types [Array<Class>] Array of allowed parameter types
145
+ # @raise [FetcheableOnApi::ArgumentError] When parameter type is not in permitted types
146
+ #
147
+ # @example
148
+ # # Validates that params[:filter] is a Hash or ActionController::Parameters
149
+ # foa_valid_parameters!(:filter)
150
+ #
151
+ # # Validates that params[:sort] is a String
152
+ # foa_valid_parameters!(:sort, foa_permitted_types: [String])
153
+ #
154
+ # @private
155
+ def foa_valid_parameters!(*keys, foa_permitted_types: foa_default_permitted_types)
156
+ return if foa_valid_params_types(*keys, foa_permitted_types: foa_permitted_types)
79
157
 
158
+ actual_type = params.dig(*keys).class
80
159
  raise FetcheableOnApi::ArgumentError,
81
- "Incorrect type #{params.dig(*keys).class} for params #{keys}"
160
+ "Incorrect type #{actual_type} for params #{keys}"
82
161
  end
83
162
 
84
- def foa_valid_params_types(
85
- *keys, foa_permitted_types: foa_default_permitted_types)
86
- foa_permitted_types.inject(false) do |res, type|
87
- res || foa_valid_params_type(params.dig(*keys), type)
163
+ # Checks if the parameter value at the specified keys matches any of the permitted types.
164
+ #
165
+ # @param keys [Array<Symbol>] Path to the parameter to check
166
+ # @param foa_permitted_types [Array<Class>] Array of allowed parameter types
167
+ # @return [Boolean] True if the parameter type is valid, false otherwise
168
+ # @private
169
+ def foa_valid_params_types(*keys, foa_permitted_types: foa_default_permitted_types)
170
+ foa_permitted_types.inject(false) do |result, type|
171
+ result || foa_valid_params_type(params.dig(*keys), type)
88
172
  end
89
173
  end
90
174
 
91
- # Returns true if class is the class of value,
92
- # or if class is one of the superclasses of value
93
- # or modules included in value.
175
+ # Checks if a value is of the specified type using Ruby's is_a? method.
176
+ # This handles inheritance and module inclusion correctly.
177
+ #
178
+ # @param value [Object] The value to type-check
179
+ # @param type [Class] The expected type/class
180
+ # @return [Boolean] True if value is an instance of type (or its subclass/module)
181
+ # @private
94
182
  def foa_valid_params_type(value, type)
95
183
  value.is_a?(type)
96
184
  end
97
185
 
98
- # Types allowed by default.
186
+ # Default permitted parameter types for most operations.
187
+ # ActionController::Parameters is the standard Rails params object,
188
+ # while Hash is allowed for direct hash parameters in tests or non-Rails usage.
189
+ #
190
+ # @return [Array<Class>] Array of default permitted parameter types
191
+ # @private
99
192
  def foa_default_permitted_types
100
193
  [ActionController::Parameters, Hash]
101
194
  end
102
195
 
103
- # Convert string to datetime.
196
+ # Convert string timestamp to DateTime object.
197
+ # This is used for date/time filtering when the format is set to :datetime.
198
+ # By default, it expects Unix epoch timestamps as strings.
199
+ #
200
+ # This method can be overridden in controllers to support different date formats:
201
+ #
202
+ # @param string [String] The timestamp string to convert
203
+ # @return [DateTime] The parsed DateTime object
204
+ #
205
+ # @example Override in controller for custom date format
206
+ # class UsersController < ApplicationController
207
+ # private
208
+ #
209
+ # def foa_string_to_datetime(string)
210
+ # DateTime.strptime(string, '%Y-%m-%d %H:%M:%S')
211
+ # end
212
+ # end
213
+ #
214
+ # @example Default usage with epoch timestamps
215
+ # foa_string_to_datetime('1609459200') # => 2021-01-01 00:00:00 +0000
104
216
  def foa_string_to_datetime(string)
105
- DateTime.strptime(string, "%s")
217
+ DateTime.strptime(string, '%s')
106
218
  end
107
219
  end
108
220
 
221
+ # Automatically include FetcheableOnApi in all ActionController classes when Rails loads.
222
+ # This makes the filtering, sorting, and pagination functionality available
223
+ # to all controllers without requiring manual inclusion.
224
+ #
225
+ # @note This uses ActiveSupport's lazy loading mechanism to ensure ActionController
226
+ # is fully loaded before including the module.
109
227
  ActiveSupport.on_load :action_controller do
110
228
  include FetcheableOnApi
111
229
  end
@@ -1,10 +1,24 @@
1
1
  module FetcheableOnApi
2
2
  module Generators
3
- # Create conf file
3
+ # Rails generator for creating FetcheableOnApi initializer file.
4
+ #
5
+ # This generator creates a configuration initializer file that allows
6
+ # developers to customize FetcheableOnApi settings for their application.
7
+ #
8
+ # @example Running the generator
9
+ # rails generate fetcheable_on_api:install
10
+ # # Creates: config/initializers/fetcheable_on_api.rb
11
+ #
12
+ # @since 0.1.0
4
13
  class InstallGenerator < Rails::Generators::Base
5
14
  source_root File.expand_path('../templates', __dir__)
6
15
  desc 'Creates FetcheableOnApi initializer for your application'
7
16
 
17
+ # Copy the initializer template to the Rails application's config/initializers directory.
18
+ # The generated file contains configuration options with sensible defaults and
19
+ # documentation about available settings.
20
+ #
21
+ # @return [void]
8
22
  def copy_initializer
9
23
  template 'fetcheable_on_api_initializer.rb',
10
24
  'config/initializers/fetcheable_on_api.rb'
@@ -1,3 +1,17 @@
1
+ # FetcheableOnApi configuration
2
+ #
3
+ # This initializer configures the FetcheableOnApi gem settings for your application.
4
+ # These settings affect the behavior of filtering, sorting, and pagination across
5
+ # all controllers that use the FetcheableOnApi module.
6
+
1
7
  FetcheableOnApi.configure do |config|
8
+ # Default number of records per page when no page[size] parameter is provided.
9
+ # This affects the Pageable module when clients don't specify a page size.
10
+ #
11
+ # Examples:
12
+ # - With default (25): GET /users?page[number]=2 returns 25 records
13
+ # - With custom (50): GET /users?page[number]=2 returns 50 records
14
+ #
15
+ # Default: 25
2
16
  config.pagination_default_size = 25
3
17
  end