简体   繁体   English

Rails 将多个参数传递给 dry-monad

[英]Rails pass more than one parameter into dry-monads

Let's assume I've got below monad class:假设我有下面的 monad 类:

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)

I think the issue is that you are expecting it to pass kwargs (keyword arguments) but it is passing a Hash .我认为问题在于您期望它传递 kwargs (关键字参数)但它传递的是Hash Ruby 2.7 deprecated "automatic conversion" of Hash to kwargs and ruby 3.0 removed it completely. Ruby 2.7 弃用了 Hash 到 kwargs 的“自动转换”,而 ruby 3.0 完全删除了它。 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)选项 1(调用块bind
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选项 2 - 更改方法签名,然后在正文中使用Hash访问方法
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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM