rails_ops 1.4.6 → 1.4.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cff3257dfac8bc81e9f4f9664239d20df0ff74843dfb149f28c5fe096a5ac70
4
- data.tar.gz: 247157a7ade590f8f017d76b2196cb224b2df913dbbc4e26696726686169189c
3
+ metadata.gz: 75ccfe7e3e3c1b5d575f21fffdcdd997e360ca15a3b99fc18048ef5ebb78aa27
4
+ data.tar.gz: 14f0a5676ed25fe83f7d1f78d27db94ee5e0b0292adca402dfc1236a97ad8b29
5
5
  SHA512:
6
- metadata.gz: 7d923e42260e28fdb51461f7723994cb8edcb370b9b61c276108e681fbb8a660166cb11426f8b464c8897b935020187c2503f57d30dd6b9d510f278d9a13231b
7
- data.tar.gz: 675dd3b3fcaf417ec901f7991363fd37863447a69b943f26e8f9f5d2dfa18e8d918d366fe872e4a40cb716abff1dd314a5144cf0b7f075a2babe89cac8a2ad7a
6
+ metadata.gz: cd19494f0f1e6e1518573ee51488dd9ed4302c9d906e7158a2da83c78366aca02ee78e10510f701f856c05d05eda35f652c0dbf8c909f2b0869e1ba772e4203c
7
+ data.tar.gz: 384f8044f573a11308a1749b1a12c057c99cf8bf1a27374dbeb7acfbc9060bf003d5c4304a141481276bc69fd1c5ac096756c1bf0a137b23dc74a5d072de9795
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.8 (2023-10-12)
4
+
5
+ * Keep original validation error message when
6
+ `rescue_validation_error_in_controller` is enabled
7
+
8
+ ## 1.4.7 (2023-10-09)
9
+
10
+ * Add parameter `override` to static `model` method in model operations
11
+
3
12
  ## 1.4.6 (2023-07-25)
4
13
 
5
14
  * Make sure that `RailsOps::Exceptions::SubOpValidationFailed` always results in
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rails_ops (1.4.6)
4
+ rails_ops (1.4.8)
5
5
  active_type (>= 1.3.0)
6
6
  minitest
7
7
  rails
@@ -11,69 +11,69 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- actioncable (7.0.4.3)
15
- actionpack (= 7.0.4.3)
16
- activesupport (= 7.0.4.3)
14
+ actioncable (7.0.6)
15
+ actionpack (= 7.0.6)
16
+ activesupport (= 7.0.6)
17
17
  nio4r (~> 2.0)
18
18
  websocket-driver (>= 0.6.1)
19
- actionmailbox (7.0.4.3)
20
- actionpack (= 7.0.4.3)
21
- activejob (= 7.0.4.3)
22
- activerecord (= 7.0.4.3)
23
- activestorage (= 7.0.4.3)
24
- activesupport (= 7.0.4.3)
19
+ actionmailbox (7.0.6)
20
+ actionpack (= 7.0.6)
21
+ activejob (= 7.0.6)
22
+ activerecord (= 7.0.6)
23
+ activestorage (= 7.0.6)
24
+ activesupport (= 7.0.6)
25
25
  mail (>= 2.7.1)
26
26
  net-imap
27
27
  net-pop
28
28
  net-smtp
29
- actionmailer (7.0.4.3)
30
- actionpack (= 7.0.4.3)
31
- actionview (= 7.0.4.3)
32
- activejob (= 7.0.4.3)
33
- activesupport (= 7.0.4.3)
29
+ actionmailer (7.0.6)
30
+ actionpack (= 7.0.6)
31
+ actionview (= 7.0.6)
32
+ activejob (= 7.0.6)
33
+ activesupport (= 7.0.6)
34
34
  mail (~> 2.5, >= 2.5.4)
35
35
  net-imap
36
36
  net-pop
37
37
  net-smtp
38
38
  rails-dom-testing (~> 2.0)
39
- actionpack (7.0.4.3)
40
- actionview (= 7.0.4.3)
41
- activesupport (= 7.0.4.3)
42
- rack (~> 2.0, >= 2.2.0)
39
+ actionpack (7.0.6)
40
+ actionview (= 7.0.6)
41
+ activesupport (= 7.0.6)
42
+ rack (~> 2.0, >= 2.2.4)
43
43
  rack-test (>= 0.6.3)
44
44
  rails-dom-testing (~> 2.0)
45
45
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
46
- actiontext (7.0.4.3)
47
- actionpack (= 7.0.4.3)
48
- activerecord (= 7.0.4.3)
49
- activestorage (= 7.0.4.3)
50
- activesupport (= 7.0.4.3)
46
+ actiontext (7.0.6)
47
+ actionpack (= 7.0.6)
48
+ activerecord (= 7.0.6)
49
+ activestorage (= 7.0.6)
50
+ activesupport (= 7.0.6)
51
51
  globalid (>= 0.6.0)
52
52
  nokogiri (>= 1.8.5)
53
- actionview (7.0.4.3)
54
- activesupport (= 7.0.4.3)
53
+ actionview (7.0.6)
54
+ activesupport (= 7.0.6)
55
55
  builder (~> 3.1)
56
56
  erubi (~> 1.4)
57
57
  rails-dom-testing (~> 2.0)
58
58
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
59
- active_type (2.3.2)
59
+ active_type (2.3.3)
60
60
  activerecord (>= 3.2)
61
- activejob (7.0.4.3)
62
- activesupport (= 7.0.4.3)
61
+ activejob (7.0.6)
62
+ activesupport (= 7.0.6)
63
63
  globalid (>= 0.3.6)
64
- activemodel (7.0.4.3)
65
- activesupport (= 7.0.4.3)
66
- activerecord (7.0.4.3)
67
- activemodel (= 7.0.4.3)
68
- activesupport (= 7.0.4.3)
69
- activestorage (7.0.4.3)
70
- actionpack (= 7.0.4.3)
71
- activejob (= 7.0.4.3)
72
- activerecord (= 7.0.4.3)
73
- activesupport (= 7.0.4.3)
64
+ activemodel (7.0.6)
65
+ activesupport (= 7.0.6)
66
+ activerecord (7.0.6)
67
+ activemodel (= 7.0.6)
68
+ activesupport (= 7.0.6)
69
+ activestorage (7.0.6)
70
+ actionpack (= 7.0.6)
71
+ activejob (= 7.0.6)
72
+ activerecord (= 7.0.6)
73
+ activesupport (= 7.0.6)
74
74
  marcel (~> 1.0)
75
75
  mini_mime (>= 1.1.0)
76
- activesupport (7.0.4.3)
76
+ activesupport (7.0.6)
77
77
  concurrent-ruby (~> 1.0, >= 1.0.2)
78
78
  i18n (>= 1.6, < 2)
79
79
  minitest (>= 5.1)
@@ -94,12 +94,12 @@ GEM
94
94
  erubi (1.12.0)
95
95
  globalid (1.1.0)
96
96
  activesupport (>= 5.0)
97
- i18n (1.12.0)
97
+ i18n (1.14.1)
98
98
  concurrent-ruby (~> 1.0)
99
99
  json (2.6.3)
100
- loofah (2.19.1)
100
+ loofah (2.21.3)
101
101
  crass (~> 1.0.2)
102
- nokogiri (>= 1.5.9)
102
+ nokogiri (>= 1.12.0)
103
103
  mail (2.8.1)
104
104
  mini_mime (>= 0.1.1)
105
105
  net-imap
@@ -108,7 +108,7 @@ GEM
108
108
  marcel (1.0.2)
109
109
  method_source (1.0.0)
110
110
  mini_mime (1.1.2)
111
- minitest (5.18.0)
111
+ minitest (5.18.1)
112
112
  net-imap (0.3.4)
113
113
  date
114
114
  net-protocol
@@ -119,9 +119,9 @@ GEM
119
119
  net-smtp (0.3.3)
120
120
  net-protocol
121
121
  nio4r (2.5.8)
122
- nokogiri (1.14.2-x86_64-darwin)
122
+ nokogiri (1.15.3-x86_64-darwin)
123
123
  racc (~> 1.4)
124
- nokogiri (1.14.2-x86_64-linux)
124
+ nokogiri (1.15.3-x86_64-linux)
125
125
  racc (~> 1.4)
126
126
  parallel (1.22.1)
127
127
  parser (3.2.1.1)
@@ -129,32 +129,34 @@ GEM
129
129
  pry (0.14.2)
130
130
  coderay (~> 1.1)
131
131
  method_source (~> 1.0)
132
- racc (1.6.2)
133
- rack (2.2.6.4)
132
+ racc (1.7.1)
133
+ rack (2.2.7)
134
134
  rack-test (2.1.0)
135
135
  rack (>= 1.3)
136
- rails (7.0.4.3)
137
- actioncable (= 7.0.4.3)
138
- actionmailbox (= 7.0.4.3)
139
- actionmailer (= 7.0.4.3)
140
- actionpack (= 7.0.4.3)
141
- actiontext (= 7.0.4.3)
142
- actionview (= 7.0.4.3)
143
- activejob (= 7.0.4.3)
144
- activemodel (= 7.0.4.3)
145
- activerecord (= 7.0.4.3)
146
- activestorage (= 7.0.4.3)
147
- activesupport (= 7.0.4.3)
136
+ rails (7.0.6)
137
+ actioncable (= 7.0.6)
138
+ actionmailbox (= 7.0.6)
139
+ actionmailer (= 7.0.6)
140
+ actionpack (= 7.0.6)
141
+ actiontext (= 7.0.6)
142
+ actionview (= 7.0.6)
143
+ activejob (= 7.0.6)
144
+ activemodel (= 7.0.6)
145
+ activerecord (= 7.0.6)
146
+ activestorage (= 7.0.6)
147
+ activesupport (= 7.0.6)
148
148
  bundler (>= 1.15.0)
149
- railties (= 7.0.4.3)
150
- rails-dom-testing (2.0.3)
151
- activesupport (>= 4.2.0)
149
+ railties (= 7.0.6)
150
+ rails-dom-testing (2.1.1)
151
+ activesupport (>= 5.0.0)
152
+ minitest
152
153
  nokogiri (>= 1.6)
153
- rails-html-sanitizer (1.5.0)
154
- loofah (~> 2.19, >= 2.19.1)
155
- railties (7.0.4.3)
156
- actionpack (= 7.0.4.3)
157
- activesupport (= 7.0.4.3)
154
+ rails-html-sanitizer (1.6.0)
155
+ loofah (~> 2.21)
156
+ nokogiri (~> 1.14)
157
+ railties (7.0.6)
158
+ actionpack (= 7.0.6)
159
+ activesupport (= 7.0.6)
158
160
  method_source
159
161
  rake (>= 12.2)
160
162
  thor (~> 1.0)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.6
1
+ 1.4.8
@@ -43,8 +43,8 @@ module RailsOps
43
43
  # This generally should be combined with enabling the option "ignore_obsolete_properties"
44
44
  # of schemacop.
45
45
  if RailsOps.config.rescue_validation_error_in_controller
46
- rescue_from Schemacop::Exceptions::ValidationError do |_e|
47
- fail ActionController::BadRequest
46
+ rescue_from Schemacop::Exceptions::ValidationError do |e|
47
+ fail ActionController::BadRequest, e.message
48
48
  end
49
49
  end
50
50
 
@@ -124,7 +124,10 @@ module RailsOps
124
124
  # strong params and converts them to a hash. This method can be overridden
125
125
  # for passing custom params to an operation for an entire controller.
126
126
  def op_params
127
- @op_params ||= filter_op_params(params.permit!).to_h
127
+ @op_params ||= begin
128
+ params = self.params.try(:permit!) || self.params
129
+ filter_op_params(params).to_h
130
+ end
128
131
  end
129
132
 
130
133
  # Constructs and returns the operation context used for instantiating
@@ -40,11 +40,13 @@ class RailsOps::Operation::Model < RailsOps::Operation
40
40
  # @param model_class [Class] The model class to take or extend
41
41
  # @param name [String,Symbol] A custom name that will be used for generating
42
42
  # the anonymous class
43
+ # @param override [boolean] Allows overriding previously set models (e.g. via
44
+ # operation inheritance)
43
45
  # @yield [] This optional block is executed in context of the newly generated,
44
46
  # anonymous class and allows you to extend it
45
- def self.model(model_class = nil, name = nil, &block)
47
+ def self.model(model_class = nil, name = nil, override: false, &block)
46
48
  if model_class || block_given?
47
- fail 'Model class can only be set once.' if _model_class
49
+ fail 'Model class can only be set once.' if _model_class && !override
48
50
 
49
51
  model_class ||= default_model_class
50
52
 
data/rails_ops.gemspec CHANGED
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: rails_ops 1.4.6 ruby lib
2
+ # stub: rails_ops 1.4.8 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "rails_ops".freeze
6
- s.version = "1.4.6"
6
+ s.version = "1.4.8"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Sitrox".freeze]
11
- s.date = "2023-07-25"
11
+ s.date = "2023-10-12"
12
12
  s.files = [".github/workflows/rubocop.yml".freeze, ".github/workflows/ruby.yml".freeze, ".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, "Appraisals".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "Gemfile.lock".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "gemfiles/rails_6.0.gemfile".freeze, "gemfiles/rails_6.1.gemfile".freeze, "gemfiles/rails_7.0.gemfile".freeze, "lib/generators/operation/USAGE".freeze, "lib/generators/operation/operation_generator.rb".freeze, "lib/generators/operation/templates/controller.erb".freeze, "lib/generators/operation/templates/controller_wrapper.erb".freeze, "lib/generators/operation/templates/create.erb".freeze, "lib/generators/operation/templates/destroy.erb".freeze, "lib/generators/operation/templates/load.erb".freeze, "lib/generators/operation/templates/update.erb".freeze, "lib/generators/operation/templates/view.erb".freeze, "lib/rails_ops.rb".freeze, "lib/rails_ops/authorization_backend/abstract.rb".freeze, "lib/rails_ops/authorization_backend/can_can_can.rb".freeze, "lib/rails_ops/configuration.rb".freeze, "lib/rails_ops/context.rb".freeze, "lib/rails_ops/controller_mixin.rb".freeze, "lib/rails_ops/exceptions.rb".freeze, "lib/rails_ops/hooked_job.rb".freeze, "lib/rails_ops/hookup.rb".freeze, "lib/rails_ops/hookup/dsl.rb".freeze, "lib/rails_ops/hookup/dsl_validator.rb".freeze, "lib/rails_ops/hookup/hook.rb".freeze, "lib/rails_ops/log_subscriber.rb".freeze, "lib/rails_ops/mixins.rb".freeze, "lib/rails_ops/mixins/authorization.rb".freeze, "lib/rails_ops/mixins/log_settings.rb".freeze, "lib/rails_ops/mixins/model.rb".freeze, "lib/rails_ops/mixins/model/authorization.rb".freeze, "lib/rails_ops/mixins/model/nesting.rb".freeze, "lib/rails_ops/mixins/param_authorization.rb".freeze, "lib/rails_ops/mixins/policies.rb".freeze, "lib/rails_ops/mixins/require_context.rb".freeze, "lib/rails_ops/mixins/routes.rb".freeze, "lib/rails_ops/mixins/schema_validation.rb".freeze, "lib/rails_ops/mixins/sub_ops.rb".freeze, "lib/rails_ops/model_mixins.rb".freeze, "lib/rails_ops/model_mixins/ar_extension.rb".freeze, "lib/rails_ops/model_mixins/marshalling.rb".freeze, "lib/rails_ops/model_mixins/parent_op.rb".freeze, "lib/rails_ops/model_mixins/sti_fixes.rb".freeze, "lib/rails_ops/model_mixins/virtual_attributes.rb".freeze, "lib/rails_ops/model_mixins/virtual_attributes/virtual_column_wrapper.rb".freeze, "lib/rails_ops/model_mixins/virtual_has_one.rb".freeze, "lib/rails_ops/model_mixins/virtual_model_name.rb".freeze, "lib/rails_ops/operation.rb".freeze, "lib/rails_ops/operation/model.rb".freeze, "lib/rails_ops/operation/model/create.rb".freeze, "lib/rails_ops/operation/model/destroy.rb".freeze, "lib/rails_ops/operation/model/load.rb".freeze, "lib/rails_ops/operation/model/update.rb".freeze, "lib/rails_ops/profiler.rb".freeze, "lib/rails_ops/profiler/node.rb".freeze, "lib/rails_ops/railtie.rb".freeze, "lib/rails_ops/scoped_env.rb".freeze, "lib/rails_ops/virtual_model.rb".freeze, "rails_ops.gemspec".freeze, "test/db/models.rb".freeze, "test/db/schema.rb".freeze, "test/dummy/Rakefile".freeze, "test/dummy/app/assets/config/manifest.js".freeze, "test/dummy/app/assets/images/.keep".freeze, "test/dummy/app/assets/javascripts/application.js".freeze, "test/dummy/app/assets/javascripts/cable.js".freeze, "test/dummy/app/assets/javascripts/channels/.keep".freeze, "test/dummy/app/assets/stylesheets/application.css".freeze, "test/dummy/app/channels/application_cable/channel.rb".freeze, "test/dummy/app/channels/application_cable/connection.rb".freeze, "test/dummy/app/controllers/application_controller.rb".freeze, "test/dummy/app/controllers/concerns/.keep".freeze, "test/dummy/app/controllers/group_controller.rb".freeze, "test/dummy/app/helpers/application_helper.rb".freeze, "test/dummy/app/jobs/application_job.rb".freeze, "test/dummy/app/mailers/application_mailer.rb".freeze, "test/dummy/app/models/ability.rb".freeze, "test/dummy/app/models/animal.rb".freeze, "test/dummy/app/models/application_record.rb".freeze, "test/dummy/app/models/bird.rb".freeze, "test/dummy/app/models/cat.rb".freeze, "test/dummy/app/models/computer.rb".freeze, "test/dummy/app/models/concerns/.keep".freeze, "test/dummy/app/models/cpu.rb".freeze, "test/dummy/app/models/dog.rb".freeze, "test/dummy/app/models/flower.rb".freeze, "test/dummy/app/models/group.rb".freeze, "test/dummy/app/models/mainboard.rb".freeze, "test/dummy/app/models/nightingale.rb".freeze, "test/dummy/app/models/phoenix.rb".freeze, "test/dummy/app/models/user.rb".freeze, "test/dummy/app/views/layouts/application.html.erb".freeze, "test/dummy/app/views/layouts/mailer.html.erb".freeze, "test/dummy/app/views/layouts/mailer.text.erb".freeze, "test/dummy/bin/bundle".freeze, "test/dummy/bin/rails".freeze, "test/dummy/bin/rake".freeze, "test/dummy/bin/setup".freeze, "test/dummy/bin/update".freeze, "test/dummy/bin/yarn".freeze, "test/dummy/config.ru".freeze, "test/dummy/config/application.rb".freeze, "test/dummy/config/boot.rb".freeze, "test/dummy/config/cable.yml".freeze, "test/dummy/config/database.yml".freeze, "test/dummy/config/environment.rb".freeze, "test/dummy/config/environments/development.rb".freeze, "test/dummy/config/environments/production.rb".freeze, "test/dummy/config/environments/test.rb".freeze, "test/dummy/config/hookup.rb".freeze, "test/dummy/config/initializers/application_controller_renderer.rb".freeze, "test/dummy/config/initializers/assets.rb".freeze, "test/dummy/config/initializers/backtrace_silencers.rb".freeze, "test/dummy/config/initializers/cookies_serializer.rb".freeze, "test/dummy/config/initializers/filter_parameter_logging.rb".freeze, "test/dummy/config/initializers/inflections.rb".freeze, "test/dummy/config/initializers/mime_types.rb".freeze, "test/dummy/config/initializers/rails_ops.rb".freeze, "test/dummy/config/initializers/wrap_parameters.rb".freeze, "test/dummy/config/locales/en.yml".freeze, "test/dummy/config/puma.rb".freeze, "test/dummy/config/routes.rb".freeze, "test/dummy/config/secrets.yml".freeze, "test/dummy/config/spring.rb".freeze, "test/dummy/db/schema.rb".freeze, "test/dummy/lib/assets/.keep".freeze, "test/dummy/log/.keep".freeze, "test/dummy/package.json".freeze, "test/dummy/public/404.html".freeze, "test/dummy/public/422.html".freeze, "test/dummy/public/500.html".freeze, "test/dummy/public/apple-touch-icon-precomposed.png".freeze, "test/dummy/public/apple-touch-icon.png".freeze, "test/dummy/public/favicon.ico".freeze, "test/dummy/tmp/.keep".freeze, "test/test_helper.rb".freeze, "test/unit/rails_ops/generators/operation_generator_test.rb".freeze, "test/unit/rails_ops/hookup_test.rb".freeze, "test/unit/rails_ops/mixins/controller_test.rb".freeze, "test/unit/rails_ops/mixins/model/deep_nesting_test.rb".freeze, "test/unit/rails_ops/mixins/model/marshalling_test.rb".freeze, "test/unit/rails_ops/mixins/param_authorization_test.rb".freeze, "test/unit/rails_ops/mixins/policies_test.rb".freeze, "test/unit/rails_ops/operation/auth_test.rb".freeze, "test/unit/rails_ops/operation/model/create_test.rb".freeze, "test/unit/rails_ops/operation/model/destroy_test.rb".freeze, "test/unit/rails_ops/operation/model/load_test.rb".freeze, "test/unit/rails_ops/operation/model/sti_test.rb".freeze, "test/unit/rails_ops/operation/model/update_test.rb".freeze, "test/unit/rails_ops/operation/model_test.rb".freeze, "test/unit/rails_ops/operation/update_lazy_auth_test.rb".freeze, "test/unit/rails_ops/operation_test.rb".freeze, "test/unit/rails_ops/profiler_test.rb".freeze]
13
13
  s.rubygems_version = "3.4.6".freeze
14
14
  s.summary = "An operations service layer for rails projects.".freeze
@@ -37,6 +37,7 @@ class RailsOps::HookupTest < ActiveSupport::TestCase
37
37
  end
38
38
 
39
39
  def test_dont_draw_twice
40
+ RailsOps.hookup.load_config
40
41
  assert_raises_with_message RuntimeError, "Hooks can't be drawn twice." do
41
42
  RailsOps.hookup.draw do
42
43
  run 'RailsOps::HookupTest::HookupTarget' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_ops
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.6
4
+ version: 1.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sitrox
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-25 00:00:00.000000000 Z
11
+ date: 2023-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -415,7 +415,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
415
415
  - !ruby/object:Gem::Version
416
416
  version: '0'
417
417
  requirements: []
418
- rubygems_version: 3.4.10
418
+ rubygems_version: 3.4.6
419
419
  signing_key:
420
420
  specification_version: 4
421
421
  summary: An operations service layer for rails projects.