Ruby on rails 如何在ruby中干燥一系列只差一行代码的函数?

Ruby on rails 如何在ruby中干燥一系列只差一行代码的函数?,ruby-on-rails,ruby,dry,Ruby On Rails,Ruby,Dry,我在ROR应用程序中有一个用户模型,它有多种类似的方法 #getClient() returns an object that knows how to find certain info for a date #processHeaders() is a function that processes output and updates some values in the database #refreshToken() is function that is called when an

我在ROR应用程序中有一个用户模型,它有多种类似的方法

#getClient() returns an object that knows how to find certain info for a date
#processHeaders() is a function that processes output and updates some values in the database
#refreshToken() is function that is called when an error occurs when requesting data from the object returned by getClient()


  def transactions_on_date(date)
    if blocked?
      # do something
    else
      begin
        output = getClient().transactions(date)
        processHeaders(output)
        return output
      rescue UnauthorizedError => ex
        refresh_token()
        output = getClient().transactions(date)
        process_fitbit_rate_headers(output)
        return output
      end
    end
  end

  def events_on_date(date)
    if blocked?
      # do something
    else
      begin
        output = getClient().events(date)
        processHeaders(output)
        return output
      rescue UnauthorizedError => ex
        refresh_token()
        output = getClient().events(date)
        processHeaders(output)
        return output
      end
    end
  end
我的用户类中有几个看起来完全相同的函数。这些函数之间唯一的区别是行
output=getClient().something(date)
。是否有一种方法可以使此代码看起来更干净,这样就不会有重复的函数列表。

是的,您可以使用:
getClient().send(:method\u name,date)

顺便说一句,
getClient
不是正确的Ruby方法名。它应该是
getClient

是的,您可以使用:
getClient().send(:方法、名称、日期)


顺便说一句,
getClient
不是正确的Ruby方法名。它应该是
get\u client

答案通常是传递一个块并按功能方式执行:

def handle_blocking(date)
  if blocked?
   # do something
  else
    begin
      output = yield(date)
      processHeaders(output)

      output
    rescue UnauthorizedError => ex
      refresh_token
      output = yield(date)
      process_fitbit_rate_headers(output)

      output
    end
  end
end
那么你这样称呼它:

handle_blocking(date) do |date|
  getClient.something(date)
end
这允许大量定制。
yield
调用执行您提供的代码块,并将
date
参数传递给它


使代码干涸的过程通常包括寻找模式,并将它们浓缩成这样有用的方法。使用功能性方法可以使事情保持干净。

答案通常是传递一个块并以功能性的方式执行:

def handle_blocking(date)
  if blocked?
   # do something
  else
    begin
      output = yield(date)
      processHeaders(output)

      output
    rescue UnauthorizedError => ex
      refresh_token
      output = yield(date)
      process_fitbit_rate_headers(output)

      output
    end
  end
end
那么你这样称呼它:

handle_blocking(date) do |date|
  getClient.something(date)
end
这允许大量定制。
yield
调用执行您提供的代码块,并将
date
参数传递给它


使代码干涸的过程通常包括寻找模式,并将它们浓缩成这样有用的方法。使用功能性方法可以保持清洁。

两种答案的组合如何:

class User

  def method_missing sym, *args
    m_name = sym.to_s
    if m_name.end_with? '_on_date'
      prop = m_name.split('_').first.to_sym
      handle_blocking(args.first) { getClient().send(prop, args.first) }
    else
      super(sym, *args)
    end
  end

  def respond_to? sym, private=false
    m_name.end_with?('_on_date') || super(sym, private)
  end

  def handle_blocking date
    # see other answer
  end

end

然后您可以调用“交易日期”、“事件日期”、“foo日期”,这样就可以了。

两种答案的组合如何:

class User

  def method_missing sym, *args
    m_name = sym.to_s
    if m_name.end_with? '_on_date'
      prop = m_name.split('_').first.to_sym
      handle_blocking(args.first) { getClient().send(prop, args.first) }
    else
      super(sym, *args)
    end
  end

  def respond_to? sym, private=false
    m_name.end_with?('_on_date') || super(sym, private)
  end

  def handle_blocking date
    # see other answer
  end

end

然后您可以调用“transaction\u on\u date”、“events\u on\u date”、“foo\u on\u date”,这样就可以了。

值得注意的是,Ruby style强烈建议在
get\u client
上使用类似于
getClient
的名称,并且在未传递任何参数时省略括号。此外,对于简单的“getter”方法,完全省略
get
。方法
client
client=
get\u-client
set\u-client
更可取。值得注意的是,Ruby风格强烈建议在
getClient
上使用
get\u-client
等名称,并且在没有传递参数时省略括号。此外,对于简单的“getter”方法,完全省略
get
。方法>代码>客户端< /C> >代码>客户机=/COD>非常适合于<代码> GETXClient 和 StIsClient 。我会考虑在参数中指定<代码>和块<代码>,使用<代码>如果BuffiGror? @ MAX,只要您想通过,就必须在参数中指定<代码>和块< /代码>。通过另一种方法。在参数中声明它会带来大量开销,因此养成这样做的习惯是不好的。由于这取决于是否有块,因此如果调用不正确,它将崩溃<代码> BuffiRead?如果有一个默认的行为,那将是有用的。我会考虑在参数中指定<代码>和块<代码>,并且使用<代码>如果BuffiGuield: @ MAX,只要您想把它传递给另一个方法,就只需要在参数中指定<代码>和块< /代码>。在参数中声明它会带来大量开销,因此养成这样做的习惯是不好的。由于这取决于是否有块,因此如果调用不正确,它将崩溃<代码>给定的块?如果有默认行为的情况,则会很有用。