warped 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +25 -0
  3. data/Gemfile +0 -2
  4. data/Gemfile.lock +25 -19
  5. data/README.md +116 -270
  6. data/app/assets/config/warped_manifest.js +2 -0
  7. data/app/assets/javascript/warped/controllers/filter_controller.js +76 -0
  8. data/app/assets/javascript/warped/controllers/filters_controller.js +21 -0
  9. data/app/assets/javascript/warped/index.js +2 -0
  10. data/app/assets/stylesheets/warped/application.css +15 -0
  11. data/app/assets/stylesheets/warped/base.css +23 -0
  12. data/app/assets/stylesheets/warped/filters.css +115 -0
  13. data/app/assets/stylesheets/warped/pagination.css +74 -0
  14. data/app/assets/stylesheets/warped/search.css +33 -0
  15. data/app/assets/stylesheets/warped/table.css +114 -0
  16. data/app/views/warped/_actions.html.erb +9 -0
  17. data/app/views/warped/_cell.html.erb +3 -0
  18. data/app/views/warped/_column.html.erb +35 -0
  19. data/app/views/warped/_filters.html.erb +21 -0
  20. data/app/views/warped/_hidden_fields.html.erb +19 -0
  21. data/app/views/warped/_pagination.html.erb +34 -0
  22. data/app/views/warped/_row.html.erb +19 -0
  23. data/app/views/warped/_search.html.erb +21 -0
  24. data/app/views/warped/_table.html.erb +52 -0
  25. data/app/views/warped/filters/_filter.html.erb +40 -0
  26. data/config/importmap.rb +3 -0
  27. data/docs/controllers/FILTERABLE.md +193 -0
  28. data/docs/controllers/PAGEABLE.md +70 -0
  29. data/docs/controllers/README.md +8 -0
  30. data/docs/controllers/SEARCHABLE.md +95 -0
  31. data/docs/controllers/SORTABLE.md +94 -0
  32. data/docs/controllers/TABULATABLE.md +28 -0
  33. data/docs/controllers/views/PARTIALS.md +285 -0
  34. data/docs/jobs/README.md +22 -0
  35. data/docs/services/README.md +81 -0
  36. data/lib/generators/warped/install_generator.rb +1 -1
  37. data/lib/warped/api/filter/base/value.rb +52 -0
  38. data/lib/warped/api/filter/base.rb +84 -0
  39. data/lib/warped/api/filter/boolean.rb +41 -0
  40. data/lib/warped/api/filter/date.rb +26 -0
  41. data/lib/warped/api/filter/date_time.rb +32 -0
  42. data/lib/warped/api/filter/decimal.rb +31 -0
  43. data/lib/warped/api/filter/factory.rb +38 -0
  44. data/lib/warped/api/filter/integer.rb +38 -0
  45. data/lib/warped/api/filter/string.rb +25 -0
  46. data/lib/warped/api/filter/time.rb +25 -0
  47. data/lib/warped/api/filter.rb +14 -0
  48. data/lib/warped/api/sort/value.rb +40 -0
  49. data/lib/warped/api/sort.rb +65 -0
  50. data/lib/warped/controllers/filterable/ui.rb +46 -0
  51. data/lib/warped/controllers/filterable.rb +79 -42
  52. data/lib/warped/controllers/pageable/ui.rb +70 -0
  53. data/lib/warped/controllers/pageable.rb +11 -11
  54. data/lib/warped/controllers/searchable/ui.rb +37 -0
  55. data/lib/warped/controllers/searchable.rb +2 -0
  56. data/lib/warped/controllers/sortable/ui.rb +53 -0
  57. data/lib/warped/controllers/sortable.rb +53 -33
  58. data/lib/warped/controllers/tabulatable/ui.rb +54 -0
  59. data/lib/warped/controllers/tabulatable.rb +13 -27
  60. data/lib/warped/emails/components/align.rb +21 -0
  61. data/lib/warped/emails/components/base.rb +116 -0
  62. data/lib/warped/emails/components/button.rb +58 -0
  63. data/lib/warped/emails/components/divider.rb +15 -0
  64. data/lib/warped/emails/components/heading.rb +65 -0
  65. data/lib/warped/emails/components/layouts/columns.rb +36 -0
  66. data/lib/warped/emails/components/layouts/cta.rb +38 -0
  67. data/lib/warped/emails/components/layouts/main.rb +34 -0
  68. data/lib/warped/emails/components/link.rb +36 -0
  69. data/lib/warped/emails/components/spacer.rb +15 -0
  70. data/lib/warped/emails/components/stepper.rb +104 -0
  71. data/lib/warped/emails/components/table.rb +37 -0
  72. data/lib/warped/emails/components/text.rb +67 -0
  73. data/lib/warped/emails/helpers.rb +26 -0
  74. data/lib/warped/emails/slottable.rb +61 -0
  75. data/lib/warped/emails/styleable.rb +160 -0
  76. data/lib/warped/engine.rb +19 -0
  77. data/lib/warped/queries/filter.rb +32 -12
  78. data/lib/warped/table/action.rb +33 -0
  79. data/lib/warped/table/column.rb +34 -0
  80. data/lib/warped/version.rb +1 -1
  81. data/lib/warped.rb +2 -0
  82. data/warped.gemspec +1 -1
  83. metadata +73 -7
  84. data/lib/warped/emails/.keep +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 967b7e175b3e607946af10eef1af2cd6400d8bcb294a7a49a3298568b6234b25
4
- data.tar.gz: f959ca8e38e009e9a59daecab21fb4ae855e2f3ad516a660b69c29c6acb219f3
3
+ metadata.gz: c1c6444d0d93fbbfa88436418e69edc9e44e228402d56becbc99bd7eae122f14
4
+ data.tar.gz: 4eeeb9b833549db2c33a67fa73627e3e55f27dda5178d9f2f377b989f64739a0
5
5
  SHA512:
6
- metadata.gz: 5665f91cf7cb50151006cf7852283c4a5da5e05506a039eb70a8464738fee9b1c7903f530e1301489a9788f5781ef10e095efdd4acd19fe7e9fa253845b6beec
7
- data.tar.gz: b6c2c71ab7de2ac911d599135a166a00e5a62870be1182c445f994656186d4f7fabf156fd6c513b5699ca3747ba9cd4351560b2441703ceca0576059ae4cf8f0
6
+ metadata.gz: 486f3074c354576fb33e04df666248b27e4b0f2dd13a6ce1256c9ec66c9ad786a158010b199b80f11761b5c5bcc83af5ee3f6c01b5a631de83da53a706d5c520
7
+ data.tar.gz: 2a3f730c41a5f42c92aac9c3e2708caf0f803f157771a25be75b524304ec1f7203056ae4f7bc40675b7c2aef779f7dce7a2e54cb6a494ded18261361eef84237
data/.rubocop.yml CHANGED
@@ -18,13 +18,38 @@ Layout/LineLength:
18
18
  Exclude:
19
19
  - "lib/warped/queries/paginate.rb"
20
20
 
21
+ Metrics/AbcSize:
22
+ Exclude:
23
+ - "lib/warped/controllers/filterable/ui.rb"
24
+ - "lib/warped/controllers/pageable/ui.rb"
25
+ - "lib/warped/controllers/sortable/ui.rb"
26
+ - "lib/warped/emails/components/**/*.rb"
27
+ - "lib/warped/queries/filter.rb"
28
+
21
29
  Metrics/BlockLength:
22
30
  Exclude:
31
+ - "lib/warped/emails/components/**/*.rb"
23
32
  - "spec/**/*"
24
33
 
34
+ Metrics/ParameterLists:
35
+ Exclude:
36
+ - "lib/warped/emails/components/**/*.rb"
37
+
38
+ Metrics/PerceivedComplexity:
39
+ Exclude:
40
+ - "lib/warped/controllers/pageable/ui.rb"
41
+
25
42
  Metrics/CyclomaticComplexity:
26
43
  Exclude:
44
+ - "lib/warped/controllers/pageable/ui.rb"
27
45
  - "lib/warped/queries/filter.rb"
28
46
 
29
47
  Metrics/MethodLength:
30
48
  Max: 20
49
+ Exclude:
50
+ - lib/warped/queries/filter.rb
51
+
52
+ Style/OptionalArguments:
53
+ Exclude:
54
+ - lib/warped/emails/components/button.rb
55
+ - lib/warped/emails/components/link.rb
data/Gemfile CHANGED
@@ -10,5 +10,3 @@ gem "rake", "~> 13.0"
10
10
  gem "rspec", "~> 3.0"
11
11
 
12
12
  gem "rubocop", "~> 1.21"
13
-
14
- gem "debug", "~> 1.5", platforms: %i[mri mingw x64_mingw]
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- warped (0.1.0)
5
- rails (>= 6.0, < 8.0)
4
+ warped (1.0.0)
5
+ rails (>= 7.1, <= 8.0)
6
6
  zeitwerk (>= 2.4)
7
7
 
8
8
  GEM
@@ -90,12 +90,8 @@ GEM
90
90
  connection_pool (2.4.1)
91
91
  crass (1.0.6)
92
92
  date (3.3.4)
93
- debug (1.9.1)
94
- irb (~> 1.10)
95
- reline (>= 0.3.8)
96
93
  diff-lcs (1.5.1)
97
- drb (2.2.0)
98
- ruby2_keywords
94
+ drb (2.2.1)
99
95
  erubi (1.12.0)
100
96
  globalid (1.2.1)
101
97
  activesupport (>= 6.1)
@@ -115,7 +111,7 @@ GEM
115
111
  net-imap
116
112
  net-pop
117
113
  net-smtp
118
- marcel (1.0.2)
114
+ marcel (1.0.4)
119
115
  mini_mime (1.1.5)
120
116
  minitest (5.22.2)
121
117
  mutex_m (0.2.0)
@@ -129,8 +125,18 @@ GEM
129
125
  net-smtp (0.4.0.1)
130
126
  net-protocol
131
127
  nio4r (2.7.0)
128
+ nokogiri (1.16.2-aarch64-linux)
129
+ racc (~> 1.4)
130
+ nokogiri (1.16.2-arm-linux)
131
+ racc (~> 1.4)
132
132
  nokogiri (1.16.2-arm64-darwin)
133
133
  racc (~> 1.4)
134
+ nokogiri (1.16.2-x86-linux)
135
+ racc (~> 1.4)
136
+ nokogiri (1.16.2-x86_64-darwin)
137
+ racc (~> 1.4)
138
+ nokogiri (1.16.2-x86_64-linux)
139
+ racc (~> 1.4)
134
140
  parallel (1.24.0)
135
141
  parser (3.3.0.5)
136
142
  ast (~> 2.4.1)
@@ -180,7 +186,7 @@ GEM
180
186
  rdoc (6.6.2)
181
187
  psych (>= 4.0.0)
182
188
  regexp_parser (2.9.0)
183
- reline (0.4.2)
189
+ reline (0.4.3)
184
190
  io-console (~> 0.5)
185
191
  rexml (3.2.6)
186
192
  rspec (3.13.0)
@@ -196,7 +202,7 @@ GEM
196
202
  diff-lcs (>= 1.2.0, < 2.0)
197
203
  rspec-support (~> 3.13.0)
198
204
  rspec-support (3.13.1)
199
- rubocop (1.60.2)
205
+ rubocop (1.61.0)
200
206
  json (~> 2.3)
201
207
  language_server-protocol (>= 3.17.0)
202
208
  parallel (~> 1.10)
@@ -207,12 +213,11 @@ GEM
207
213
  rubocop-ast (>= 1.30.0, < 2.0)
208
214
  ruby-progressbar (~> 1.7)
209
215
  unicode-display_width (>= 2.4.0, < 3.0)
210
- rubocop-ast (1.30.0)
211
- parser (>= 3.2.1.0)
216
+ rubocop-ast (1.31.1)
217
+ parser (>= 3.3.0.4)
212
218
  ruby-progressbar (1.13.0)
213
- ruby2_keywords (0.0.5)
214
219
  stringio (3.1.0)
215
- thor (1.3.0)
220
+ thor (1.3.1)
216
221
  timeout (0.4.1)
217
222
  tzinfo (2.0.6)
218
223
  concurrent-ruby (~> 1.0)
@@ -224,17 +229,18 @@ GEM
224
229
  zeitwerk (2.6.13)
225
230
 
226
231
  PLATFORMS
227
- arm64-darwin-21
228
- arm64-darwin-22
229
- arm64-darwin-23
232
+ aarch64-linux
233
+ arm-linux
234
+ arm64-darwin
235
+ x86-linux
236
+ x86_64-darwin
230
237
  x86_64-linux
231
238
 
232
239
  DEPENDENCIES
233
- debug (~> 1.5)
234
240
  rake (~> 13.0)
235
241
  rspec (~> 3.0)
236
242
  rubocop (~> 1.21)
237
243
  warped!
238
244
 
239
245
  BUNDLED WITH
240
- 2.3.26
246
+ 2.5.6
data/README.md CHANGED
@@ -7,7 +7,7 @@ Develop rails applications at the speed of thought. Warped is a collection of to
7
7
 
8
8
  Install the gem and add to the Rails application's Gemfile by executing:
9
9
 
10
- $ bundle add warped-rails
10
+ $ bundle add warped
11
11
 
12
12
  Then run the generator to create the configuration file:
13
13
 
@@ -15,6 +15,34 @@ Then run the generator to create the configuration file:
15
15
 
16
16
  The generator will create a file at `config/initializers/warped.rb` with the default configuration.
17
17
 
18
+ ### Installation for rails fullstack apps
19
+
20
+ For using the views provided by the gem, your app will need to have the following:
21
+ 1. [rails/importmap-rails](https://github.com/rails/importmap-rails) configured
22
+ 2. [hotwired/stimulus-rails](https://github.com/hotwired/stimulus-rails) configured
23
+
24
+ Add the following to your `config/importmap.rb`:
25
+
26
+ ```ruby
27
+ pin_all_from "app/javascript/controllers/warped", under: "controllers/warped"
28
+ ```
29
+
30
+ > This will import all the stimulus controllers provided by the gem.
31
+
32
+ Add the following to your `app/javascript/controllers/index.js`, bellow the `eagerLoadControllersFrom("controllers", application)` line:
33
+ ```javascript
34
+ eagerLoadControllersFrom("warped/controllers", application)
35
+ ```
36
+
37
+ Include the css provided by the gem in your `app/views/layouts/application.html.erb`:
38
+ ```erb
39
+ <%= stylesheet_link_tag "warped/base" %>
40
+ <%= stylesheet_link_tag "warped/table" %>
41
+ <%= stylesheet_link_tag "warped/search" %>
42
+ <%= stylesheet_link_tag "warped/filters" %>
43
+ <%= stylesheet_link_tag "warped/pagination" %>
44
+ ```
45
+
18
46
  ## Usage
19
47
 
20
48
  Warped provides utilities for making it easier to develop rails applications. The utilities are organized into modules and can be used by including the module in the class that needs the utility.
@@ -56,96 +84,10 @@ GET /users?name=John
56
84
  GET /users?email=john@example.com
57
85
  GET /users?created_at=2021-01-01
58
86
  ```
87
+ > [!TIP]
88
+ > It's highly recommended to use the type-safe filter methods provided by the gem. This prevents invalid queries from being executed on the database. See the [Filterable documentation](docs/controllers/FILTERABLE.md) for more information.
59
89
 
60
- ##### Referencing tables in the filterable fields
61
-
62
- The `filterable_by` method can also be used to reference fields in associated tables. For example, to filter the users by the name of the company they work for, the following can be done:
63
-
64
- ```ruby
65
- class UsersController < ApplicationController
66
- include Warped::Controllers::Filterable
67
-
68
- filterable_by :name, :email, :created_at, 'companies.name'
69
-
70
- def index
71
- users = filter(User.joins(:company))
72
- render json: users
73
- end
74
- end
75
- ```
76
-
77
- Request examples:
78
- ```
79
- GET /users?name=John
80
- GET /users?companies.name=Acme
81
- ```
82
-
83
- ##### Renaming the filter query parameters
84
-
85
- If you don't want to use the field name as the query parameter (as to not expose the database schema, or when joining the same table multiple times),
86
- you can specify the query parameter to use for each field:
87
-
88
- ```ruby
89
- class UsersController < ApplicationController
90
- include Warped::Controllers::Filterable
91
-
92
- filterable_by 'companies.name' => :company_name, 'users.name' => :user_name
93
-
94
- def index
95
- users = filter(User.join(:company))
96
- render json: users
97
- end
98
- end
99
- ```
100
-
101
- Request examples:
102
- ```
103
- GET /users?user_name=John
104
- GET /users?company_name=Acme
105
- ```
106
-
107
- ##### Using filters other than `eq`
108
-
109
- By default, the `filter` method will use the `eq` filter method to filter the records. If you want to use a different filter method, you can specify the filter "relation" in the query parameter:
110
-
111
- ```ruby
112
- class UsersController < ApplicationController
113
- include Warped::Controllers::Filterable
114
-
115
- filterable_by :name, :age
116
-
117
- def index
118
- users = filter(User.all)
119
- render json: users
120
- end
121
- end
122
- ```
123
-
124
- Request examples:
125
- ```
126
- GET /users?name=John # returns users with name John
127
- GET /users?name[]=John&name[]=Jane # returns users where the name is in ('John', 'Jane')
128
- GET /users?age.rel=is_null # returns users where the age is null
129
- GET /users?age.rel=is_not_null # returns users where the age is not null
130
- GET /users?age.rel=between&age[]=18&age[]=30 # returns users with age between 18 and 30
131
- GET /users?age.rel=%3E%0A&age=18 # returns users with age greater than 18, %3E%0A is url encoded for ">"
132
- ```
133
-
134
- The full list of filter relations is:
135
- - `=` (default) - equals
136
- - `!=` - not equals
137
- - `>` - greater than
138
- - `>=` - greater than or equals
139
- - `<` - less than
140
- - `<=` - less than or equals
141
- - `between` - between (requires two values)
142
- - `in` - in (default when multiple values are provided)
143
- - `not_in` - not in (requires multiple values)
144
- - `starts_with` - starts with
145
- - `ends_with` - ends with
146
- - `contains` - contains
147
- - `is_null` - is null (does not require a value)
148
- - `is_not_null` - is not null (does not require a value)
90
+ [Complete documentation for Warped::Controllers::Filterable](docs/controllers/FILTERABLE.md).
149
91
 
150
92
  #### Warped::Controllers::Searchable
151
93
 
@@ -181,67 +123,7 @@ GET /users?q=John
181
123
  # calls #search(User.all, search_term: 'John', model_search_scope: :search) in the controller
182
124
  ```
183
125
 
184
- ##### Customizing the search query parameter
185
-
186
- You can customize the default query parameter by:
187
- 1. Passing fetching the fetch term from the params hash, and passing it directly to the search method:
188
-
189
- ```ruby
190
- class UsersController < ApplicationController
191
- include Warped::Controllers::Searchable
192
-
193
- def index
194
- # This will use the query parameter `term` instead of `q`
195
- users = search(User.all, search_term: params[:term])
196
- render json: users
197
- end
198
- end
199
- ```
200
-
201
- 2. Overriding the `search_param` method in the controller
202
-
203
- ```ruby
204
- class UsersController < ApplicationController
205
- include Warped::Controllers::Searchable
206
-
207
- def index
208
- # This will use the query parameter `term` instead of `q`
209
- users = search(User.all)
210
- render json: users
211
- end
212
-
213
- private
214
-
215
- def search_param
216
- :term
217
- end
218
- end
219
- ```
220
-
221
- 3. Calling #searchable_by in the controller and overriding the default query parameter
222
-
223
- ```ruby
224
- # app/models/user.rb
225
- class User < ApplicationRecord
226
- include PgSearch::Model
227
- pg_search_scope :search_by_word, against: :name, using: { tsearch: { any_word: true } }
228
- end
229
-
230
-
231
- # app/controllers/users_controller.rb
232
- class UsersController < ApplicationController
233
- include Warped::Controllers::Searchable
234
-
235
- # This will use the query parameter `term` instead of `q`
236
- # and the search scope `search_by_word` instead of the default
237
- searchable_by :search_by_word, param: :term
238
-
239
- def index
240
- users = search(User.all)
241
- render json: users
242
- end
243
- end
244
- ```
126
+ [Complete documentation for Warped::Controllers::Searchable](docs/controllers/SEARCHABLE.md).
245
127
 
246
128
  #### Warped::Controllers::Sortable
247
129
 
@@ -261,6 +143,8 @@ class UsersController < ApplicationController
261
143
  end
262
144
  end
263
145
  ```
146
+ > [!TIP]
147
+ > It's highly recommended to use the type-safe sort methods provided by the gem. This prevents invalid queries from being executed on the database. See the [Sortable documentation](docs/controllers/SORTABLE.md) for more information.
264
148
 
265
149
  This will use the query parameter `sort_key` and `sort_direction` to sort the records.
266
150
  - The default sort direction is `desc`.
@@ -291,52 +175,8 @@ Request examples:
291
175
  ```
292
176
  GET /users # sort by id in descending order
293
177
  ```
294
- ##### Referencing tables in the sortable fields
295
-
296
- Like the `filterable_by` method, the `sortable_by` method can also be used to reference fields in associated tables.
297
-
298
- ```ruby
299
- class UsersController < ApplicationController
300
- include Warped::Controllers::Sortable
301
-
302
- sortable_by :name, 'companies.name'
303
-
304
- def index
305
- users = sort(User.joins(:company))
306
- render json: users
307
- end
308
- end
309
- ```
310
-
311
- Request examples:
312
- ```
313
- GET /users?sort_key=name # sort by name in descending order
314
- GET /users?sort_key=companies.name&sort_direction=asc # sort by company name in ascending order
315
- ```
316
-
317
- ##### Renaming the sort query parameters
318
-
319
- If you don't want to use the field name as the query parameter (as to not expose the database schema, or when joining the same table multiple times),
320
- you can specify the query parameter to use for each field:
321
-
322
- ```ruby
323
- class UsersController < ApplicationController
324
- include Warped::Controllers::Sortable
325
178
 
326
- sortable_by 'companies.name' => :company_name, 'users.name' => :user_name
327
-
328
- def index
329
- users = sort(User.join(:company))
330
- render json: users
331
- end
332
- end
333
- ```
334
-
335
- Request examples:
336
- ```
337
- GET /users?sort_key=user_name # sort by name in descending order
338
- GET /users?sort_key=company_name&sort_direction=asc # sort by company name in ascending order
339
- ```
179
+ [Complete documentation for Warped::Controllers::Sortable](docs/controllers/SORTABLE.md).
340
180
 
341
181
  #### Warped::Controllers::Pageable
342
182
 
@@ -351,7 +191,7 @@ class UsersController < ApplicationController
351
191
 
352
192
  def index
353
193
  users = paginate(User.all)
354
- render json: users, meta: page_info
194
+ render json: users, meta: pagination
355
195
  end
356
196
  end
357
197
  ```
@@ -363,81 +203,111 @@ GET /users?per_page=25 # returns the first page of users with 25 records per pag
363
203
  GET /users?page=2&per_page=25 # returns the second page of users with 25 records per page
364
204
  ```
365
205
 
366
- ##### Accessing the pagination information
206
+ [Complete documentation for Warped::Controllers::Pageable](docs/controllers/PAGEABLE.md).
207
+
208
+ #### Warped::Controllers::Tabulatable
209
+
210
+ The `Tabulatable` concern provides a method to filter, sort, search, and paginate the records in a controller's action.
211
+
212
+ The method `tabulate` is used to filter, sort, search, and paginate the records. So, in the case that the controller action needs to filter, sort, search, and paginate the records, the `tabulate` method can be used.
367
213
 
368
- The `page_info` method can be used to access the pagination information.
214
+ The tabulatable concern provides the `tabulatable_by` method, which passes the values to `filterable_by` and `sortable_by`.
369
215
 
370
216
  ```ruby
371
217
  class UsersController < ApplicationController
372
- include Warped::Controllers::Pageable
218
+ include Warped::Controllers::Tabulatable
219
+
220
+ tabulatable_by :name, :email, :created_at
373
221
 
374
222
  def index
375
- users = paginate(User.all)
376
- render json: users, meta: page_info
223
+ users = tabulate(User.all)
224
+ render json: users, meta: pagination
377
225
  end
378
226
  end
379
227
  ```
380
228
 
381
- `page_info` returns a hash with
382
- - `page` - the current page
383
- - `per_page` - the number of records per page
384
- - `total_pages` - the total number of pages
385
- - `total_count` - the number of records in the scope
386
- - `next-page` - the next page number
387
- - `prev-page` - the previous page number
229
+ Request examples:
230
+ ```
231
+ GET /users?age[]=18&age[]=30&age.rel=between&sort_key=name&sort_direction=asc&q=John&page=2&per_page=10
232
+ # returns the second page of users with 10 records per page, where the age is between 18 and 30, sorted by name in ascending order, and searched by the term John
233
+ ```
234
+
235
+ Just like `paginate`, when calling the `tabulate` method in the controller action, the `pagination` method can be used to access the pagination information.
388
236
 
237
+ [Complete documentation for Warped::Controllers::Tabulatable](docs/controllers/TABULATABLE.md).
389
238
 
390
- ##### Customizing the pagination behavior
239
+ ### Views
391
240
 
392
- By default, the `paginate` method will paginate the scope in pages of size 10, and will return the first page if the `page` query parameter is not provided.
241
+ Warped comes with a set of partials and stimulus controllers that can be used to make development of index views easier/faster.
393
242
 
394
- Additionally, there's a limit of `100` records per page. So, if the `per_page` query parameter is greater than `100`, the pagination will use `100` as the page size.
243
+ In order to use the views provided by the gem, warped provides ::Ui modules for each of the before menttioned concerns. `These Warped::Controllers::<ConcernName>::Ui` provide the helper methods needed by the partials in order to work.
395
244
 
396
- You can customize the default page size and the default page number by overriding the `default_per_page` value in the controller.
245
+ The partials are:
246
+ - `Warped::Controllers::Filterable::Ui` -> `warped/_filters.html.erb`
247
+ - `Warped::Controllers::Searchable::Ui` -> `warped/_search.html.erb`
248
+ - `Warped::Controllers::Pageable::Ui` -> `warped/_pagination.html.erb`
249
+ - `Warped::Controllers::Tabulatable::Ui` -> `warped/_table.html.erb`
397
250
 
251
+ Example:
398
252
  ```ruby
399
- class UsersController < ApplicationController
400
- include Warped::Controllers::Pageable
253
+ # app/models/user.rb
254
+ class User < ApplicationRecord
255
+ # first_name :string
256
+ # last_name :string
257
+ # email :string
258
+ # created_at :datetime
401
259
 
402
- # This will set the default page size to 25 when the `per_page` query parameter is not provided
403
- self.default_per_page = 25
260
+ scope :search, ->(query) { where('first_name LIKE ? OR last_name LIKE ? OR email LIKE ?', "%#{query}%", "%#{query}%", "%#{query}%") }
404
261
 
405
- def index
406
- users = paginate(User.all)
407
- render json: users, meta: page_info
408
- end
409
262
  end
410
- ```
411
263
 
412
- #### Warped::Controllers::Tabulatable
413
-
414
- The `Tabulatable` concern provides a method to filter, sort, search, and paginate the records in a controller's action.
415
-
416
- The method `tabulate` is used to filter, sort, search, and paginate the records. So, in the case that the controller action needs to filter, sort, search, and paginate the records, the `tabulate` method can be used.
264
+ # app/controllers/users_controller.rb
265
+ class UsersController < ApplicationControlelr
266
+ include Warped::Controllers::Tabulatable::Ui
417
267
 
418
- The tabulatable concern provides the `tabulatable_by` method, which passes the values to `filterable_by` and `sortable_by`.
268
+ tabulatable_by name: { kind: :string }, email: { kind: :string }, created_at: { kind: :date_time }
419
269
 
420
- ```ruby
421
- class UsersController < ApplicationController
422
- include Warped::Controllers::Tabulatable
270
+ def index
271
+ @users = tabulate(User.all)
272
+ end
423
273
 
424
- tabulatable_by :name, :email, :created_at
274
+ def show
275
+ @user = User.find(params[:id])
276
+ end
425
277
 
426
- def index
427
- users = tabulate(User.all)
428
- render json: users, meta: page_info
278
+ def destroy
279
+ User.find(params[:id]).destroy
280
+ redirect_to users_path
429
281
  end
430
282
  end
431
283
  ```
432
284
 
433
- Request examples:
434
- ```
435
- GET /users?age[]=18&age[]=30&age.rel=between&sort_key=name&sort_direction=asc&q=John&page=2&per_page=10
436
- # returns the second page of users with 10 records per page, where the age is between 18 and 30, sorted by name in ascending order, and searched by the term John
437
- ```
438
-
439
- Just like `paginate`, when calling the `tabulate` method in the controller action, the `page_info` method can be used to access the pagination information.
440
-
285
+ ```erb
286
+ # app/views/users/index.html.erb
287
+ <%= render "warped/table", collection: @users,
288
+ path: users_path,
289
+ columns: [
290
+ Warped::Table::Column.new(:id, 'ID'),
291
+ Warped::Table::Column.new(:full_name, 'Full Name', method: ->(user) { [user.first_name, user.last_name].compact_blank.join(" ") }),
292
+ Warped::Table::Column.new(:email),
293
+ Warped::Table::Column.new(:created_at, 'Created At', method: ->(user) { user.created_at.strftime('%Y-%m-%d') })
294
+ ],
295
+ actions: [
296
+ Warped::Table::Action.new('Show', ->(user) { user_path(user) }),
297
+ Warped::Table::Action.new('Delete', ->(user) { user_path(user) }, turbo_method: :delete, turbo_confirm: 'Are you sure?')
298
+ ],
299
+ turbo_action: :replace
300
+ %>
301
+ ```
302
+ The code above, renders a table with:
303
+ - The columns `ID`, `Full Name`, `Email`, and `Created At`, all of which are sortable.
304
+ - The actions `Show` and `Delete` for each user. The action `Delete` will use the `DELETE` method and will ask for confirmation before executing the action.
305
+ - The filters for the `name`, `email`, and `created_at` fields.
306
+ - A search input that will search the users by the term provided.
307
+ - A pagination component that will paginate the users, showing 10 users per page by default.
308
+ - The table filtering/sorting/searching/pagination will be done using the [turbo-action=replace](https://turbo.hotwired.dev/handbook/frames#promoting-a-frame-navigation-to-a-page-visit).
309
+
310
+ [Complete documentation for Warped built-in Partials](docs/controllers/views/PARTIALS.md).
441
311
  ### Services
442
312
 
443
313
  The gem provides a `Warped::Service::Base` class that can be used to create services in a rails application.
@@ -492,33 +362,7 @@ PrintService.call # Executes new.call, prints "Hello, John!"
492
362
  PrintService.call('world') # Executes new('world').call, prints "Hello, world!"
493
363
  ```
494
364
 
495
- ##### Using services as job classes in the background
496
-
497
- The `Warped::Service::Base` class provides a class method `.enable_job!` that can be used to enable the service to be used as a job class.
498
-
499
- ```ruby
500
- class PrintService < Warped::Service::Base
501
- enable_job!
502
-
503
- def call
504
- puts 'Hello, world!'
505
- end
506
- end
507
- ```
508
-
509
- The `enable_job!` method will define a `PrintService::Job` class that inherits from `Warped::Jobs::Base` and calls the `call` method on the service instance.
510
-
511
- ```ruby
512
- PrintService.call_later # Executes PrintService::Job.perform_later
513
- PrintService::Job.perform_later # Executes PrintService.new.call in the background
514
- ```
515
-
516
- call_later and perform_later will pass the arguments to the `initialize` method of the service class, and then call the `call` method on the new instance.
517
-
518
- ```ruby
519
- PrintService.call_later('world') # Executes PrintService::Job.perform_later('world')
520
- PrintService::Job.perform_later('world') # Executes PrintService.new('world').call in the background
521
- ```
365
+ [Complete documentation for Warped::Services](docs/services/README.md).
522
366
 
523
367
  ### Jobs
524
368
 
@@ -543,6 +387,8 @@ Warped.configure do |config|
543
387
  end
544
388
  ```
545
389
 
390
+ [Complete documentation for Warped::Jobs](docs/jobs/README.md).
391
+
546
392
 
547
393
  ## Development
548
394
 
@@ -0,0 +1,2 @@
1
+ //= link_directory ../stylesheets/warped .css
2
+ //= link_directory ../stylesheets/warped .js