Let's assume I've got below monad class:
require 'dry-monads'
require 'dry/monads/all'
module Test
class MonadsClass
include Dry::Monads
def initialize(signees)
@signees = signees
end
def call
Success(signees)
.bind(method(:fetch_template))
.bind(method(:envelope_from_template))
end
attr_reader :signees
private
def fetch_template(signees)
key = "template_#{signees.size}".to_sym
template_id = Rails.application.credentials.some_api.fetch(key)
Success(template_id: template_id, key: key)
end
def envelope_from_template(template_id:, key:)
response = some_api.copy_from_template(template_id, key)
response.failure? ? Failure(response.failure) : Success(response.value!)
end
end
end
Why in this combination I'm getting strange error of:
Failure/Error:
def envelope_from_template(template_id:, key:)
response = some_api.copy_from_template(template_id)
response.failure? ? Failure(response.failure) : Success(response.value!)
end
ArgumentError:
wrong number of arguments (given 1, expected 0; required keywords: template_id, key)
CodePudding user response:
I think the issue is that you are expecting it to pass kwargs (keyword arguments) but it is passing a Hash
. Ruby 2.7 deprecated "automatic conversion" of Hash to kwargs and ruby 3.0 removed it completely. You can read more about the separation of positional and keyword arguments Here
In other words you are expecting it to call
envelope_from_template(template_id: 123, key: 'abc')
but you are actually calling
envelope_from_template({template_id: 123, key: 'abc'})
Instead you have a couple options which should work:
- Option 1 (call
bind
with a block)
def call
Success(signees)
.bind(method(:fetch_template))
.bind {|h| envelope_from_template(**h) }
end
- Option 2 - Change the method signature and then use
Hash
access methods in the body
def envelope_from_template(params)
response = some_api.copy_from_template(params.values_at(:template_id, :key))
response.failure? ? Failure(response.failure) : Success(response.value!)
end