reform: Problem with delegation in forms in 2.6.1 / disposable 0.6.0
Complete Description of Issue
I have this in a contract:
money_property :fixed_charge, currency: ->(form) { form.default_currency }
...
private
delegate :assignment, to: :model
delegate :default_currency, to: :assignment, allow_nil: true
It works fine with Reform 2.6.0, but with 2.6.1 I get the following error:
1) timesheets submission as a contractor submit a timesheet block with a note
Failure/Error: delegate :assignment, to: :model
ArgumentError:
wrong number of arguments (given 2, expected 1)
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/3.0.0/forwardable.rb:133:in `instance_delegate'
# ./app/concepts/assignments/contract/rate.rb:56:in `<class:Rate>'
# ./app/concepts/assignments/contract/rate.rb:2:in `<module:Contract>'
# ./app/concepts/assignments/contract/rate.rb:1:in `<main>'
# ./app/concepts/assignments/op/add_rate.rb:7:in `<class:Present>'
# ./app/concepts/assignments/op/add_rate.rb:3:in `<class:AddRate>'
# ./app/concepts/assignments/op/add_rate.rb:2:in `<module:Op>'
# ./app/concepts/assignments/op/add_rate.rb:1:in `<main>'
Line 56 is the delegation line, line 2 is the class definition, which is weird.
If I remove the delegation and do this instead then it works:
def assignment
model.assignment
end
def default_currency
assignment&.default_currency
end
However, those methods can no longer be private, which suggests to me that execution scope has changed?
money_property
is defined like this - not pasting the whole thing here - but you can see how the proc passed to currency is called.
module Contract
module Money
extend ActiveSupport::Concern
module ClassMethods
def money_property(name, currency: nil, **options)
...
define_method :"coerce_#{name}" do |value|
currency_val = currency.respond_to?(:call) ? currency.call(self) : currency
...
end
end
end
end
end
Has the self
that is passed to call
changed?
Steps to reproduce
Expected behavior
Should function as on 2.6.0
Actual behavior
Getting wrong number of arguments (given 2, expected 1)
on use of delegate
System configuration
Reform version: 2.6.1 Ruby version: 3.0.2
Full Backtrace of Exception (if any)
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/3.0.0/forwardable.rb:133:in `instance_delegate'
# ./app/concepts/assignments/contract/rate.rb:56:in `<class:Rate>'
# ./app/concepts/assignments/contract/rate.rb:2:in `<module:Contract>'
# ./app/concepts/assignments/contract/rate.rb:1:in `<main>'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/zeitwerk-2.5.1/lib/zeitwerk/kernel.rb:27:in `require'
# ./app/concepts/assignments/op/add_rate.rb:7:in `<class:Present>'
# ./app/concepts/assignments/op/add_rate.rb:3:in `<class:AddRate>'
# ./app/concepts/assignments/op/add_rate.rb:2:in `<module:Op>'
# ./app/concepts/assignments/op/add_rate.rb:1:in `<main>'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/zeitwerk-2.5.1/lib/zeitwerk/kernel.rb:27:in `require'
# ./spec/factories/rates.rb:41:in `block (3 levels) in <main>'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/attribute_assigner.rb:50:in `instance_exec'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/attribute_assigner.rb:50:in `build_class_instance'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/attribute_assigner.rb:13:in `object'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/evaluation.rb:13:in `object'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/strategy/create.rb:9:in `result'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/factory.rb:43:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/factory_runner.rb:29:in `block in run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/activesupport-6.1.4.1/lib/active_support/notifications.rb:205:in `instrument'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/factory_runner.rb:28:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/strategy_syntax_method_registrar.rb:28:in `block in define_singular_strategy_method'
# ./spec/factories/assignments.rb:169:in `block (4 levels) in <main>'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/callback.rb:13:in `instance_exec'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/callback.rb:13:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/callbacks_observer.rb:11:in `block in update'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/callbacks_observer.rb:10:in `each'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/callbacks_observer.rb:10:in `update'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/3.0.0/observer.rb:222:in `block in notify_observers'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/3.0.0/observer.rb:221:in `each'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/3.0.0/observer.rb:221:in `notify_observers'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/evaluation.rb:24:in `notify'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/strategy/create.rb:13:in `block in result'
# <internal:kernel>:90:in `tap'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/strategy/create.rb:9:in `result'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/factory.rb:43:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/factory_runner.rb:29:in `block in run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/activesupport-6.1.4.1/lib/active_support/notifications.rb:205:in `instrument'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/factory_runner.rb:28:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/factory_bot-6.2.0/lib/factory_bot/strategy_syntax_method_registrar.rb:28:in `block in define_singular_strategy_method'
# ./spec/concepts/timesheets/submissions/features/timesheets_spec.rb:20:in `block (3 levels) in <top (required)>'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:317:in `block (2 levels) in let'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:157:in `block (3 levels) in fetch_or_store'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:157:in `fetch'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:157:in `block (2 levels) in fetch_or_store'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-support-3.10.3/lib/rspec/support/reentrant_mutex.rb:23:in `synchronize'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:156:in `block in fetch_or_store'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:155:in `fetch'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:155:in `fetch_or_store'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:317:in `block in let'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:376:in `block in let!'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:455:in `instance_exec'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:455:in `instance_exec'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:365:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:529:in `block in run_owned_hooks_for'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:528:in `each'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:528:in `run_owned_hooks_for'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:615:in `block in run_example_hooks_for'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:614:in `reverse_each'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:614:in `run_example_hooks_for'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:484:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:502:in `run_before_example'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:261:in `block in run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:508:in `block in with_around_and_singleton_context_hooks'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:465:in `block in with_around_example_hooks'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:486:in `block in run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:626:in `block in run_around_example_hooks_for'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:350:in `call'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-rails-5.0.2/lib/rspec/rails/adapters.rb:75:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:455:in `instance_exec'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:455:in `instance_exec'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:390:in `execute_with'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:628:in `block (2 levels) in run_around_example_hooks_for'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:350:in `call'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:629:in `run_around_example_hooks_for'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:486:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:465:in `with_around_example_hooks'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:508:in `with_around_and_singleton_context_hooks'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:259:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:644:in `block in run_examples'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:640:in `map'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:640:in `run_examples'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:606:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:607:in `block in run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:607:in `map'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:607:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `block (3 levels) in run_specs'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `map'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `block (2 levels) in run_specs'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/configuration.rb:2067:in `with_suite_hooks'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:116:in `block in run_specs'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/reporter.rb:74:in `report'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:115:in `run_specs'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:89:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:71:in `run'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:45:in `invoke'
# /Users/samuelstickland/.gem/ruby/3.0.2/gems/rspec-core-3.10.1/exe/rspec:4:in `<top (required)>'
# /Users/samuelstickland/.gem/ruby/3.0.2/bin/rspec:25:in `load'
# /Users/samuelstickland/.gem/ruby/3.0.2/bin/rspec:25:in `<top (required)>'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/cli/exec.rb:58:in `load'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/cli/exec.rb:58:in `kernel_load'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/cli/exec.rb:23:in `run'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/cli.rb:478:in `exec'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/cli.rb:31:in `dispatch'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/cli.rb:25:in `start'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/gems/3.0.0/gems/bundler-2.2.30/exe/bundle:49:in `block in <top (required)>'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/site_ruby/3.0.0/bundler/friendly_errors.rb:103:in `with_friendly_errors'
# /Users/samuelstickland/.rubies/ruby-3.0.2/lib/ruby/gems/3.0.0/gems/bundler-2.2.30/exe/bundle:37:in `<top (required)>'
# /Users/samuelstickland/.rubies/ruby-3.0.2/bin/bundle:23:in `load'
# /Users/samuelstickland/.rubies/ruby-3.0.2/bin/bundle:23:in `<main>'
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 2
- Comments: 26 (17 by maintainers)
I blogged about this https://dev.to/trailblazer/dont-mix-forwardable-and-activesupportdelegate-5hmm
Here is the diff from my
Gemfile.lock
Thanks for the repo, @majksner! I was able to make it work, but it’s a weird error, I suspect ActiveSupport’s
delegate
to be the problem source.Here’s how I fixed it.
@apotonick
Here you go:
Code is a bit messy, but this was the quickest thing to do.
Let me know if you need anything else.