带有可选选项和&块参数的Ruby方法

时间:2016-07-27 13:53:54

标签: ruby methods parameters unary-operator

  1. 嘿那里

    是否可以将可选属性和块作为参数 方法调用?

    示例:我必须致电

    method(foo, foo: bar, -> { do_something }
    

    并尝试

    def method(foo, *bar, &block)
    end
    

    至于我的理解,块总是必须在最后位置?

    经过一番研究后,我发现了一元(?)*似乎是为了 阵列。自从我尝试传递Hash后,我将代码更改为

    def method(foo, bar={}, &block)
    end
    

    但这也不能解决问题。我猜是因为他不能 弄清楚栏的结束位置和块开始。

    有任何想法或建议吗?提前谢谢

    追加:只是为了好奇我为什么需要这个。我们有一个大json 架构运行并有一个小的DSL,从中构建json 模型明确。我们不想深入细节 实现exportable_scopes。

    class FooBar
      exportable_scope :some_scope, title: 'Some Scope', -> { rewhere archived: true }
    end
    

    在某些初始化程序中,应该会发生这种情况:

    def exportable_scope scope, attributes, &block
      scope scope block
      if attributes.any?
        attributes.each do |attribute|
          exportable_schema.scopes[scope] = attribute
        end
      else
        exportable_schema.scopes[scope] = {title: scope}
      end
    end
    

    所以这个工作正常,我只需要提示该方法 参数。

1 个答案:

答案 0 :(得分:5)

是的,有可能。

混合不同类型的参数时,必须按特定顺序将它们包含在方法定义中:

  1. 位置参数(必需和可选)以及单个splat参数,按任意顺序;
  2. 关键字参数(必填和可选),按任意顺序;
  3. 双splat参数;
  4. 阻止参数(前缀为&);
  5. 上述顺序有些灵活。我们可以定义一个方法并使用单个splat参数开始参数列表,然后使用几个可选的位置参数,依此类推。尽管Ruby允许这样做,但它通常是一种非常糟糕的做法,因为代码难以阅读,甚至更难调试。通常最好使用以下顺序:

    1. 所需的位置参数;
    2. 可选的位置参数(默认值);
    3. 单个splat参数;
    4. 关键字参数(必填和可选,其顺序无关);
    5. 双splat参数;
    6. 显式块参数(以&前缀)。
    7. 示例:

      def meditate cushion, meditation="kinhin", *room_items, time: , posture: "kekkafuza", **periods, &b
          puts "We are practicing #{meditation}, for #{time} minutes, in the #{posture} posture (ouch, my knees!)."
          puts "Room items: #{room_items}"
          puts "Periods: #{periods}"
          b.call # Run the proc received through the &b parameter
      end
      
      meditate("zafu", "zazen", "zabuton", "incense", time: 40, period1: "morning", period2: "afternoon" ) { puts "Hello from inside the block" }
      
      # Output:
      We are practicing zazen, for 40 minutes, in the kekkafuza posture (ouch, my knees!).
      Room items: ["zabuton", "incense"]
      Periods: {:period1=>"morning", :period2=>"afternoon"}
      Hello from inside the block
      

      请注意,在调用方法时,我们有:

      • 提供缓冲强制位置参数;
      • 覆盖冥想可选位置参数的默认值;
      • 通过* room_items参数传递了几个额外的位置参数(zabuton和熏香);
      • 提供时间强制关键字参数;
      • 省略了姿势可选关键字参数;
      • 通过**期间参数传递了几个额外的关键字参数(period1:" morning",period2:" afternoon");
      • 通过了阻止{puts" Hello来自区块内" }通过& b参数;

      请注意上述示例服务器仅用于说明混合不同类型参数的可能性。在实际代码中构建这样的方法将是一种不好的做法。如果一个方法需要那么多参数,那么最好将它分成更小的方法。如果将这么多数据传递给单个方法是绝对必要的,我们应该创建一个类以更有条理的方式存储数据,然后将该类的实例作为单个参数传递给该方法。 / p>