auxiliary_rails 0.2.0 → 0.3.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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +26 -0
  3. data/.rubocop.yml +11 -2
  4. data/.rubocop_todo.yml +13 -9
  5. data/.yardopts +5 -0
  6. data/CHANGELOG.md +19 -2
  7. data/CONTRIBUTING.md +0 -6
  8. data/Gemfile.lock +20 -16
  9. data/README.md +204 -3
  10. data/auxiliary_rails.gemspec +7 -5
  11. data/bin/rubocop +3 -0
  12. data/lib/auxiliary_rails.rb +5 -3
  13. data/lib/auxiliary_rails/application/command.rb +56 -0
  14. data/lib/auxiliary_rails/application/error.rb +10 -0
  15. data/lib/auxiliary_rails/application/form.rb +30 -0
  16. data/lib/auxiliary_rails/application/query.rb +78 -0
  17. data/lib/auxiliary_rails/cli.rb +19 -5
  18. data/lib/auxiliary_rails/concerns/performable.rb +141 -0
  19. data/lib/auxiliary_rails/version.rb +1 -1
  20. data/lib/generators/auxiliary_rails/install_commands_generator.rb +5 -0
  21. data/lib/generators/auxiliary_rails/install_generator.rb +0 -1
  22. data/lib/generators/auxiliary_rails/templates/application_error_template.rb +1 -1
  23. data/lib/generators/auxiliary_rails/templates/commands/application_command_template.rb +1 -1
  24. data/lib/generators/auxiliary_rails/templates/commands/command_template.rb +2 -2
  25. data/lib/generators/auxiliary_rails/templates/commands/commands.en_template.yml +5 -0
  26. data/templates/rails/elementary.rb +45 -9
  27. metadata +43 -11
  28. data/lib/auxiliary_rails/abstract_command.rb +0 -95
  29. data/lib/auxiliary_rails/abstract_error.rb +0 -7
  30. data/lib/generators/auxiliary_rails/install_rubocop_generator.rb +0 -29
  31. data/lib/generators/auxiliary_rails/templates/rubocop/rubocop_auxiliary_rails_template.yml +0 -65
  32. data/lib/generators/auxiliary_rails/templates/rubocop/rubocop_template.yml +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6270fee8c57097f95277b91cb770228af36551459ebd01fbbe1900ff43a5b4b3
4
- data.tar.gz: 6b6e074c5751b729106fe2dcdc1f606474a95f6575eb8df0b1cbd68d54ebbe7b
3
+ metadata.gz: d2dca627a51fe1045de4e00f82cd2ac9dcc96df20816d7de67a8bf818180a06c
4
+ data.tar.gz: e5ae6c889d8ed752d382d86822410a409daaf9f14b04cbf833938af32adab6e9
5
5
  SHA512:
6
- metadata.gz: 77302dee8e26ab571731ee47779f70ade277fc5c476f197259a18d321336c0952f45bb69bba62bcde6d52cba677c979ac00646cc8e8165e7288da023cabb5642
7
- data.tar.gz: 450261a1b391e70b1cd7b926bb0cb4985f2f82021713041be5f6f04a403ea0b48eb9b8623ea2178c40a10533d05013067997dd15868def2a686947187af9fccc
6
+ metadata.gz: cabb77bb72b361996f1bd9623768d7c1af219c0f1bed3a516781493b0b77b7892bb42a3e4ffbefaabd879862fd7b3f25872a87e814e6b7aa7ec2bfc51e1e93d1
7
+ data.tar.gz: 07d26c7e442836147af787b33b5d6300f8e3d01c4b60a53fd31cbf0381158a7af5f16f8cb67af8d395ac8df25333cc75de8edaf8d1b0eb01e5cb1f708a1ebc43
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,26 @@
1
+ image: ruby:2.6
2
+
3
+ cache:
4
+ paths:
5
+ - vendor/bundle
6
+ - vendor/ruby
7
+
8
+ before_script:
9
+ - ruby -v
10
+ - gem install bundler --no-document
11
+ - bundle config set path 'vendor'
12
+ - bundle install --jobs $(nproc)
13
+
14
+ rspec:
15
+ stage: test
16
+ script:
17
+ - bundle exec rspec
18
+
19
+ rubocop:
20
+ stage: test
21
+ allow_failure: true
22
+ script:
23
+ - bundle exec rubocop
24
+
25
+ stages:
26
+ - test
data/.rubocop.yml CHANGED
@@ -7,13 +7,17 @@ require:
7
7
 
8
8
  AllCops:
9
9
  Exclude:
10
- - vendor/bundle/**/* # fix for running on Travis CI
10
+ - lib/generators/auxiliary_rails/templates/**/*
11
+ - vendor/**/* # fix for CI
11
12
 
12
13
  #################### Layout ##############################
13
14
 
14
- Layout/AlignArguments:
15
+ Layout/ArgumentAlignment:
15
16
  EnforcedStyle: with_fixed_indentation
16
17
 
18
+ Layout/MultilineMethodCallIndentation:
19
+ EnforcedStyle: indented
20
+
17
21
  #################### Metrics ##############################
18
22
 
19
23
  Metrics/BlockLength:
@@ -22,6 +26,8 @@ Metrics/BlockLength:
22
26
 
23
27
  #################### RSpec ################################
24
28
 
29
+ RSpec/ExampleLength:
30
+ Max: 10
25
31
 
26
32
  RSpec/MultipleExpectations:
27
33
  Max: 3
@@ -33,3 +39,6 @@ Style/Documentation:
33
39
 
34
40
  Style/FrozenStringLiteralComment:
35
41
  Enabled: false
42
+
43
+ Style/NegatedIf:
44
+ EnforcedStyle: postfix
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-05-12 09:23:17 +0300 using RuboCop version 0.68.1.
3
+ # on 2020-01-25 02:14:48 +0200 using RuboCop version 0.78.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -8,20 +8,24 @@
8
8
 
9
9
  # Offense count: 1
10
10
  # Cop supports --auto-correct.
11
- # Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
12
- Layout/ExtraSpacing:
11
+ Lint/SendWithMixinArgument:
13
12
  Exclude:
14
- - 'auxiliary_rails.gemspec'
13
+ - 'lib/auxiliary_rails/railtie.rb'
15
14
 
16
15
  # Offense count: 1
17
- # Cop supports --auto-correct.
18
- # Configuration parameters: AllowForAlignment.
19
- Layout/SpaceAroundOperators:
20
- Exclude:
21
- - 'auxiliary_rails.gemspec'
16
+ RSpec/NestedGroups:
17
+ Max: 4
22
18
 
23
19
  # Offense count: 1
24
20
  # Configuration parameters: MinBodyLength.
25
21
  Style/GuardClause:
26
22
  Exclude:
27
23
  - 'auxiliary_rails.gemspec'
24
+
25
+ # Offense count: 1
26
+ # Cop supports --auto-correct.
27
+ # Configuration parameters: EnforcedStyle, AllowInnerSlashes.
28
+ # SupportedStyles: slashes, percent_r, mixed
29
+ Style/RegexpLiteral:
30
+ Exclude:
31
+ - 'lib/generators/auxiliary_rails/command_generator.rb'
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --title "AuxiliaryRails"
2
+ --private --protected
3
+ --exclude lib/generators/*
4
+ --exclude lib/auxiliary_rails.rb
5
+ --exclude lib/auxiliary_rails/railtie.rb
data/CHANGELOG.md CHANGED
@@ -1,9 +1,26 @@
1
1
  # AuxiliaryRails Changelog
2
2
 
3
+ ## v0.3.0
4
+
5
+ ### Added
6
+ - Form Objects
7
+ - Query Objects
8
+ - Performable concern
9
+ - YARD docs and link to API documentation
10
+ - Commands usage examples
11
+ - Commands: `arguments` helper to get hash of all `param`s
12
+
13
+ ### Changed
14
+ - Namespace `Application` instead of `Abstract` prefixes for classes
15
+ - Commands migrate from `#call` to `#perform` method
16
+ - Commands: force validations
17
+
18
+ ### Removed
19
+ - RuboCop generator replaced with `rubocop-ergoserv` gem
20
+
3
21
  ## v0.2.0
4
22
 
5
23
  * Commands migration to `dry-initializer`
6
- * Commands usage examples
7
24
 
8
25
  ## v0.1.7
9
26
 
@@ -26,7 +43,7 @@
26
43
 
27
44
  ## v0.1.3
28
45
 
29
- * Upgrate `rubocop` gem and its configs
46
+ * Upgrade `rubocop` gem and its configs
30
47
  * `rubocop-rspec` and `rubocop-performance` gem iteration
31
48
  * Added basic Rails application template
32
49
  * CLI with `create_rails_app` command
data/CONTRIBUTING.md CHANGED
@@ -1,7 +1 @@
1
1
  # Contributing to AuxiliaryRails
2
-
3
- ## Rubocop Templates
4
-
5
- ### Versioning
6
-
7
- File `rubocop_auxiliary_rails_template.yml` contains a basic template of Rubocop config. After making any changes to this file the line `Version: N` should be updated and `N` (version number) should be incremented by one.
data/Gemfile.lock CHANGED
@@ -1,7 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- auxiliary_rails (0.2.0)
4
+ auxiliary_rails (0.3.0)
5
+ dry-core
6
+ dry-initializer
5
7
  dry-initializer-rails
6
8
  thor
7
9
 
@@ -66,17 +68,19 @@ GEM
66
68
  ast (2.4.0)
67
69
  builder (3.2.4)
68
70
  coderay (1.1.2)
69
- concurrent-ruby (1.1.5)
70
- crass (1.0.5)
71
+ concurrent-ruby (1.1.6)
72
+ crass (1.0.6)
71
73
  diff-lcs (1.3)
72
- dry-initializer (3.0.2)
74
+ dry-core (0.4.9)
75
+ concurrent-ruby (~> 1.0)
76
+ dry-initializer (3.0.3)
73
77
  dry-initializer-rails (3.1.1)
74
78
  dry-initializer (>= 2.4, < 4)
75
79
  rails (> 3.0)
76
80
  erubi (1.9.0)
77
81
  globalid (0.4.2)
78
82
  activesupport (>= 4.2.0)
79
- i18n (1.7.0)
83
+ i18n (1.8.2)
80
84
  concurrent-ruby (~> 1.0)
81
85
  jaro_winkler (1.5.4)
82
86
  loofah (2.4.0)
@@ -87,20 +91,20 @@ GEM
87
91
  marcel (0.3.3)
88
92
  mimemagic (~> 0.3.2)
89
93
  method_source (0.9.2)
90
- mimemagic (0.3.3)
94
+ mimemagic (0.3.4)
91
95
  mini_mime (1.0.2)
92
96
  mini_portile2 (2.4.0)
93
- minitest (5.13.0)
97
+ minitest (5.14.0)
94
98
  nio4r (2.5.2)
95
- nokogiri (1.10.7)
99
+ nokogiri (1.10.9)
96
100
  mini_portile2 (~> 2.4.0)
97
101
  parallel (1.19.1)
98
- parser (2.7.0.1)
102
+ parser (2.7.0.4)
99
103
  ast (~> 2.4.0)
100
104
  pry (0.12.2)
101
105
  coderay (~> 1.1.0)
102
106
  method_source (~> 0.9.0)
103
- rack (2.0.8)
107
+ rack (2.2.2)
104
108
  rack-test (1.1.0)
105
109
  rack (>= 1.0, < 3)
106
110
  rails (6.0.2.1)
@@ -144,16 +148,16 @@ GEM
144
148
  diff-lcs (>= 1.2.0, < 2.0)
145
149
  rspec-support (~> 3.9.0)
146
150
  rspec-support (3.9.2)
147
- rubocop (0.78.0)
151
+ rubocop (0.79.0)
148
152
  jaro_winkler (~> 1.5.1)
149
153
  parallel (~> 1.10)
150
- parser (>= 2.6)
154
+ parser (>= 2.7.0.1)
151
155
  rainbow (>= 2.2.2, < 4.0)
152
156
  ruby-progressbar (~> 1.7)
153
157
  unicode-display_width (>= 1.4.0, < 1.7)
154
158
  rubocop-performance (1.5.2)
155
159
  rubocop (>= 0.71.0)
156
- rubocop-rspec (1.37.1)
160
+ rubocop-rspec (1.38.1)
157
161
  rubocop (>= 0.68.1)
158
162
  ruby-progressbar (1.10.1)
159
163
  sprockets (4.0.0)
@@ -167,11 +171,11 @@ GEM
167
171
  thread_safe (0.3.6)
168
172
  tzinfo (1.2.6)
169
173
  thread_safe (~> 0.1)
170
- unicode-display_width (1.6.0)
174
+ unicode-display_width (1.6.1)
171
175
  websocket-driver (0.7.1)
172
176
  websocket-extensions (>= 0.1.0)
173
177
  websocket-extensions (0.1.4)
174
- zeitwerk (2.2.2)
178
+ zeitwerk (2.3.0)
175
179
 
176
180
  PLATFORMS
177
181
  ruby
@@ -183,7 +187,7 @@ DEPENDENCIES
183
187
  rails (>= 5.2, < 7)
184
188
  rake
185
189
  rspec (~> 3.8)
186
- rubocop
190
+ rubocop (= 0.79)
187
191
  rubocop-performance
188
192
  rubocop-rspec
189
193
 
data/README.md CHANGED
@@ -29,18 +29,22 @@ Or install it yourself as:
29
29
 
30
30
  ## Usage
31
31
 
32
+ - [API documentation](https://www.rubydoc.info/gems/auxiliary_rails)
33
+
32
34
  ### Rails Application Templates
33
35
 
34
36
  Install gem into the system (e.g. using `gem install auxiliary_rails`) then:
35
37
 
36
38
  ```sh
37
39
  auxiliary_rails new APP_PATH
40
+ # or add `--develop` option to pull the most recent template from repository
41
+ auxiliary_rails new APP_PATH --develop
38
42
  ```
39
43
 
40
44
  Or use `rails new` command specifying `--template` argument:
41
45
 
42
46
  ```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
47
+ 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 --skip-webpack-install
44
48
  ```
45
49
 
46
50
  ### Generators
@@ -52,8 +56,6 @@ rails generate auxiliary_rails:install
52
56
  # Install one by one
53
57
  rails generate auxiliary_rails:install_commands
54
58
  rails generate auxiliary_rails:install_errors
55
- rails generate auxiliary_rails:install_rubocop
56
- rails generate auxiliary_rails:install_rubocop --no-specify-gems
57
59
 
58
60
  # API resource generator
59
61
  rails generate auxiliary_rails:api_resource
@@ -62,6 +64,205 @@ rails generate auxiliary_rails:api_resource
62
64
  rails generate auxiliary_rails:command
63
65
  ```
64
66
 
67
+ ### Command Objects
68
+
69
+ Variation of implementation of [Command pattern](https://en.wikipedia.org/wiki/Command_pattern).
70
+
71
+ ```ruby
72
+ # app/commands/application_command.rb
73
+ class ApplicationCommand < AuxiliaryRails::Application::Command
74
+ end
75
+
76
+ # app/commands/register_user_command.rb
77
+ class RegisterUserCommand < ApplicationCommand
78
+ # Define command arguments
79
+ # using `param` or `option` methods provided by dry-initializer
80
+ # https://dry-rb.org/gems/dry-initializer/3.0/
81
+ param :email
82
+ param :password
83
+
84
+ # Define the results of the command
85
+ # using `attr_reader` and set it as a regular instance var inside the command
86
+ attr_reader :user
87
+
88
+ # Regular Active Model Validations can be used to validate params
89
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html
90
+ # Use #valid?, #invalid?, #validate! methods to engage validations
91
+ validates :password, length: { in: 8..32 }
92
+
93
+ # Define the only public method `#perform`
94
+ # where command's flow is defined
95
+ def perform
96
+ # Use `return failure!` to exit from the command with failure
97
+ return failure! if registration_disabled?
98
+
99
+ # Method `#transaction` is a shortcut for `ActiveRecord::Base.transaction`
100
+ transaction do
101
+ # Keep the `#perform` method short and clean, put all the steps, actions
102
+ # and business logic into meaningful and self-explanatory methods
103
+ create_user
104
+
105
+ # Use `error!` method to interrupt the flow raising an error
106
+ error! unless @user.persistent?
107
+
108
+ send_notification
109
+ # ...
110
+ end
111
+
112
+ # Always end the `#perform` method with `success!`
113
+ # this will set the proper status and allow to chain command methods.
114
+ success!
115
+ end
116
+
117
+ private
118
+
119
+ def create_user
120
+ @user = User.create(email: email, password: password)
121
+ end
122
+
123
+ def send_notification
124
+ # ...
125
+ end
126
+ end
127
+
128
+ ### usage ###
129
+
130
+ class RegistrationsController
131
+ def register
132
+ cmd = RegisterUserCommand.call(params[:email], params[:password])
133
+
134
+ if cmd.success?
135
+ redirect_to user_path(cmd.user) and return
136
+ else
137
+ @errors = cmd.errors
138
+ end
139
+
140
+ ### OR ###
141
+
142
+ RegisterUserCommand.call(params[:email], params[:password])
143
+ .on(:success) do
144
+ redirect_to dashboard_path and return
145
+ end
146
+ .on(:failure) do |cmd|
147
+ @errors = cmd.errors
148
+ end
149
+ end
150
+ end
151
+ ```
152
+
153
+ ### Form Objects
154
+
155
+ ```ruby
156
+ # app/forms/application_form.rb
157
+ class ApplicationForm < AuxiliaryRails::Application::Form
158
+ end
159
+
160
+ # app/forms/company_registration_form.rb
161
+ class CompanyRegistrationForm < ApplicationForm
162
+ # Define form attributes
163
+ attribute :company_name, :string
164
+ attribute :email, :string
165
+
166
+ # Define form submission results
167
+ attr_reader :company
168
+
169
+ # Regular Active Model Validations can be used to validate attributes
170
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html
171
+ validates :company_name, presence: true
172
+ validates :email, email: true
173
+
174
+ def perform
175
+ # Perform business logic here
176
+
177
+ # Use `attr_reader` to expose the submission results.
178
+ @company = create_company
179
+ # Return `failure!` to indicate failure and stop execution
180
+ return failure! if @company.invalid?
181
+
182
+ send_notification if email.present?
183
+
184
+ # Always end with `success!` method call to indicate success
185
+ success!
186
+ end
187
+
188
+ private
189
+
190
+ def create_comany
191
+ Company.create(name: company_name)
192
+ end
193
+
194
+ def send_notification
195
+ # mail to: email
196
+ end
197
+ end
198
+
199
+ ### Usage ###
200
+
201
+ form = CompanyRegistrationForm.call(params[:company])
202
+ if form.success?
203
+ redirect_to company_path(form.company) and return
204
+ else
205
+ @errors = form.errors
206
+ end
207
+ ```
208
+
209
+ ### Query Objects
210
+
211
+ ```ruby
212
+ # app/queries/application_query.rb
213
+ class ApplicationQuery < AuxiliaryRails::Application::Query
214
+ end
215
+
216
+ # app/queries/authors_query.rb
217
+ class AuthorsQuery < ApplicationQuery
218
+ default_relation Author.all
219
+
220
+ option :name_like, optional: true
221
+ option :with_books, optional: true
222
+
223
+ def perform
224
+ if recent == true
225
+ # equivalent to `@query = @query.order(:created_at)`:
226
+ query order(:created_at)
227
+ end
228
+
229
+ if name_like.present?
230
+ query with_name_like(name_like)
231
+ end
232
+ end
233
+
234
+ private
235
+
236
+ def with_name_like(value)
237
+ where('authors.name LIKE ?', "%#{value}%")
238
+ end
239
+ end
240
+
241
+ # app/queries/authors_with_books_query.rb
242
+ class AuthorsWithBooksQuery < AuthorsQuery
243
+ option :min_book_count, default: { 3 }
244
+
245
+ def perform
246
+ query joins(:books)
247
+ .group(:author_id)
248
+ .having('COUNT(books.id) > ?', min_book_count)
249
+ end
250
+ end
251
+
252
+ ### Usage ###
253
+
254
+ # it is possible to wrap query object in a scope and use as a regular scope
255
+ # app/models/inmate.rb
256
+ class Author < ApplicationRecord
257
+ scope :name_like, ->(value) { AuthorsQuery.call(name_like: value) }
258
+ end
259
+
260
+ authors = Author.name_like('Arthur')
261
+
262
+ # or call query directly
263
+ authors = AuthorsWithBooksQuery.call(min_book_count: 10)
264
+ ```
265
+
65
266
  ### View Helpers
66
267
 
67
268
  ```ruby