auxiliary_rails 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +26 -0
  3. data/.rubocop.yml +31 -3
  4. data/.rubocop_todo.yml +3 -19
  5. data/.ruby-version +1 -1
  6. data/.yardopts +5 -0
  7. data/CHANGELOG.md +39 -2
  8. data/CODE_OF_CONDUCT.md +128 -0
  9. data/CONTRIBUTING.md +0 -6
  10. data/Gemfile.lock +164 -132
  11. data/README.md +267 -5
  12. data/auxiliary_rails.gemspec +18 -13
  13. data/bin/rspec +29 -0
  14. data/bin/rubocop +29 -0
  15. data/bitbucket-pipelines.yml +35 -0
  16. data/lib/auxiliary_rails/application/command.rb +53 -0
  17. data/lib/auxiliary_rails/application/error.rb +50 -0
  18. data/lib/auxiliary_rails/application/form.rb +31 -0
  19. data/lib/auxiliary_rails/application/query.rb +75 -0
  20. data/lib/auxiliary_rails/application/service.rb +42 -0
  21. data/lib/auxiliary_rails/cli.rb +18 -5
  22. data/lib/auxiliary_rails/concerns/callable.rb +23 -0
  23. data/lib/auxiliary_rails/concerns/errorable.rb +22 -0
  24. data/lib/auxiliary_rails/concerns/performable.rb +120 -0
  25. data/lib/auxiliary_rails/railtie.rb +2 -1
  26. data/lib/auxiliary_rails/version.rb +1 -1
  27. data/lib/auxiliary_rails/view_helpers/display_helper.rb +30 -0
  28. data/lib/auxiliary_rails/view_helpers.rb +4 -0
  29. data/lib/auxiliary_rails.rb +7 -3
  30. data/lib/generators/auxiliary_rails/command_generator.rb +1 -1
  31. data/lib/generators/auxiliary_rails/install_commands_generator.rb +5 -0
  32. data/lib/generators/auxiliary_rails/install_errors_controller_generator.rb +31 -0
  33. data/lib/generators/auxiliary_rails/install_generator.rb +1 -1
  34. data/lib/generators/auxiliary_rails/service_generator.rb +48 -0
  35. data/lib/generators/auxiliary_rails/templates/application_error_template.rb +1 -1
  36. data/lib/generators/auxiliary_rails/templates/commands/application_command_template.rb +1 -1
  37. data/lib/generators/auxiliary_rails/templates/commands/command_spec_template.rb +1 -1
  38. data/lib/generators/auxiliary_rails/templates/commands/command_template.rb +2 -2
  39. data/lib/generators/auxiliary_rails/templates/commands/commands.en_template.yml +5 -0
  40. data/lib/generators/auxiliary_rails/templates/errors_controller/errors_controller_template.rb +15 -0
  41. data/lib/generators/auxiliary_rails/templates/errors_controller/not_found_template.html.erb +2 -0
  42. data/lib/generators/auxiliary_rails/templates/errors_controller/show_template.html.erb +1 -0
  43. data/lib/generators/auxiliary_rails/templates/errors_controller/unacceptable_template.html.erb +2 -0
  44. data/lib/generators/auxiliary_rails/templates/services/service_spec_template.rb +5 -0
  45. data/lib/generators/auxiliary_rails/templates/services/service_template.rb +10 -0
  46. data/templates/rails/elementary.rb +39 -10
  47. metadata +87 -32
  48. data/lib/auxiliary_rails/abstract_command.rb +0 -95
  49. data/lib/auxiliary_rails/abstract_error.rb +0 -7
  50. data/lib/generators/auxiliary_rails/install_rubocop_generator.rb +0 -29
  51. data/lib/generators/auxiliary_rails/templates/rubocop/rubocop_auxiliary_rails_template.yml +0 -65
  52. data/lib/generators/auxiliary_rails/templates/rubocop/rubocop_template.yml +0 -11
data/Gemfile.lock CHANGED
@@ -1,177 +1,209 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- auxiliary_rails (0.2.0)
4
+ auxiliary_rails (0.4.0)
5
+ dry-core
6
+ dry-initializer
5
7
  dry-initializer-rails
8
+ rails (>= 5.2)
6
9
  thor
7
10
 
8
11
  GEM
9
12
  remote: https://rubygems.org/
10
13
  specs:
11
- actioncable (6.0.2.1)
12
- actionpack (= 6.0.2.1)
14
+ actioncable (7.0.3.1)
15
+ actionpack (= 7.0.3.1)
16
+ activesupport (= 7.0.3.1)
13
17
  nio4r (~> 2.0)
14
18
  websocket-driver (>= 0.6.1)
15
- actionmailbox (6.0.2.1)
16
- actionpack (= 6.0.2.1)
17
- activejob (= 6.0.2.1)
18
- activerecord (= 6.0.2.1)
19
- activestorage (= 6.0.2.1)
20
- activesupport (= 6.0.2.1)
19
+ actionmailbox (7.0.3.1)
20
+ actionpack (= 7.0.3.1)
21
+ activejob (= 7.0.3.1)
22
+ activerecord (= 7.0.3.1)
23
+ activestorage (= 7.0.3.1)
24
+ activesupport (= 7.0.3.1)
21
25
  mail (>= 2.7.1)
22
- actionmailer (6.0.2.1)
23
- actionpack (= 6.0.2.1)
24
- actionview (= 6.0.2.1)
25
- activejob (= 6.0.2.1)
26
+ net-imap
27
+ net-pop
28
+ net-smtp
29
+ actionmailer (7.0.3.1)
30
+ actionpack (= 7.0.3.1)
31
+ actionview (= 7.0.3.1)
32
+ activejob (= 7.0.3.1)
33
+ activesupport (= 7.0.3.1)
26
34
  mail (~> 2.5, >= 2.5.4)
35
+ net-imap
36
+ net-pop
37
+ net-smtp
27
38
  rails-dom-testing (~> 2.0)
28
- actionpack (6.0.2.1)
29
- actionview (= 6.0.2.1)
30
- activesupport (= 6.0.2.1)
31
- rack (~> 2.0, >= 2.0.8)
39
+ actionpack (7.0.3.1)
40
+ actionview (= 7.0.3.1)
41
+ activesupport (= 7.0.3.1)
42
+ rack (~> 2.0, >= 2.2.0)
32
43
  rack-test (>= 0.6.3)
33
44
  rails-dom-testing (~> 2.0)
34
45
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
35
- actiontext (6.0.2.1)
36
- actionpack (= 6.0.2.1)
37
- activerecord (= 6.0.2.1)
38
- activestorage (= 6.0.2.1)
39
- activesupport (= 6.0.2.1)
46
+ actiontext (7.0.3.1)
47
+ actionpack (= 7.0.3.1)
48
+ activerecord (= 7.0.3.1)
49
+ activestorage (= 7.0.3.1)
50
+ activesupport (= 7.0.3.1)
51
+ globalid (>= 0.6.0)
40
52
  nokogiri (>= 1.8.5)
41
- actionview (6.0.2.1)
42
- activesupport (= 6.0.2.1)
53
+ actionview (7.0.3.1)
54
+ activesupport (= 7.0.3.1)
43
55
  builder (~> 3.1)
44
56
  erubi (~> 1.4)
45
57
  rails-dom-testing (~> 2.0)
46
58
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
47
- activejob (6.0.2.1)
48
- activesupport (= 6.0.2.1)
59
+ activejob (7.0.3.1)
60
+ activesupport (= 7.0.3.1)
49
61
  globalid (>= 0.3.6)
50
- activemodel (6.0.2.1)
51
- activesupport (= 6.0.2.1)
52
- activerecord (6.0.2.1)
53
- activemodel (= 6.0.2.1)
54
- activesupport (= 6.0.2.1)
55
- activestorage (6.0.2.1)
56
- actionpack (= 6.0.2.1)
57
- activejob (= 6.0.2.1)
58
- activerecord (= 6.0.2.1)
59
- marcel (~> 0.3.1)
60
- activesupport (6.0.2.1)
62
+ activemodel (7.0.3.1)
63
+ activesupport (= 7.0.3.1)
64
+ activerecord (7.0.3.1)
65
+ activemodel (= 7.0.3.1)
66
+ activesupport (= 7.0.3.1)
67
+ activestorage (7.0.3.1)
68
+ actionpack (= 7.0.3.1)
69
+ activejob (= 7.0.3.1)
70
+ activerecord (= 7.0.3.1)
71
+ activesupport (= 7.0.3.1)
72
+ marcel (~> 1.0)
73
+ mini_mime (>= 1.1.0)
74
+ activesupport (7.0.3.1)
61
75
  concurrent-ruby (~> 1.0, >= 1.0.2)
62
- i18n (>= 0.7, < 2)
63
- minitest (~> 5.1)
64
- tzinfo (~> 1.1)
65
- zeitwerk (~> 2.2)
66
- ast (2.4.0)
76
+ i18n (>= 1.6, < 2)
77
+ minitest (>= 5.1)
78
+ tzinfo (~> 2.0)
79
+ ast (2.4.2)
67
80
  builder (3.2.4)
68
- coderay (1.1.2)
69
- concurrent-ruby (1.1.5)
70
- crass (1.0.5)
71
- diff-lcs (1.3)
72
- dry-initializer (3.0.2)
81
+ coderay (1.1.3)
82
+ concurrent-ruby (1.1.10)
83
+ crass (1.0.6)
84
+ diff-lcs (1.5.0)
85
+ digest (3.1.0)
86
+ dry-core (0.8.1)
87
+ concurrent-ruby (~> 1.0)
88
+ dry-initializer (3.1.1)
73
89
  dry-initializer-rails (3.1.1)
74
90
  dry-initializer (>= 2.4, < 4)
75
91
  rails (> 3.0)
76
- erubi (1.9.0)
77
- globalid (0.4.2)
78
- activesupport (>= 4.2.0)
79
- i18n (1.7.0)
92
+ erubi (1.11.0)
93
+ globalid (1.0.0)
94
+ activesupport (>= 5.0)
95
+ i18n (1.12.0)
80
96
  concurrent-ruby (~> 1.0)
81
- jaro_winkler (1.5.4)
82
- loofah (2.4.0)
97
+ loofah (2.18.0)
83
98
  crass (~> 1.0.2)
84
99
  nokogiri (>= 1.5.9)
85
100
  mail (2.7.1)
86
101
  mini_mime (>= 0.1.1)
87
- marcel (0.3.3)
88
- mimemagic (~> 0.3.2)
89
- method_source (0.9.2)
90
- mimemagic (0.3.3)
91
- mini_mime (1.0.2)
92
- mini_portile2 (2.4.0)
93
- minitest (5.13.0)
94
- nio4r (2.5.2)
95
- nokogiri (1.10.7)
96
- mini_portile2 (~> 2.4.0)
97
- parallel (1.19.1)
98
- parser (2.7.0.1)
99
- ast (~> 2.4.0)
100
- pry (0.12.2)
101
- coderay (~> 1.1.0)
102
- method_source (~> 0.9.0)
103
- rack (2.0.8)
104
- rack-test (1.1.0)
105
- rack (>= 1.0, < 3)
106
- rails (6.0.2.1)
107
- actioncable (= 6.0.2.1)
108
- actionmailbox (= 6.0.2.1)
109
- actionmailer (= 6.0.2.1)
110
- actionpack (= 6.0.2.1)
111
- actiontext (= 6.0.2.1)
112
- actionview (= 6.0.2.1)
113
- activejob (= 6.0.2.1)
114
- activemodel (= 6.0.2.1)
115
- activerecord (= 6.0.2.1)
116
- activestorage (= 6.0.2.1)
117
- activesupport (= 6.0.2.1)
118
- bundler (>= 1.3.0)
119
- railties (= 6.0.2.1)
120
- sprockets-rails (>= 2.0.0)
102
+ marcel (1.0.2)
103
+ method_source (1.0.0)
104
+ mini_mime (1.1.2)
105
+ mini_portile2 (2.8.0)
106
+ minitest (5.16.3)
107
+ net-imap (0.2.3)
108
+ digest
109
+ net-protocol
110
+ strscan
111
+ net-pop (0.1.1)
112
+ digest
113
+ net-protocol
114
+ timeout
115
+ net-protocol (0.1.3)
116
+ timeout
117
+ net-smtp (0.3.1)
118
+ digest
119
+ net-protocol
120
+ timeout
121
+ nio4r (2.5.8)
122
+ nokogiri (1.13.8)
123
+ mini_portile2 (~> 2.8.0)
124
+ racc (~> 1.4)
125
+ parallel (1.22.1)
126
+ parser (3.1.2.1)
127
+ ast (~> 2.4.1)
128
+ pry (0.14.1)
129
+ coderay (~> 1.1)
130
+ method_source (~> 1.0)
131
+ racc (1.6.0)
132
+ rack (2.2.4)
133
+ rack-test (2.0.2)
134
+ rack (>= 1.3)
135
+ rails (7.0.3.1)
136
+ actioncable (= 7.0.3.1)
137
+ actionmailbox (= 7.0.3.1)
138
+ actionmailer (= 7.0.3.1)
139
+ actionpack (= 7.0.3.1)
140
+ actiontext (= 7.0.3.1)
141
+ actionview (= 7.0.3.1)
142
+ activejob (= 7.0.3.1)
143
+ activemodel (= 7.0.3.1)
144
+ activerecord (= 7.0.3.1)
145
+ activestorage (= 7.0.3.1)
146
+ activesupport (= 7.0.3.1)
147
+ bundler (>= 1.15.0)
148
+ railties (= 7.0.3.1)
121
149
  rails-dom-testing (2.0.3)
122
150
  activesupport (>= 4.2.0)
123
151
  nokogiri (>= 1.6)
124
- rails-html-sanitizer (1.3.0)
152
+ rails-html-sanitizer (1.4.3)
125
153
  loofah (~> 2.3)
126
- railties (6.0.2.1)
127
- actionpack (= 6.0.2.1)
128
- activesupport (= 6.0.2.1)
154
+ railties (7.0.3.1)
155
+ actionpack (= 7.0.3.1)
156
+ activesupport (= 7.0.3.1)
129
157
  method_source
130
- rake (>= 0.8.7)
131
- thor (>= 0.20.3, < 2.0)
132
- rainbow (3.0.0)
133
- rake (13.0.1)
134
- rspec (3.9.0)
135
- rspec-core (~> 3.9.0)
136
- rspec-expectations (~> 3.9.0)
137
- rspec-mocks (~> 3.9.0)
138
- rspec-core (3.9.1)
139
- rspec-support (~> 3.9.1)
140
- rspec-expectations (3.9.0)
158
+ rake (>= 12.2)
159
+ thor (~> 1.0)
160
+ zeitwerk (~> 2.5)
161
+ rainbow (3.1.1)
162
+ rake (13.0.6)
163
+ regexp_parser (2.5.0)
164
+ rexml (3.2.5)
165
+ rspec (3.11.0)
166
+ rspec-core (~> 3.11.0)
167
+ rspec-expectations (~> 3.11.0)
168
+ rspec-mocks (~> 3.11.0)
169
+ rspec-core (3.11.0)
170
+ rspec-support (~> 3.11.0)
171
+ rspec-expectations (3.11.0)
141
172
  diff-lcs (>= 1.2.0, < 2.0)
142
- rspec-support (~> 3.9.0)
143
- rspec-mocks (3.9.1)
173
+ rspec-support (~> 3.11.0)
174
+ rspec-mocks (3.11.1)
144
175
  diff-lcs (>= 1.2.0, < 2.0)
145
- rspec-support (~> 3.9.0)
146
- rspec-support (3.9.2)
147
- rubocop (0.78.0)
148
- jaro_winkler (~> 1.5.1)
176
+ rspec-support (~> 3.11.0)
177
+ rspec-support (3.11.0)
178
+ rubocop (1.20.0)
149
179
  parallel (~> 1.10)
150
- parser (>= 2.6)
180
+ parser (>= 3.0.0.0)
151
181
  rainbow (>= 2.2.2, < 4.0)
182
+ regexp_parser (>= 1.8, < 3.0)
183
+ rexml
184
+ rubocop-ast (>= 1.9.1, < 2.0)
152
185
  ruby-progressbar (~> 1.7)
153
- unicode-display_width (>= 1.4.0, < 1.7)
154
- rubocop-performance (1.5.2)
155
- rubocop (>= 0.71.0)
156
- rubocop-rspec (1.37.1)
157
- rubocop (>= 0.68.1)
158
- ruby-progressbar (1.10.1)
159
- sprockets (4.0.0)
186
+ unicode-display_width (>= 1.4.0, < 3.0)
187
+ rubocop-ast (1.21.0)
188
+ parser (>= 3.1.1.0)
189
+ rubocop-performance (1.14.3)
190
+ rubocop (>= 1.7.0, < 2.0)
191
+ rubocop-ast (>= 0.4.0)
192
+ rubocop-rake (0.6.0)
193
+ rubocop (~> 1.0)
194
+ rubocop-rspec (2.11.1)
195
+ rubocop (~> 1.19)
196
+ ruby-progressbar (1.11.0)
197
+ strscan (3.0.4)
198
+ thor (1.2.1)
199
+ timeout (0.3.0)
200
+ tzinfo (2.0.5)
160
201
  concurrent-ruby (~> 1.0)
161
- rack (> 1, < 3)
162
- sprockets-rails (3.2.1)
163
- actionpack (>= 4.0)
164
- activesupport (>= 4.0)
165
- sprockets (>= 3.0.0)
166
- thor (1.0.1)
167
- thread_safe (0.3.6)
168
- tzinfo (1.2.6)
169
- thread_safe (~> 0.1)
170
- unicode-display_width (1.6.0)
171
- websocket-driver (0.7.1)
202
+ unicode-display_width (2.2.0)
203
+ websocket-driver (0.7.5)
172
204
  websocket-extensions (>= 0.1.0)
173
- websocket-extensions (0.1.4)
174
- zeitwerk (2.2.2)
205
+ websocket-extensions (0.1.5)
206
+ zeitwerk (2.6.0)
175
207
 
176
208
  PLATFORMS
177
209
  ruby
@@ -180,12 +212,12 @@ DEPENDENCIES
180
212
  auxiliary_rails!
181
213
  bundler (~> 2.0)
182
214
  pry
183
- rails (>= 5.2, < 7)
184
215
  rake
185
216
  rspec (~> 3.8)
186
- rubocop
217
+ rubocop (= 1.20.0)
187
218
  rubocop-performance
219
+ rubocop-rake
188
220
  rubocop-rspec
189
221
 
190
222
  BUNDLED WITH
191
- 2.0.2
223
+ 2.1.4
data/README.md CHANGED
@@ -11,12 +11,15 @@ Collection of classes, configs, scripts, generators for Ruby on Rails helping yo
11
11
  Add one of these lines to your application's `Gemfile`:
12
12
 
13
13
  ```ruby
14
- # version released to RubyGems
14
+ # version released to RubyGems (recommended)
15
15
  gem 'auxiliary_rails'
16
+
16
17
  # or latest version from the repository
17
18
  gem 'auxiliary_rails', git: 'https://github.com/ergoserv/auxiliary_rails'
18
- # or from a specific branch of the repository
19
+ # or from a specific branch of the GitHub repository
19
20
  gem 'auxiliary_rails', github: 'ergoserv/auxiliary_rails', branch: 'develop'
21
+ # or from a local path (for development and testing purposes)
22
+ gem 'auxiliary_rails', path: '../auxiliary_rails'
20
23
  ```
21
24
 
22
25
  And then execute:
@@ -29,18 +32,22 @@ Or install it yourself as:
29
32
 
30
33
  ## Usage
31
34
 
35
+ - [API documentation](https://www.rubydoc.info/gems/auxiliary_rails)
36
+
32
37
  ### Rails Application Templates
33
38
 
34
39
  Install gem into the system (e.g. using `gem install auxiliary_rails`) then:
35
40
 
36
41
  ```sh
37
42
  auxiliary_rails new APP_PATH
43
+ # or add `--develop` option to pull the most recent template from repository
44
+ auxiliary_rails new APP_PATH --develop
38
45
  ```
39
46
 
40
47
  Or use `rails new` command specifying `--template` argument:
41
48
 
42
49
  ```sh
43
- rails new APP_PATH --skip-action-cable --skip-coffee --skip-test --database=postgresql --template=https://raw.githubusercontent.com/ergoserv/auxiliary_rails/develop/templates/rails/elementary.rb
50
+ rails new APP_PATH --database=postgresql --template=https://raw.githubusercontent.com/ergoserv/auxiliary_rails/develop/templates/rails/elementary.rb --skip-action-cable --skip-coffee --skip-test
44
51
  ```
45
52
 
46
53
  ### Generators
@@ -52,14 +59,268 @@ rails generate auxiliary_rails:install
52
59
  # Install one by one
53
60
  rails generate auxiliary_rails:install_commands
54
61
  rails generate auxiliary_rails:install_errors
55
- rails generate auxiliary_rails:install_rubocop
56
- rails generate auxiliary_rails:install_rubocop --no-specify-gems
62
+ rails generate auxiliary_rails:install_errors_controller
57
63
 
58
64
  # API resource generator
59
65
  rails generate auxiliary_rails:api_resource
60
66
 
61
67
  # Command generator
62
68
  rails generate auxiliary_rails:command
69
+
70
+ # Service generator
71
+ rails generate auxiliary_rails:service
72
+ ```
73
+
74
+ ### API Resources
75
+
76
+ Read article [Building an API](https://github.com/ergoserv/handbook/blob/master/guides/building_api.md) for more details.
77
+
78
+ Use generator to generate appropriate classes and files (Resource, Entity, Helper, Spec) for the specified end-point:
79
+
80
+ ```sh
81
+ rails generate auxiliary_rails:api_resource
82
+ ```
83
+
84
+ ## Application
85
+
86
+ ### Command Objects
87
+
88
+ Variation of implementation of [Command pattern](https://refactoring.guru/design-patterns/command).
89
+
90
+ Read post [Command Objects - a.k.a Service Objects in Ruby on Rails - The Ergonomic Way](https://www.ergoserv.com/blog/command-objects-aka-service-objects-in-ruby-on-rails-the-ergonomic-way) for more details.
91
+
92
+ ```ruby
93
+ # app/commands/application_command.rb
94
+ class ApplicationCommand < AuxiliaryRails::Application::Command
95
+ end
96
+
97
+ # app/commands/register_user_command.rb
98
+ class RegisterUserCommand < ApplicationCommand
99
+ # Define command arguments
100
+ # using `param` or `option` methods provided by dry-initializer
101
+ # https://dry-rb.org/gems/dry-initializer/3.0/
102
+ param :email
103
+ param :password
104
+
105
+ # Define the results of the command using `attr_reader`
106
+ # and set it as a regular instance var inside the command
107
+ attr_reader :user
108
+
109
+ # Regular Active Model Validations can be used to validate params
110
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html
111
+ # Use #valid?, #invalid?, #validate! methods to engage validations
112
+ validates :password, length: { in: 8..32 }
113
+
114
+ # Define the only public method `#perform` where command's flow is defined
115
+ def perform
116
+ # Use `return failure!` and `return success!` inside `#perform` method
117
+ # to control exits from the command with appropriate status.
118
+
119
+ # Use `return failure!` to exit from the command with failure
120
+ return failure! if registration_disabled?
121
+
122
+ # Method `#transaction` is a shortcut for `ActiveRecord::Base.transaction`
123
+ transaction do
124
+ # Keep the `#perform` method short and clean, put all the steps, actions
125
+ # and business logic into meaningful and self-explanatory methods
126
+ @user = create_user
127
+
128
+ # Use `error!` method to interrupt the flow raising an error
129
+ error! unless user.persistent?
130
+
131
+ send_notifications
132
+ # ...
133
+ end
134
+
135
+ # Always end the `#perform` method with `success!`.
136
+ # It will set the proper command's execution status.
137
+ success!
138
+ end
139
+
140
+ private
141
+
142
+ def create_user
143
+ User.create(email: email, password: password)
144
+ end
145
+
146
+ def send_notifications
147
+ # ...
148
+ end
149
+ end
150
+
151
+ ### usage ###
152
+
153
+ class RegistrationsController
154
+ def register
155
+ cmd = RegisterUserCommand.call(params[:email], params[:password])
156
+
157
+ if cmd.success?
158
+ redirect_to user_path(cmd.user) and return
159
+ else
160
+ @errors = cmd.errors
161
+ end
162
+
163
+ ### OR ###
164
+
165
+ RegisterUserCommand.call(params[:email], params[:password])
166
+ .on(:success) do
167
+ redirect_to dashboard_path and return
168
+ end
169
+ .on(:failure) do |cmd|
170
+ @errors = cmd.errors
171
+ end
172
+ end
173
+ end
174
+ ```
175
+
176
+ ### Error Objects
177
+
178
+ Custom error objects.
179
+ Read article [Error Handling](https://github.com/ergoserv/handbook/blob/master/guides/error_handling.md) for more details.
180
+
181
+ ```ruby
182
+ # app/errors/application_error.rb
183
+ class ApplicationCommand < AuxiliaryRails::Application::Error
184
+ end
185
+ ```
186
+
187
+ ### Form Objects
188
+
189
+ ```ruby
190
+ # app/forms/application_form.rb
191
+ class ApplicationForm < AuxiliaryRails::Application::Form
192
+ end
193
+
194
+ # app/forms/company_registration_form.rb
195
+ class CompanyRegistrationForm < ApplicationForm
196
+ # Define form attributes
197
+ attribute :company_name, :string
198
+ attribute :email, :string
199
+
200
+ # Define form submission results
201
+ attr_reader :company
202
+
203
+ # Regular Active Model Validations can be used to validate attributes
204
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html
205
+ validates :company_name, presence: true
206
+ validates :email, email: true
207
+
208
+ def perform
209
+ # Perform business logic here
210
+
211
+ # Use `attr_reader` to expose the submission results.
212
+ @company = create_company
213
+ # Return `failure!` to indicate failure and stop execution
214
+ return failure! if @company.invalid?
215
+
216
+ send_notification if email.present?
217
+
218
+ # Always end with `success!` method call to indicate success
219
+ success!
220
+ end
221
+
222
+ private
223
+
224
+ def create_comany
225
+ Company.create(name: company_name)
226
+ end
227
+
228
+ def send_notification
229
+ # mail to: email
230
+ end
231
+ end
232
+
233
+ ### Usage ###
234
+
235
+ form = CompanyRegistrationForm.call(params[:company])
236
+ if form.success?
237
+ redirect_to company_path(form.company) and return
238
+ else
239
+ @errors = form.errors
240
+ end
241
+ ```
242
+
243
+ ### Query Objects
244
+
245
+ ```ruby
246
+ # app/queries/application_query.rb
247
+ class ApplicationQuery < AuxiliaryRails::Application::Query
248
+ end
249
+
250
+ # app/queries/authors_query.rb
251
+ class AuthorsQuery < ApplicationQuery
252
+ default_relation Author.all
253
+
254
+ option :name_like, optional: true
255
+ option :with_books, optional: true
256
+
257
+ def perform
258
+ if recent == true
259
+ # equivalent to `@query = @query.order(:created_at)`:
260
+ query order(:created_at)
261
+ end
262
+
263
+ if name_like.present?
264
+ query with_name_like(name_like)
265
+ end
266
+ end
267
+
268
+ private
269
+
270
+ def with_name_like(value)
271
+ where('authors.name LIKE ?', "%#{value}%")
272
+ end
273
+ end
274
+
275
+ # app/queries/authors_with_books_query.rb
276
+ class AuthorsWithBooksQuery < AuthorsQuery
277
+ option :min_book_count, default: { 3 }
278
+
279
+ def perform
280
+ query joins(:books)
281
+ .group(:author_id)
282
+ .having('COUNT(books.id) > ?', min_book_count)
283
+ end
284
+ end
285
+
286
+ ### Usage ###
287
+
288
+ # it is possible to wrap query object in a scope and use as a regular scope
289
+ # app/models/author.rb
290
+ class Author < ApplicationRecord
291
+ scope :name_like, ->(value) { AuthorsQuery.call(name_like: value) }
292
+ end
293
+
294
+ authors = Author.name_like('Arthur')
295
+
296
+ # or call query directly
297
+ authors = AuthorsWithBooksQuery.call(min_book_count: 10)
298
+ ```
299
+
300
+ ### Service Modules
301
+
302
+ Read [Service Modules](https://github.com/ergoserv/handbook/blob/master/guides/service_modules.md) for more details.
303
+
304
+ **Service Generator**
305
+
306
+ ```sh
307
+ rails generate auxiliary_rails:service
308
+ ```
309
+
310
+ **Service Config** - provides a unified access to a service configs and loads the first found from:
311
+
312
+ - Constant (`MyService::CONFIG`)
313
+ - Application config file (`config/settings.yml`, see gem [`config`](https://github.com/rubyconfig/config))
314
+ - Service config file (`config/services/my_service.yml`)
315
+
316
+ ```ruby
317
+ # app/services/my_service.rb
318
+ module MyService
319
+ extend AuxiliaryRails::Application::Service
320
+ end
321
+
322
+ # usage
323
+ MyService.config.some_key
63
324
  ```
64
325
 
65
326
  ### View Helpers
@@ -67,6 +328,7 @@ rails generate auxiliary_rails:command
67
328
  ```ruby
68
329
  current_controller?(*ctrl_names)
69
330
  current_action?(*action_names)
331
+ display_name(resource)
70
332
  ```
71
333
 
72
334
  ## Development