auxiliary_rails 0.2.0 → 0.4.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.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +26 -0
- data/.rubocop.yml +31 -3
- data/.rubocop_todo.yml +3 -19
- data/.ruby-version +1 -1
- data/.yardopts +5 -0
- data/CHANGELOG.md +39 -2
- data/CODE_OF_CONDUCT.md +128 -0
- data/CONTRIBUTING.md +0 -6
- data/Gemfile.lock +164 -132
- data/README.md +267 -5
- data/auxiliary_rails.gemspec +18 -13
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/bitbucket-pipelines.yml +35 -0
- data/lib/auxiliary_rails/application/command.rb +53 -0
- data/lib/auxiliary_rails/application/error.rb +50 -0
- data/lib/auxiliary_rails/application/form.rb +31 -0
- data/lib/auxiliary_rails/application/query.rb +75 -0
- data/lib/auxiliary_rails/application/service.rb +42 -0
- data/lib/auxiliary_rails/cli.rb +18 -5
- data/lib/auxiliary_rails/concerns/callable.rb +23 -0
- data/lib/auxiliary_rails/concerns/errorable.rb +22 -0
- data/lib/auxiliary_rails/concerns/performable.rb +120 -0
- data/lib/auxiliary_rails/railtie.rb +2 -1
- data/lib/auxiliary_rails/version.rb +1 -1
- data/lib/auxiliary_rails/view_helpers/display_helper.rb +30 -0
- data/lib/auxiliary_rails/view_helpers.rb +4 -0
- data/lib/auxiliary_rails.rb +7 -3
- data/lib/generators/auxiliary_rails/command_generator.rb +1 -1
- data/lib/generators/auxiliary_rails/install_commands_generator.rb +5 -0
- data/lib/generators/auxiliary_rails/install_errors_controller_generator.rb +31 -0
- data/lib/generators/auxiliary_rails/install_generator.rb +1 -1
- data/lib/generators/auxiliary_rails/service_generator.rb +48 -0
- data/lib/generators/auxiliary_rails/templates/application_error_template.rb +1 -1
- data/lib/generators/auxiliary_rails/templates/commands/application_command_template.rb +1 -1
- data/lib/generators/auxiliary_rails/templates/commands/command_spec_template.rb +1 -1
- data/lib/generators/auxiliary_rails/templates/commands/command_template.rb +2 -2
- data/lib/generators/auxiliary_rails/templates/commands/commands.en_template.yml +5 -0
- data/lib/generators/auxiliary_rails/templates/errors_controller/errors_controller_template.rb +15 -0
- data/lib/generators/auxiliary_rails/templates/errors_controller/not_found_template.html.erb +2 -0
- data/lib/generators/auxiliary_rails/templates/errors_controller/show_template.html.erb +1 -0
- data/lib/generators/auxiliary_rails/templates/errors_controller/unacceptable_template.html.erb +2 -0
- data/lib/generators/auxiliary_rails/templates/services/service_spec_template.rb +5 -0
- data/lib/generators/auxiliary_rails/templates/services/service_template.rb +10 -0
- data/templates/rails/elementary.rb +39 -10
- metadata +87 -32
- data/lib/auxiliary_rails/abstract_command.rb +0 -95
- data/lib/auxiliary_rails/abstract_error.rb +0 -7
- data/lib/generators/auxiliary_rails/install_rubocop_generator.rb +0 -29
- data/lib/generators/auxiliary_rails/templates/rubocop/rubocop_auxiliary_rails_template.yml +0 -65
- 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.
|
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 (
|
12
|
-
actionpack (=
|
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 (
|
16
|
-
actionpack (=
|
17
|
-
activejob (=
|
18
|
-
activerecord (=
|
19
|
-
activestorage (=
|
20
|
-
activesupport (=
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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 (
|
29
|
-
actionview (=
|
30
|
-
activesupport (=
|
31
|
-
rack (~> 2.0, >= 2.0
|
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 (
|
36
|
-
actionpack (=
|
37
|
-
activerecord (=
|
38
|
-
activestorage (=
|
39
|
-
activesupport (=
|
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 (
|
42
|
-
activesupport (=
|
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 (
|
48
|
-
activesupport (=
|
59
|
+
activejob (7.0.3.1)
|
60
|
+
activesupport (= 7.0.3.1)
|
49
61
|
globalid (>= 0.3.6)
|
50
|
-
activemodel (
|
51
|
-
activesupport (=
|
52
|
-
activerecord (
|
53
|
-
activemodel (=
|
54
|
-
activesupport (=
|
55
|
-
activestorage (
|
56
|
-
actionpack (=
|
57
|
-
activejob (=
|
58
|
-
activerecord (=
|
59
|
-
|
60
|
-
|
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 (>=
|
63
|
-
minitest (
|
64
|
-
tzinfo (~>
|
65
|
-
|
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.
|
69
|
-
concurrent-ruby (1.1.
|
70
|
-
crass (1.0.
|
71
|
-
diff-lcs (1.
|
72
|
-
|
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.
|
77
|
-
globalid (0.
|
78
|
-
activesupport (>=
|
79
|
-
i18n (1.
|
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
|
-
|
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.
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
152
|
+
rails-html-sanitizer (1.4.3)
|
125
153
|
loofah (~> 2.3)
|
126
|
-
railties (
|
127
|
-
actionpack (=
|
128
|
-
activesupport (=
|
154
|
+
railties (7.0.3.1)
|
155
|
+
actionpack (= 7.0.3.1)
|
156
|
+
activesupport (= 7.0.3.1)
|
129
157
|
method_source
|
130
|
-
rake (>=
|
131
|
-
thor (
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
rspec-
|
140
|
-
|
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.
|
143
|
-
rspec-mocks (3.
|
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.
|
146
|
-
rspec-support (3.
|
147
|
-
rubocop (
|
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 (>=
|
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, <
|
154
|
-
rubocop-
|
155
|
-
|
156
|
-
rubocop-
|
157
|
-
rubocop (>= 0.
|
158
|
-
|
159
|
-
|
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
|
-
|
162
|
-
|
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.
|
174
|
-
zeitwerk (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.
|
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 --
|
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:
|
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
|