rails_ops 1.7.2 → 1.7.4
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/.github/workflows/ruby.yml +0 -4
- data/Appraisals +3 -0
- data/CHANGELOG.md +15 -0
- data/CLAUDE.md +83 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +7 -2
- data/LICENSE +1 -1
- data/README.md +452 -105
- data/VERSION +1 -1
- data/gemfiles/rails_6.0.gemfile +2 -0
- data/gemfiles/rails_6.1.gemfile +2 -0
- data/gemfiles/rails_7.0.gemfile +2 -0
- data/gemfiles/rails_7.1.gemfile +1 -0
- data/gemfiles/rails_7.2.gemfile +1 -0
- data/gemfiles/rails_8.0.gemfile +1 -0
- data/lib/rails_ops/mixins/model/nesting.rb +5 -0
- data/lib/rails_ops/mixins/policies.rb +8 -0
- data/lib/rails_ops/mixins/schema_validation.rb +6 -1
- data/rails_ops.gemspec +4 -4
- data/test/unit/rails_ops/mixins/policies_test.rb +93 -0
- data/test/unit/rails_ops/operation_test.rb +43 -0
- metadata +4 -9
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.7.
|
|
1
|
+
1.7.4
|
data/gemfiles/rails_6.0.gemfile
CHANGED
data/gemfiles/rails_6.1.gemfile
CHANGED
data/gemfiles/rails_7.0.gemfile
CHANGED
data/gemfiles/rails_7.1.gemfile
CHANGED
data/gemfiles/rails_7.2.gemfile
CHANGED
data/gemfiles/rails_8.0.gemfile
CHANGED
|
@@ -168,6 +168,11 @@ module RailsOps::Mixins::Model::Nesting
|
|
|
168
168
|
def perform_nested_model_ops!
|
|
169
169
|
fail 'Nested model operations can only be performed once.' if nested_model_ops_performed?
|
|
170
170
|
|
|
171
|
+
# Run before_model_validation policies. This is the correct place for
|
|
172
|
+
# attribute cleanup and sanitization as the model attributes are
|
|
173
|
+
# assigned but validation has not yet run.
|
|
174
|
+
run_policies :before_model_validation
|
|
175
|
+
|
|
171
176
|
# Validate the whole model hierarchy. Since we're calling 'model' here, this
|
|
172
177
|
# line also makes sure a model is built.
|
|
173
178
|
model.validate!
|
|
@@ -11,6 +11,7 @@ module RailsOps::Mixins::Policies
|
|
|
11
11
|
before_perform
|
|
12
12
|
after_perform
|
|
13
13
|
before_nested_model_ops
|
|
14
|
+
before_model_validation
|
|
14
15
|
before_model_save
|
|
15
16
|
].freeze
|
|
16
17
|
|
|
@@ -33,6 +34,13 @@ module RailsOps::Mixins::Policies
|
|
|
33
34
|
fail 'Policy :before_attr_assign may not be used unless your operation defines the `assign_attributes` method!'
|
|
34
35
|
end
|
|
35
36
|
|
|
37
|
+
# The `before_model_validation` chain is only allowed if the operation
|
|
38
|
+
# is a model operation, i.e. it needs to implement the `build_model`
|
|
39
|
+
# method.
|
|
40
|
+
if chain == :before_model_validation && !method_defined?(:build_model)
|
|
41
|
+
fail 'Policy :before_model_validation may not be used unless your operation defines the `build_model` method!'
|
|
42
|
+
end
|
|
43
|
+
|
|
36
44
|
self._policy_chains = _policy_chains.dup
|
|
37
45
|
if prepend_action
|
|
38
46
|
_policy_chains[chain] = [block] + _policy_chains[chain]
|
|
@@ -25,7 +25,12 @@ module RailsOps::Mixins::SchemaValidation
|
|
|
25
25
|
# @param *args [Array] Parameters to pass at schema initialization
|
|
26
26
|
# @yield Block to pass at schema initialization
|
|
27
27
|
def schema2(*args, &block)
|
|
28
|
-
|
|
28
|
+
if args.any? || block_given?
|
|
29
|
+
self._op_schema = Schemacop::Schema.new(*args, &block)
|
|
30
|
+
else
|
|
31
|
+
# Define empty schema (not possible with V2 schema).
|
|
32
|
+
schema3
|
|
33
|
+
end
|
|
29
34
|
end
|
|
30
35
|
|
|
31
36
|
def schema3(type = :hash, *args, **kwargs, &block)
|
data/rails_ops.gemspec
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: rails_ops 1.7.
|
|
2
|
+
# stub: rails_ops 1.7.4 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "rails_ops".freeze
|
|
6
|
-
s.version = "1.7.
|
|
6
|
+
s.version = "1.7.4"
|
|
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 = "
|
|
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, "gemfiles/rails_7.1.gemfile".freeze, "gemfiles/rails_7.2.gemfile".freeze, "gemfiles/rails_8.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]
|
|
11
|
+
s.date = "2026-02-18"
|
|
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, "CLAUDE.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, "gemfiles/rails_7.1.gemfile".freeze, "gemfiles/rails_7.2.gemfile".freeze, "gemfiles/rails_8.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.licenses = ["MIT".freeze]
|
|
14
14
|
s.rubygems_version = "3.4.6".freeze
|
|
15
15
|
s.summary = "An operations service layer for rails projects.".freeze
|
|
@@ -85,6 +85,99 @@ class RailsOps::Mixins::PoliciesTest < ActiveSupport::TestCase
|
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
def test_before_model_validation_sequence
|
|
89
|
+
group = Group.create!
|
|
90
|
+
|
|
91
|
+
op = Class.new(RailsOps::Operation::Model::Update) do
|
|
92
|
+
attr_reader :sequence
|
|
93
|
+
|
|
94
|
+
model Group
|
|
95
|
+
|
|
96
|
+
policy :before_attr_assign do
|
|
97
|
+
@sequence = []
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
policy :before_nested_model_ops do
|
|
101
|
+
@sequence << :before_nested_model_ops
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
policy :before_model_validation do
|
|
105
|
+
@sequence << :before_model_validation
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
policy :before_model_save do
|
|
109
|
+
@sequence << :before_model_save
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def perform
|
|
113
|
+
@sequence << :before_save
|
|
114
|
+
save!
|
|
115
|
+
@sequence << :after_save
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
result = op.run!(id: group.id)
|
|
120
|
+
assert_equal %i[
|
|
121
|
+
before_save
|
|
122
|
+
before_nested_model_ops
|
|
123
|
+
before_model_validation
|
|
124
|
+
before_model_save
|
|
125
|
+
after_save
|
|
126
|
+
], result.sequence
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_before_model_validation_needs_build_model
|
|
130
|
+
assert_raises RuntimeError, match: /Policy :before_model_validation may not be used unless your operation defines the `build_model` method!/ do
|
|
131
|
+
Class.new(RailsOps::Operation) do
|
|
132
|
+
policy :before_model_validation do
|
|
133
|
+
# Nothing needed here
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def test_before_model_validation_attribute_sanitization
|
|
140
|
+
op = Class.new(RailsOps::Operation::Model::Create) do
|
|
141
|
+
model Group
|
|
142
|
+
|
|
143
|
+
policy :before_model_validation do
|
|
144
|
+
# Simulate role-dependent attribute cleanup: nil out color
|
|
145
|
+
# when name is "restricted".
|
|
146
|
+
model.color = nil if model.name == 'restricted'
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# With name "restricted", the policy should nil out color before
|
|
151
|
+
# validation runs.
|
|
152
|
+
result = op.run!(group: { name: 'restricted', color: 'red' })
|
|
153
|
+
assert_equal 'restricted', result.model.name
|
|
154
|
+
assert_nil result.model.color
|
|
155
|
+
|
|
156
|
+
# With a different name, color should be preserved.
|
|
157
|
+
result = op.run!(group: { name: 'normal', color: 'blue' })
|
|
158
|
+
assert_equal 'normal', result.model.name
|
|
159
|
+
assert_equal 'blue', result.model.color
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_before_model_validation_runs_before_validation
|
|
163
|
+
# Add a validation to Group that rejects color "invalid", then
|
|
164
|
+
# use a before_model_validation policy to fix it before validate!
|
|
165
|
+
# runs. If the policy runs at the right time, the operation
|
|
166
|
+
# succeeds.
|
|
167
|
+
op = Class.new(RailsOps::Operation::Model::Create) do
|
|
168
|
+
model Group do
|
|
169
|
+
validates :color, exclusion: { in: ['invalid'] }
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
policy :before_model_validation do
|
|
173
|
+
model.color = 'fixed' if model.color == 'invalid'
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
result = op.run!(group: { name: 'test', color: 'invalid' })
|
|
178
|
+
assert_equal 'fixed', result.model.color
|
|
179
|
+
end
|
|
180
|
+
|
|
88
181
|
def test_prepend_action
|
|
89
182
|
op = Class.new(RailsOps::Operation) do
|
|
90
183
|
attr_reader :sequence
|
|
@@ -198,6 +198,49 @@ class RailsOps::OperationTest < ActiveSupport::TestCase
|
|
|
198
198
|
end
|
|
199
199
|
end
|
|
200
200
|
|
|
201
|
+
def test_no_schema
|
|
202
|
+
op = Class.new(RailsOps::Operation) do
|
|
203
|
+
def perform; end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
assert_nothing_raised do
|
|
207
|
+
op.run!(foo: :bar)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def test_empty_schema
|
|
212
|
+
op = Class.new(RailsOps::Operation) do
|
|
213
|
+
schema
|
|
214
|
+
def perform; end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
assert_raises Schemacop::Exceptions::ValidationError do
|
|
218
|
+
op.run!(foo: :bar)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def test_empty_schema2
|
|
223
|
+
op = Class.new(RailsOps::Operation) do
|
|
224
|
+
schema2
|
|
225
|
+
def perform; end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
assert_raises Schemacop::Exceptions::ValidationError do
|
|
229
|
+
op.run!(foo: :bar)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def test_empty_schema3
|
|
234
|
+
op = Class.new(RailsOps::Operation) do
|
|
235
|
+
schema3
|
|
236
|
+
def perform; end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
assert_raises Schemacop::Exceptions::ValidationError do
|
|
240
|
+
op.run!(foo: :bar)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
201
244
|
def test_op_with_schema3(use_default: false)
|
|
202
245
|
op = Class.new(RailsOps::Operation) do
|
|
203
246
|
schema_block = proc do
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_ops
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.7.
|
|
4
|
+
version: 1.7.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sitrox
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2026-02-18 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: active_type
|
|
@@ -86,8 +85,6 @@ dependencies:
|
|
|
86
85
|
- - "<="
|
|
87
86
|
- !ruby/object:Gem::Version
|
|
88
87
|
version: '3.1'
|
|
89
|
-
description:
|
|
90
|
-
email:
|
|
91
88
|
executables: []
|
|
92
89
|
extensions: []
|
|
93
90
|
extra_rdoc_files: []
|
|
@@ -99,6 +96,7 @@ files:
|
|
|
99
96
|
- ".rubocop.yml"
|
|
100
97
|
- Appraisals
|
|
101
98
|
- CHANGELOG.md
|
|
99
|
+
- CLAUDE.md
|
|
102
100
|
- Gemfile
|
|
103
101
|
- Gemfile.lock
|
|
104
102
|
- LICENSE
|
|
@@ -260,11 +258,9 @@ files:
|
|
|
260
258
|
- test/unit/rails_ops/operation/update_lazy_auth_test.rb
|
|
261
259
|
- test/unit/rails_ops/operation_test.rb
|
|
262
260
|
- test/unit/rails_ops/profiler_test.rb
|
|
263
|
-
homepage:
|
|
264
261
|
licenses:
|
|
265
262
|
- MIT
|
|
266
263
|
metadata: {}
|
|
267
|
-
post_install_message:
|
|
268
264
|
rdoc_options: []
|
|
269
265
|
require_paths:
|
|
270
266
|
- lib
|
|
@@ -279,8 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
279
275
|
- !ruby/object:Gem::Version
|
|
280
276
|
version: '0'
|
|
281
277
|
requirements: []
|
|
282
|
-
rubygems_version:
|
|
283
|
-
signing_key:
|
|
278
|
+
rubygems_version: 4.0.2
|
|
284
279
|
specification_version: 4
|
|
285
280
|
summary: An operations service layer for rails projects.
|
|
286
281
|
test_files:
|