【问题标题】:Ruby define_method with parameter based on block具有基于块的参数的 Ruby 定义方法
【发布时间】:2014-11-13 19:12:11
【问题描述】:

我刚刚想通了,我将我的方法更新为下面并将 args 传递给块执行:

def self.element(element_name, options = {}, &block)
    define_method "#{element_name}" do |arg=nil|
        find self.instance_exec(*arg, &block), options
    end     
end

BINGOOOO!!!

我的问题如下 -

我有一个采用 3 个参数(method_name、options 和 &block)的方法,这就是我将其组合在一起的方式:

def self.element(element_name, options = {}, &block)
    define_method "#{element_name}" do
        find self.instance_exec(&block), options
    end     
end

这就是我调用方法元素的方式:

element(:method_name, visible: 5)  { "#css path to my element" }

现在我可以在任何我希望的地方使用它并执行任何我希望的操作:

method_name.click
...

到目前为止,这一直对我有用,但是当我遇到像下面的示例这样的动态元素的情况时,我需要重复元素查找(有时会重复 20 多次):

{ "#csspath1" }
{ "#csspath2" }
{ "#csspath3" }
{ "#csspath4" }
...

我正在通过块中的元素路径来处理这种情况,但还没有到达那里,我想做的是参数化可重复的数字:

{ |arg| "#csspath#{arg}" }

并且以某种方式让使用 define_method 创建的方法在我的块中传递参数,所以该方法看起来像:

method(1).click
method(2).click
method(3).click
method(4).click

我还没有到那里,欢迎任何想法....

【问题讨论】:

    标签: ruby selenium capybara


    【解决方案1】:

    这是你想要做的吗? :

    def element(element_name, options = {})
      define_method "#{element_name}" do |arg = nil|
        find yield(arg), options
      end     
    end
    

    现在定义方法:

    element(:method_name, visible: 5) {|num| "#csspath#{num}" }
    

    这里yield 语句使用默认参数nil 执行块,当您调用时将其转换为字符串时,它将是''(空字符串):

    method.click #=> will use "#csspath" for find
    

    如果像这样传递,它将评估和使用参数:

    method(1).click #=> will use "#csspath1" instead of "#csspath" for find
    

    【讨论】:

    • 太棒了,这对我也有用,而且看起来更干净!知道这两种解决方案有什么区别吗?产生参数或传递块?传递一个块只是我想要完成的开销,仅此而已?
    • 没什么,除了instance_exec 总是期望在参数中传递一个块,但是,如果你不传递块,即使yield 也将不起作用。但是,您可以通过说 if block_given? 来阻止这种行为,如果必须阻止或者只是救援而不做任何事情,则会引发错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多