rails_ops 1.4.3 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcb574a4ebd4148a9db8bc6ae9e129b015140175352dccb01b0f9eb6e53a4afd
4
- data.tar.gz: 31322cd290160be87eee75fe5ca3604d7611344f4b77faff2681364a34b166f5
3
+ metadata.gz: 9c18eddf15b9f713101e8cd2e783c01bffb0c664ea1e76b497c6a4ae0ff07eae
4
+ data.tar.gz: 4f4d8e61f2d3de18e6215417016de13251625c2fa238b78a37bf52c629cb2ede
5
5
  SHA512:
6
- metadata.gz: 81e0839e7d210cc6011868a3ea69bf5dd2714aabe96137ee6109468a00ff69400ccfe6fcc5a52a93c772dad15e3638bd0944ffc073f18f010ebd33f648cae1b1
7
- data.tar.gz: 1bbc3608339025bd703a5a74a192056f462a5fb756f76531f570cedf754b0d5009d2e69319afc940a1dfc57e38a67fbf1a4fae8f62fb702fc35cb378adcc7825
6
+ metadata.gz: 88f1d0f750f1bd794962984fa2d4e8fb37c71456e00ef8a7b795cc5fc08a748e57f1757b7bd61e8a7db9e2b76a42bae6e4ab3047568a36288a15c6cde2953aad
7
+ data.tar.gz: 11432ac0dd217407e7f3209b9201d7d408746db1d4c7d813dec706ce42b3c893551f5bfeda81e454dd8daaa459811ab01e71239e33af26c0bbfe5f6eedf022ad
data/.gitignore CHANGED
@@ -16,3 +16,4 @@
16
16
  /test/dummy/log/
17
17
  /test/tmp/
18
18
  /gemfiles/*.lock
19
+ /.idea
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.4 (2023-07-10)
4
+
5
+ * Adapt method `sub_op` to catch `<op-class>.validation_errors` and re-throw
6
+ them as `RailsOps::Exceptions::SubOpValidationFailed`.
7
+
3
8
  ## 1.4.3 (2023-03-27)
4
9
 
5
10
  * Extend the `operation` generator to accept additional flags to skip the
@@ -32,7 +37,8 @@
32
37
 
33
38
  ### Upgrading
34
39
 
35
- Please see #33 for more information on this change. If all of your operations
40
+ Please see [#33](https://github.com/sitrox/rails_ops/issues/33) for more information
41
+ on this change. If all of your operations
36
42
  follow the standard naming conventions (e.g. `Operations::User::Update` for
37
43
  updating a model named `User`), no changes will be necessary. If you don't, you
38
44
  may need to manually specify a `param_key` when using nested model operations
data/Rakefile CHANGED
@@ -24,6 +24,7 @@ task :gemspec do
24
24
  spec.add_development_dependency 'colorize'
25
25
  spec.add_development_dependency 'rubocop', '1.45.1'
26
26
  spec.add_development_dependency 'sprockets-rails'
27
+ spec.add_development_dependency 'simplecov'
27
28
  spec.add_dependency 'active_type', '>= 1.3.0'
28
29
  spec.add_dependency 'minitest'
29
30
  spec.add_dependency 'rails'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.3
1
+ 1.4.4
@@ -52,16 +52,16 @@ class OperationGenerator < Rails::Generators::NamedBase
52
52
 
53
53
  operations_path += @underscored_name.to_s
54
54
 
55
- if !@excluded_actions.include?(:show)
55
+ unless @excluded_actions.include?(:show)
56
56
  template 'load.erb', "#{operations_path}/load.rb"
57
57
  end
58
- if !@excluded_actions.include?(:create)
58
+ unless @excluded_actions.include?(:create)
59
59
  template 'create.erb', "#{operations_path}/create.rb"
60
60
  end
61
- if !@excluded_actions.include?(:update)
61
+ unless @excluded_actions.include?(:update)
62
62
  template 'update.erb', "#{operations_path}/update.rb"
63
63
  end
64
- if !@excluded_actions.include?(:destroy)
64
+ unless @excluded_actions.include?(:destroy)
65
65
  template 'destroy.erb', "#{operations_path}/destroy.rb"
66
66
  end
67
67
  end
@@ -10,7 +10,7 @@ class RailsOps::Hookup::DSLValidator
10
10
  def validate!
11
11
  # Check infinity loop
12
12
  if target_hooks.any? { |name, targets| recursion?(targets, name) }
13
- fail StandardError::SystemStackError.new, "Infinite loop detected in hooks configuration: #{inspect_trace}."
13
+ fail SystemStackError.new, "Infinite loop detected in hooks configuration: #{inspect_trace}."
14
14
  end
15
15
  end
16
16
 
@@ -23,7 +23,7 @@ class RailsOps::Hookup
23
23
  unless @config_loaded
24
24
  @config_loaded = true
25
25
 
26
- if File.exist?(CONFIG_PATH)
26
+ if File.exist?(Rails.root.join(CONFIG_PATH))
27
27
  load Rails.root.join(CONFIG_PATH)
28
28
  else
29
29
  Rails.logger.debug "RailsOps could not find hookup #{CONFIG_PATH}, using empty hookup configuration."
@@ -11,6 +11,8 @@ module RailsOps::Mixins::SubOps
11
11
  def sub_op(op, params = {})
12
12
  new_context = context.spawn(self)
13
13
  return op.new(new_context, params)
14
+ rescue *op.validation_errors => e
15
+ fail RailsOps::Exceptions::SubOpValidationFailed, e
14
16
  end
15
17
 
16
18
  # Operation-equivalent of controller method 'run!': Instantiates and runs the
@@ -149,7 +149,7 @@ class RailsOps::Operation
149
149
 
150
150
  # Fails with an exception if the operation has not been performed yet.
151
151
  def check_performed!
152
- fail 'Operation has not yet been perfomed.' unless performed?
152
+ fail 'Operation has not yet been performed.' unless performed?
153
153
  end
154
154
 
155
155
  protected
data/rails_ops.gemspec CHANGED
@@ -1,18 +1,18 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: rails_ops 1.4.3 ruby lib
2
+ # stub: rails_ops 1.4.4 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "rails_ops".freeze
6
- s.version = "1.4.3"
6
+ s.version = "1.4.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 = "2023-03-27"
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, "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/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/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/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/mixins/model/deep_nesting_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/model/create_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_auth_test.rb".freeze, "test/unit/rails_ops/operation/update_lazy_auth_test.rb".freeze, "test/unit/rails_ops/operation_test.rb".freeze]
11
+ s.date = "2023-07-10"
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, "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
15
- s.test_files = ["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/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/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/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/mixins/model/deep_nesting_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/model/create_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_auth_test.rb".freeze, "test/unit/rails_ops/operation/update_lazy_auth_test.rb".freeze, "test/unit/rails_ops/operation_test.rb".freeze]
15
+ s.test_files = ["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]
16
16
 
17
17
  s.specification_version = 4
18
18
 
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
25
25
  s.add_development_dependency(%q<colorize>.freeze, [">= 0"])
26
26
  s.add_development_dependency(%q<rubocop>.freeze, ["= 1.45.1"])
27
27
  s.add_development_dependency(%q<sprockets-rails>.freeze, [">= 0"])
28
+ s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
28
29
  s.add_runtime_dependency(%q<active_type>.freeze, [">= 1.3.0"])
29
30
  s.add_runtime_dependency(%q<minitest>.freeze, [">= 0"])
30
31
  s.add_runtime_dependency(%q<rails>.freeze, [">= 0"])
@@ -0,0 +1,28 @@
1
+ class GroupController < ApplicationController
2
+ attr_reader :current_user
3
+ skip_before_action :verify_authenticity_token
4
+
5
+ def initialize
6
+ super
7
+ @current_user = Class.new
8
+ end
9
+
10
+ def show
11
+ cls = Class.new(RailsOps::Operation::Model::Load) do
12
+ model Group
13
+ end
14
+
15
+ op cls, id: params[:id]
16
+ render json: model
17
+ end
18
+
19
+ def update
20
+ cls = Class.new(RailsOps::Operation::Model::Update) do
21
+ model Group
22
+ end
23
+
24
+ op cls, id: params[:id], group: {name: params[:name]}
25
+ run!
26
+ render json: model
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ class Ability
2
+ include CanCan::Ability
3
+
4
+ def initialize(_user)
5
+ can :manage, :all
6
+ end
7
+ end
@@ -1 +1,5 @@
1
- class Animal < ApplicationRecord; end
1
+ class Animal < ApplicationRecord
2
+ has_many :dogs
3
+ belongs_to :bird, optional: true
4
+ belongs_to :phoenix, optional: true, validate: false, autosave: false
5
+ end
@@ -1 +1,3 @@
1
- class Bird < Animal; end
1
+ class Bird < Animal
2
+ has_one :phoenix, inverse_of: :bird
3
+ end
@@ -1 +1,3 @@
1
- class Phoenix < Bird; end
1
+ class Phoenix < Bird
2
+ belongs_to :bird, optional: true, autosave: false, inverse_of: :phoenix, validate: true
3
+ end
@@ -51,4 +51,6 @@ Rails.application.configure do
51
51
  # Use an evented file watcher to asynchronously detect changes in source code,
52
52
  # routes, locales, etc. This feature depends on the listen gem.
53
53
  # config.file_watcher = ActiveSupport::EventedFileUpdateChecker
54
+
55
+ config.hosts = ['www.example.com']
54
56
  end
@@ -88,4 +88,6 @@ Rails.application.configure do
88
88
 
89
89
  # Do not dump schema after migrations.
90
90
  config.active_record.dump_schema_after_migration = false
91
+
92
+ config.hosts = ['www.example.com']
91
93
  end
@@ -0,0 +1,5 @@
1
+ RailsOps.hookup.draw do
2
+ run 'RailsOps::HookupTest::HookupTarget' do
3
+ on 'RailsOps::HookupTest::HookupStarter'
4
+ end
5
+ end
@@ -1,3 +1,4 @@
1
1
  Rails.application.routes.draw do
2
2
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
3
+ resources :group, only: [:show, :update]
3
4
  end
data/test/test_helper.rb CHANGED
@@ -1,3 +1,8 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/test/'
4
+ end
5
+
1
6
  require File.expand_path('../test/dummy/config/environment.rb', __dir__)
2
7
  # ActiveRecord::Migrator.migrations_paths = [File.expand_path("../../test/dummy/db/migrate", __FILE__)]
3
8
  require 'rails/test_help'
@@ -0,0 +1,82 @@
1
+ require 'test_helper'
2
+
3
+ class RailsOps::HookupTest < ActiveSupport::TestCase
4
+ include TestHelper
5
+
6
+ class RailsOps::HookupTest::HookupStarter < RailsOps::Operation::Model::Create
7
+ model ::Group
8
+ end
9
+
10
+ class RailsOps::HookupTest::HookupTarget < RailsOps::Operation
11
+ def perform
12
+ Group.find_by(name: 'hookup_test_group').update({ color: 'blue' })
13
+ end
14
+ end
15
+
16
+ def test_hooked_op
17
+ group = RailsOps::HookupTest::HookupStarter.run!(group: { name: 'hookup_test_group' }).model
18
+ group.reload
19
+ assert_equal 'blue', group.color
20
+ end
21
+
22
+ def test_recursive_hookup_raises
23
+ RailsOps.hookup.instance_variable_set(:@drawn, false)
24
+ RailsOps.hookup.instance_variable_set(:@config_loaded, false)
25
+ assert_raises SystemStackError do
26
+ RailsOps.hookup.draw do
27
+ run 'RailsOps::HookupTest::HookupTarget' do
28
+ on 'RailsOps::HookupTest::HookupStarter'
29
+ end
30
+
31
+ run 'RailsOps::HookupTest::HookupStarter' do
32
+ on 'RailsOps::HookupTest::HookupTarget'
33
+ end
34
+ end
35
+ end
36
+ RailsOps.hookup.load_config
37
+ end
38
+
39
+ def test_dont_draw_twice
40
+ assert_raises_with_message RuntimeError, "Hooks can't be drawn twice." do
41
+ RailsOps.hookup.draw do
42
+ run 'RailsOps::HookupTest::HookupTarget' do
43
+ on 'RailsOps::HookupTest::HookupStarter'
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ def test_missing_hookup_op
50
+ RailsOps.hookup.load_config
51
+ RailsOps.hookup.instance_variable_set(:@drawn, false)
52
+ RailsOps.hookup.draw do
53
+ run 'RailsOps::HookupTest::HookupIllusiveTarget' do
54
+ on 'RailsOps::HookupTest::HookupStarter'
55
+ end
56
+ end
57
+
58
+ assert_raises_with_message RuntimeError, 'Could not find hook target operation RailsOps::HookupTest::HookupIllusiveTarget.' do
59
+ RailsOps::HookupTest::HookupStarter.run!(group: { name: 'group' })
60
+ end
61
+
62
+ RailsOps.hookup.instance_variable_set(:@drawn, false)
63
+ RailsOps.hookup.instance_variable_set(:@config_loaded, false)
64
+ RailsOps.hookup.load_config
65
+ end
66
+
67
+ def test_missing_config_file
68
+ orig_path = RailsOps::Hookup::CONFIG_PATH
69
+ RailsOps::Hookup.const_set(:CONFIG_PATH, '/def/doesnt/exist')
70
+ RailsOps.hookup.instance_variable_set(:@drawn, false)
71
+ RailsOps.hookup.instance_variable_set(:@config_loaded, false)
72
+ assert_nothing_raised do
73
+ RailsOps.hookup.load_config
74
+ end
75
+ assert_equal({}, RailsOps.hookup.hooks)
76
+
77
+ RailsOps::Hookup.const_set(:CONFIG_PATH, orig_path)
78
+ RailsOps.hookup.instance_variable_set(:@drawn, false)
79
+ RailsOps.hookup.instance_variable_set(:@config_loaded, false)
80
+ RailsOps.hookup.load_config
81
+ end
82
+ end
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+ require 'cancancan'
3
+
4
+ class RailsOps::Mixins::ControllerTest < ActionDispatch::IntegrationTest
5
+ include TestHelper
6
+
7
+ def test_controller_op
8
+ group = Group.create(name: 'group')
9
+ get group_url(group), as: :json
10
+ assert_equal 'group', JSON.parse(@response.body)['name']
11
+ end
12
+
13
+ def test_controller_op_run
14
+ group = Group.create(name: 'group')
15
+ patch group_url(group), params: { name: 'group2' }, as: :json
16
+ assert_equal 'group2', JSON.parse(@response.body)['name']
17
+
18
+ group.reload
19
+ assert_equal 'group2', group.name
20
+ end
21
+ end
@@ -92,6 +92,67 @@ class RailsOps::Mixins::Model::DeepNestingTest < ActiveSupport::TestCase
92
92
  assert_equal 'CPU', model.mainboard.cpu.name
93
93
  end
94
94
 
95
+ def test_without_asoc
96
+ assert_raises_with_message RuntimeError, 'Association cat could not be found for Animal.' do
97
+ Class.new(RailsOps::Operation::Model::Create) do
98
+ model Animal
99
+
100
+ nest_model_op :cat, Class.new(RailsOps::Operation::Model::Create) do
101
+ model Cat
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ def test_wrong_asoc_type
108
+ assert_raises_with_message RuntimeError,
109
+ 'Method nest_model_op only supports :belongs_to associations, but association dogs of model Animal is a has_many association.' do
110
+ Class.new(RailsOps::Operation::Model::Create) do
111
+ model Animal
112
+
113
+ nest_model_op :dogs, Class.new(RailsOps::Operation::Model::Create) do
114
+ model Dog
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ def test_autosave_on
121
+ assert_raises_with_message RuntimeError, 'Association bird of Animal has :autosave turned on. This is not supported by nest_model_op.' do
122
+ Class.new(RailsOps::Operation::Model::Create) do
123
+ model Animal
124
+
125
+ nest_model_op :bird, Class.new(RailsOps::Operation::Model::Create) do
126
+ model Bird
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ def test_validation_off
133
+ assert_raises_with_message RuntimeError, 'Association phoenix of Animal has :validate turned off. This is not supported by nest_model_op.' do
134
+ Class.new(RailsOps::Operation::Model::Create) do
135
+ model Animal
136
+
137
+ nest_model_op :phoenix, Class.new(RailsOps::Operation::Model::Create) do
138
+ model Phoenix
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ def test_inverse_autosave_on
145
+ assert_raises_with_message RuntimeError, 'Association phoenix of Bird has :autosave turned on. This is not supported by nest_model_op.' do
146
+ Class.new(RailsOps::Operation::Model::Create) do
147
+ model Phoenix
148
+
149
+ nest_model_op :bird, Class.new(RailsOps::Operation::Model::Create) do
150
+ model Bird
151
+ end
152
+ end
153
+ end
154
+ end
155
+
95
156
  def test_create_computer_level_1_validation_error
96
157
  op = COMPUTER_CREATION_OP.new(
97
158
  computer: {
@@ -197,7 +258,6 @@ class RailsOps::Mixins::Model::DeepNestingTest < ActiveSupport::TestCase
197
258
  )
198
259
 
199
260
  refute update_op.run
200
- assert_equal :name, update_op.model.mainboard.errors.first.attribute
201
- assert_equal :blank, update_op.model.mainboard.errors.first.type
261
+ assert update_op.model.mainboard.errors.added?(:name, :blank)
202
262
  end
203
263
  end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ class RailsOps::Mixins::Model::MarshallingTest < ActiveSupport::TestCase
4
+ include TestHelper
5
+
6
+ class RailsOps::Mixins::Model::MarshallingTest::ParentOp < RailsOps::Operation::Model::Create
7
+ model Group
8
+ attr_reader :loaded_child_class
9
+ attr_reader :loaded_child_parent_op
10
+
11
+ def perform
12
+ sub_op = run_sub! RailsOps::Mixins::Model::MarshallingTest::ChildOp
13
+
14
+ dump_res = Marshal.dump(sub_op)
15
+ # rubocop:disable Security/MarshalLoad
16
+ load_res = Marshal.load(dump_res)
17
+ # rubocop:enable Security/MarshalLoad
18
+
19
+ @loaded_child_class = load_res.class
20
+ @loaded_child_parent_op = load_res.model.parent_op
21
+ end
22
+ end
23
+
24
+ class RailsOps::Mixins::Model::MarshallingTest::ChildOp < RailsOps::Operation::Model::Create
25
+ model Group
26
+ def perform; end
27
+ end
28
+
29
+ def test_marshal_dump_and_load
30
+ assert_nothing_raised do
31
+ op_res = RailsOps::Mixins::Model::MarshallingTest::ParentOp.run!
32
+ assert_equal RailsOps::Mixins::Model::MarshallingTest::ChildOp, op_res.loaded_child_class
33
+ assert_nil op_res.loaded_child_parent_op
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,120 @@
1
+ require 'test_helper'
2
+ require 'rails_ops/authorization_backend/can_can_can'
3
+ require 'cancancan'
4
+
5
+ class RailsOps::Operation::AuthTest < ActiveSupport::TestCase
6
+ include TestHelper
7
+
8
+ LOAD_OP = Class.new(RailsOps::Operation::Model::Load) do
9
+ model ::Group
10
+ end
11
+
12
+ LOAD_OP_WITHOUT_AUTH = Class.new(RailsOps::Operation::Model::Load) do
13
+ model ::Group
14
+ without_authorization
15
+ end
16
+
17
+ UPDATE_OP = Class.new(RailsOps::Operation::Model::Update) do
18
+ model ::Group
19
+ end
20
+
21
+ CREATE_OP = Class.new(RailsOps::Operation::Model::Create) do
22
+ model ::Group
23
+ end
24
+
25
+ DESTROY_OP = Class.new(RailsOps::Operation::Model::Destroy) do
26
+ model ::Group
27
+ end
28
+
29
+ ABILITY = Class.new do
30
+ include CanCan::Ability
31
+
32
+ def initialize(read: false, update: false, create: false, destroy: false)
33
+ super()
34
+
35
+ can :read, Group if read
36
+ can :update, Group if update
37
+ can :create, Group if create
38
+ can :destroy, Group if destroy
39
+ end
40
+ end
41
+
42
+ setup do
43
+ Group.create!(id: 1, name: 'Group')
44
+ RailsOps.config.authorization_backend = 'RailsOps::AuthorizationBackend::CanCanCan'
45
+ end
46
+
47
+ def test_unpermitted_read
48
+ ctx = RailsOps::Context.new(ability: ABILITY.new)
49
+ assert_raises CanCan::AccessDenied do
50
+ LOAD_OP.new(ctx, id: 1)
51
+ end
52
+ end
53
+
54
+ def test_unpermitted_read_without_auth
55
+ ctx = RailsOps::Context.new(ability: ABILITY.new)
56
+ assert_nothing_raised do
57
+ LOAD_OP_WITHOUT_AUTH.new(ctx, id: 1)
58
+ end
59
+ end
60
+
61
+ def test_permitted_read
62
+ ctx = RailsOps::Context.new(ability: ABILITY.new(read: true))
63
+ assert_nothing_raised do
64
+ res = LOAD_OP.new(ctx, id: 1)
65
+ assert_equal 'Group', res.model.name
66
+ end
67
+ end
68
+
69
+ def test_unpermitted_update
70
+ ctx = RailsOps::Context.new(ability: ABILITY.new(read: true))
71
+ assert_raises CanCan::AccessDenied do
72
+ op = UPDATE_OP.new(ctx, id: 1, group: { name: 'Group2' })
73
+ res = op.run!
74
+ assert_equal 'Group', res.model.name
75
+ end
76
+ end
77
+
78
+ def test_permitted_update
79
+ ctx = RailsOps::Context.new(ability: ABILITY.new(read: true, update: true))
80
+ assert_nothing_raised do
81
+ op = UPDATE_OP.new(ctx, id: 1, group: { name: 'Group2' })
82
+ res = op.run!
83
+ assert_equal 'Group2', res.model.name
84
+ end
85
+ end
86
+
87
+ def test_unpermitted_create
88
+ ctx = RailsOps::Context.new(ability: ABILITY.new(read: true))
89
+ assert_raises CanCan::AccessDenied do
90
+ op = CREATE_OP.new(ctx, id: 2, group: { name: 'Group2' })
91
+ op.run!
92
+ end
93
+ end
94
+
95
+ def test_permitted_create
96
+ ctx = RailsOps::Context.new(ability: ABILITY.new(read: true, create: true))
97
+ assert_nothing_raised do
98
+ op = CREATE_OP.new(ctx, id: 2, group: { name: 'Group2' })
99
+ op.run!
100
+ res = LOAD_OP.new(id: 2)
101
+ assert_equal 'Group2', res.model.name
102
+ end
103
+ end
104
+
105
+ def test_unpermitted_destroy
106
+ ctx = RailsOps::Context.new(ability: ABILITY.new(read: true))
107
+ assert_raises CanCan::AccessDenied do
108
+ op = DESTROY_OP.new(ctx, id: 1)
109
+ op.run!
110
+ end
111
+ end
112
+
113
+ def test_permitted_destroy
114
+ ctx = RailsOps::Context.new(ability: ABILITY.new(read: true, destroy: true))
115
+ assert_nothing_raised do
116
+ op = DESTROY_OP.new(ctx, id: 1)
117
+ op.run!
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,31 @@
1
+ class RailsOps::Operation::Model::DestroyTest < ActiveSupport::TestCase
2
+ include TestHelper
3
+
4
+ BASIC_OP = Class.new(RailsOps::Operation::Model::Destroy) do
5
+ model Group
6
+ end
7
+
8
+ def test_basic
9
+ g = Group.create
10
+ op = BASIC_OP.new(id: g.id)
11
+ assert_equal g, op.model
12
+ assert_equal Group, op.model.class
13
+ op.run!
14
+ assert op.model.destroyed?
15
+ end
16
+
17
+ def test_not_deletable
18
+ g = Group.create
19
+ cls = Class.new(RailsOps::Operation::Model::Destroy) do
20
+ model Group, 'NotDeletableGroup' do
21
+ def deleteable?
22
+ false
23
+ end
24
+ end
25
+ end
26
+ op = cls.new(id: g.id)
27
+ assert_raises RailsOps::Exceptions::ModelNotDeleteable do
28
+ op.run!
29
+ end
30
+ end
31
+ end
@@ -51,4 +51,13 @@ class RailsOps::Operation::Model::LoadTest < ActiveSupport::TestCase
51
51
  g = Group.create(name: 'g1')
52
52
  assert_equal g, cls.new(name: 'g1').model
53
53
  end
54
+
55
+ def test_too_many_authorization_actions
56
+ assert_raises_with_message ArgumentError, 'Too many arguments' do
57
+ Class.new(RailsOps::Operation::Model::Load) do
58
+ model Group
59
+ model_authorization_action :read, :update
60
+ end
61
+ end
62
+ end
54
63
  end
@@ -47,6 +47,21 @@ class RailsOps::Operation::ModelTest < ActiveSupport::TestCase
47
47
  assert_equal 'Example', cls.model.virtual_model_name
48
48
  end
49
49
 
50
+ def test_virtual_model_write_attribute
51
+ cls = Class.new(RailsOps::Operation::Model) do
52
+ model RailsOps::VirtualModel, 'Example' do
53
+ attribute :name, default: 'name'
54
+ end
55
+ end
56
+
57
+ assert_equal 'name', cls.model.new.read_attribute(:name)
58
+ assert_nothing_raised do
59
+ obj = cls.model.new
60
+ obj.write_attribute(:name, 'name2')
61
+ assert_equal 'name2', obj.read_attribute(:name)
62
+ end
63
+ end
64
+
50
65
  def test_default_model_class
51
66
  cls = Class.new(RailsOps::Operation::Model) do
52
67
  model do
@@ -64,4 +79,13 @@ class RailsOps::Operation::ModelTest < ActiveSupport::TestCase
64
79
  end
65
80
  end
66
81
  end
82
+
83
+ def test_lazy_model
84
+ cls = Class.new(RailsOps::Operation::Model::Create) do
85
+ lazy_model 'Group'
86
+ end
87
+
88
+ assert_not cls.model.class < Group
89
+ assert cls.new.model.class < Group
90
+ end
67
91
  end
@@ -40,6 +40,16 @@ class RailsOps::OperationTest < ActiveSupport::TestCase
40
40
  assert BASIC_OP.new.run!.done
41
41
  end
42
42
 
43
+ def test_run_without_perform
44
+ cls = Class.new(RailsOps::Operation)
45
+ assert_nothing_raised do
46
+ cls.new
47
+ end
48
+ assert_raises NotImplementedError do
49
+ cls.run!
50
+ end
51
+ end
52
+
43
53
  def test_non_validation_error
44
54
  assert_raises_with_message RuntimeError, 'Standard exception' do
45
55
  BASIC_OP.run(exception: 'Standard exception')
@@ -146,6 +156,17 @@ class RailsOps::OperationTest < ActiveSupport::TestCase
146
156
  assert op.performed?
147
157
  end
148
158
 
159
+ def test_check_performed
160
+ op = BASIC_OP.new
161
+ assert_raises_with_message RuntimeError, 'Operation has not yet been performed.' do
162
+ op.check_performed!
163
+ end
164
+ op.run!
165
+ assert_nothing_raised do
166
+ op.check_performed!
167
+ end
168
+ end
169
+
149
170
  def test_inspect
150
171
  assert_equal 'RailsOps::OperationTest::BASIC_OP ({"foo"=>:bar})',
151
172
  BASIC_OP.new(foo: :bar).inspect
@@ -155,4 +176,104 @@ class RailsOps::OperationTest < ActiveSupport::TestCase
155
176
  assert_equal 'RailsOps::OperationTest::BASIC_OP ({1=>2})',
156
177
  BASIC_OP.new(1 => 2).inspect
157
178
  end
179
+
180
+ def test_with_rollback_on_exception
181
+ op = Class.new(RailsOps::Operation) do
182
+ def perform
183
+ with_rollback_on_exception do
184
+ fail 'Rollback please'
185
+ end
186
+ end
187
+ end.new
188
+ assert_raises RailsOps::Exceptions::RollbackRequired do
189
+ op.run
190
+ end
191
+ end
192
+
193
+ def test_op_with_schema3(use_default: false)
194
+ op = Class.new(RailsOps::Operation) do
195
+ schema_block = proc do
196
+ int! :id
197
+ hsh! :hash do
198
+ int? :number
199
+ int! :required_number
200
+ end
201
+ end
202
+ if use_default
203
+ schema(&schema_block)
204
+ else
205
+ schema3(&schema_block)
206
+ end
207
+ end
208
+
209
+ assert_nothing_raised do
210
+ op.new(id: 1, hash: { required_number: 1 })
211
+ end
212
+ assert_raises Schemacop::Exceptions::ValidationError do
213
+ op.new(id: 1, hash: {})
214
+ end
215
+ end
216
+
217
+ def test_op_with_schema2(use_default: false)
218
+ op = Class.new(RailsOps::Operation) do
219
+ schema_block = proc do
220
+ req :id, :integer
221
+ req :hash, :hash do
222
+ opt :number, :integer
223
+ req :required_number, :integer
224
+ end
225
+ end
226
+
227
+ if use_default
228
+ schema(&schema_block)
229
+ else
230
+ schema2(&schema_block)
231
+ end
232
+ end
233
+
234
+ assert_nothing_raised do
235
+ op.new(id: 1, hash: { required_number: 1 })
236
+ end
237
+ assert_raises Schemacop::Exceptions::ValidationError do
238
+ op.new(id: 1, hash: {})
239
+ end
240
+ end
241
+
242
+ def test_op_with_schema_default
243
+ RailsOps.config.default_schemacop_version = 3
244
+ test_op_with_schema3(use_default: true)
245
+
246
+ RailsOps.config.default_schemacop_version = 2
247
+ test_op_with_schema2(use_default: true)
248
+
249
+ RailsOps.config.default_schemacop_version = -50
250
+ assert_raises_with_message RuntimeError, 'Schemacop schema versions supported are 2 and 3.' do
251
+ test_op_with_schema3(use_default: true)
252
+ end
253
+ RailsOps.config.default_schemacop_version = 3
254
+ end
255
+
256
+ def test_require_context
257
+ op = Class.new(RailsOps::Operation) do
258
+ require_context :user, :session
259
+ end
260
+
261
+ ctx = RailsOps::Context.new(user: Class.new, session: Class.new)
262
+ assert_raises_with_message RailsOps::Exceptions::MissingContextAttribute, 'This operation requires the context attribute :user to be present.' do
263
+ op.new
264
+ end
265
+ assert_nothing_raised do
266
+ op.new(ctx, foo: :bar)
267
+ end
268
+ end
269
+
270
+ def test_run_through_context
271
+ op = Class.new(RailsOps::Operation) do
272
+ def perform; end
273
+ end
274
+ ctx = RailsOps::Context.new(user: Class.new, session: Class.new)
275
+ assert_nothing_raised do
276
+ ctx.run! op, foo: :bar
277
+ end
278
+ end
158
279
  end
@@ -0,0 +1,11 @@
1
+ class RailsOps::ProfilerTest < ActiveSupport::TestCase
2
+ include TestHelper
3
+
4
+ def test_time
5
+ assert_output(/Test - 1\d\.\dms elapsed./) do
6
+ RailsOps::Profiler.time 'Test' do
7
+ sleep 0.010
8
+ end
9
+ end
10
+ end
11
+ end
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.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sitrox
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-27 00:00:00.000000000 Z
11
+ date: 2023-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: active_type
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -301,9 +315,11 @@ files:
301
315
  - test/dummy/app/channels/application_cable/connection.rb
302
316
  - test/dummy/app/controllers/application_controller.rb
303
317
  - test/dummy/app/controllers/concerns/.keep
318
+ - test/dummy/app/controllers/group_controller.rb
304
319
  - test/dummy/app/helpers/application_helper.rb
305
320
  - test/dummy/app/jobs/application_job.rb
306
321
  - test/dummy/app/mailers/application_mailer.rb
322
+ - test/dummy/app/models/ability.rb
307
323
  - test/dummy/app/models/animal.rb
308
324
  - test/dummy/app/models/application_record.rb
309
325
  - test/dummy/app/models/bird.rb
@@ -336,6 +352,7 @@ files:
336
352
  - test/dummy/config/environments/development.rb
337
353
  - test/dummy/config/environments/production.rb
338
354
  - test/dummy/config/environments/test.rb
355
+ - test/dummy/config/hookup.rb
339
356
  - test/dummy/config/initializers/application_controller_renderer.rb
340
357
  - test/dummy/config/initializers/assets.rb
341
358
  - test/dummy/config/initializers/backtrace_silencers.rb
@@ -363,17 +380,22 @@ files:
363
380
  - test/dummy/tmp/.keep
364
381
  - test/test_helper.rb
365
382
  - test/unit/rails_ops/generators/operation_generator_test.rb
383
+ - test/unit/rails_ops/hookup_test.rb
384
+ - test/unit/rails_ops/mixins/controller_test.rb
366
385
  - test/unit/rails_ops/mixins/model/deep_nesting_test.rb
386
+ - test/unit/rails_ops/mixins/model/marshalling_test.rb
367
387
  - test/unit/rails_ops/mixins/param_authorization_test.rb
368
388
  - test/unit/rails_ops/mixins/policies_test.rb
389
+ - test/unit/rails_ops/operation/auth_test.rb
369
390
  - test/unit/rails_ops/operation/model/create_test.rb
391
+ - test/unit/rails_ops/operation/model/destroy_test.rb
370
392
  - test/unit/rails_ops/operation/model/load_test.rb
371
393
  - test/unit/rails_ops/operation/model/sti_test.rb
372
394
  - test/unit/rails_ops/operation/model/update_test.rb
373
395
  - test/unit/rails_ops/operation/model_test.rb
374
- - test/unit/rails_ops/operation/update_auth_test.rb
375
396
  - test/unit/rails_ops/operation/update_lazy_auth_test.rb
376
397
  - test/unit/rails_ops/operation_test.rb
398
+ - test/unit/rails_ops/profiler_test.rb
377
399
  homepage:
378
400
  licenses: []
379
401
  metadata: {}
@@ -392,7 +414,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
392
414
  - !ruby/object:Gem::Version
393
415
  version: '0'
394
416
  requirements: []
395
- rubygems_version: 3.4.6
417
+ rubygems_version: 3.4.10
396
418
  signing_key:
397
419
  specification_version: 4
398
420
  summary: An operations service layer for rails projects.
@@ -410,9 +432,11 @@ test_files:
410
432
  - test/dummy/app/channels/application_cable/connection.rb
411
433
  - test/dummy/app/controllers/application_controller.rb
412
434
  - test/dummy/app/controllers/concerns/.keep
435
+ - test/dummy/app/controllers/group_controller.rb
413
436
  - test/dummy/app/helpers/application_helper.rb
414
437
  - test/dummy/app/jobs/application_job.rb
415
438
  - test/dummy/app/mailers/application_mailer.rb
439
+ - test/dummy/app/models/ability.rb
416
440
  - test/dummy/app/models/animal.rb
417
441
  - test/dummy/app/models/application_record.rb
418
442
  - test/dummy/app/models/bird.rb
@@ -445,6 +469,7 @@ test_files:
445
469
  - test/dummy/config/environments/development.rb
446
470
  - test/dummy/config/environments/production.rb
447
471
  - test/dummy/config/environments/test.rb
472
+ - test/dummy/config/hookup.rb
448
473
  - test/dummy/config/initializers/application_controller_renderer.rb
449
474
  - test/dummy/config/initializers/assets.rb
450
475
  - test/dummy/config/initializers/backtrace_silencers.rb
@@ -472,14 +497,19 @@ test_files:
472
497
  - test/dummy/tmp/.keep
473
498
  - test/test_helper.rb
474
499
  - test/unit/rails_ops/generators/operation_generator_test.rb
500
+ - test/unit/rails_ops/hookup_test.rb
501
+ - test/unit/rails_ops/mixins/controller_test.rb
475
502
  - test/unit/rails_ops/mixins/model/deep_nesting_test.rb
503
+ - test/unit/rails_ops/mixins/model/marshalling_test.rb
476
504
  - test/unit/rails_ops/mixins/param_authorization_test.rb
477
505
  - test/unit/rails_ops/mixins/policies_test.rb
506
+ - test/unit/rails_ops/operation/auth_test.rb
478
507
  - test/unit/rails_ops/operation/model/create_test.rb
508
+ - test/unit/rails_ops/operation/model/destroy_test.rb
479
509
  - test/unit/rails_ops/operation/model/load_test.rb
480
510
  - test/unit/rails_ops/operation/model/sti_test.rb
481
511
  - test/unit/rails_ops/operation/model/update_test.rb
482
512
  - test/unit/rails_ops/operation/model_test.rb
483
- - test/unit/rails_ops/operation/update_auth_test.rb
484
513
  - test/unit/rails_ops/operation/update_lazy_auth_test.rb
485
514
  - test/unit/rails_ops/operation_test.rb
515
+ - test/unit/rails_ops/profiler_test.rb
@@ -1,64 +0,0 @@
1
- require 'test_helper'
2
- require 'rails_ops/authorization_backend/can_can_can'
3
- require 'cancancan'
4
-
5
- class RailsOps::Operation::UpdateLazyAuthTest < ActiveSupport::TestCase
6
- include TestHelper
7
-
8
- BASIC_OP = Class.new(RailsOps::Operation::Model::Update) do
9
- model ::Group
10
-
11
- model_authorization_action :update
12
-
13
- def perform
14
- fail osparams.exception if osparams.exception
15
- @done = true
16
- end
17
- end
18
-
19
- ABILITY = Class.new do
20
- include CanCan::Ability
21
-
22
- def initialize(read: false, update: false)
23
- super()
24
-
25
- can :read, Group if read
26
- can :update, Group if update
27
- end
28
- end
29
-
30
- setup do
31
- Group.create!(id: 1, name: 'Group')
32
- RailsOps.config.authorization_backend = 'RailsOps::AuthorizationBackend::CanCanCan'
33
- end
34
-
35
- def test_unpermitted_read
36
- ctx = RailsOps::Context.new(ability: ABILITY.new(read: true))
37
- assert_raises CanCan::AccessDenied do
38
- BASIC_OP.new(ctx, id: 1)
39
- end
40
- end
41
-
42
- def test_permitted_read
43
- ctx = RailsOps::Context.new(ability: ABILITY.new(read: true))
44
- assert_nothing_raised do
45
- BASIC_OP.new(ctx, id: 1)
46
- end
47
- end
48
-
49
- def test_unpermitted_update
50
- ctx = RailsOps::Context.new(ability: ABILITY.new(read: true))
51
- op = BASIC_OP.new(ctx, id: 1)
52
- assert_raises CanCan::AccessDenied do
53
- op.run!
54
- end
55
- end
56
-
57
- def test_permitted_update
58
- ctx = RailsOps::Context.new(ability: ABILITY.new(read: true, update: true))
59
- op = BASIC_OP.new(ctx, id: 1)
60
- assert_nothing_raised do
61
- op.run!
62
- end
63
- end
64
- end