【问题标题】:How do I refactor these conditionals in my ruby class?如何在我的 ruby​​ 类中重构这些条件?
【发布时间】:2011-11-27 07:55:47
【问题描述】:

这是我的方法。它检查文件是否可用。我怎么把它弄干?

@@filepath = nil

def self.file_usable?
  return false unless @@filepath
  return false unless File.exists?(@@filepath)
  return false unless File.readable?(@@filepath)
  return false unless File.writable?(@@filepath)
  return true
end

我应该使用某种循环吗?

【问题讨论】:

  • 你有什么问题?这是一个非常易读的逻辑表示,一目了然。
  • @mu: 你真的更喜欢这个命令式返回链而不是简单的表达式a && b && c && d?。抱歉,我没听懂……
  • @tokland:我愿意,它比单行扫描要容易得多。您可以通过适当应用换行符的单个表达式来实现相同的可读性,但 Ruby 让您使用反斜杠或将逻辑运算符放在行尾有些模糊的地方。
  • 伙计们,我认为我最初粘贴的内容足够可读,但我是一个 ruby​​ 新手,试图以 DRY 的方式了解 ruby​​ 真正可以做什么。所以@tokland 的 sn-p 真的教会了我很多关于语言的知识
  • 4x "return false unless..." -- 似乎它可以从 DRYing 中受益:-)

标签: ruby refactoring


【解决方案1】:
def self.file_usable?
  @@filepath and File.exists?(@@filepath) and File.readable?(@@filepath) and File.writable?(@@filepath)
end

【讨论】:

  • 这很有趣,但我注意到所有这些方法都作用于同一个变量。难道没有办法重构它吗?
  • 如果 OP 对 @@filepath 没问题(检测到 false/nil),为什么!@@filepath.nil? 过于具体?
  • @megas:请注意,您之前的选择有一个意义,即它始终返回一个布尔值(预期的响应是 xyz? 方法)。一个严格的代码是!!@@filepath,虽然我不会真的打扰(而且这个双!!@@看起来很有趣:-))
  • 你又是对的,它可能返回 nil。在 Ruby 中,只有两个值可以是负数 - nil 和 false,所以它不会造成麻烦,对吗?
  • 您可以删除 File.exists?(@@filepath) 部分。
【解决方案2】:

我不会这样做,但是既然您要求“仅重构所有这些方法对同一个变量的操作”...

def self.file_usable?
  @@filepath && [:exists?, :readable?, :writable?].all? { |m| File.send(m, @@filepath) }
end

如果您需要以编程方式决定必须检查哪些方法,这可能很有用。如果这是一个孤立的功能,我会写:

def self.file_usable?
  f = @@filepath
  f && File.exists?(f) && File.readable?(f) && File.writable?(f)
end

【讨论】:

  • 哇!我得看看这是否有效。这看起来像我要找的东西
  • 您实际上可以通过以下方式取出第一个@@filepath &&: [:exists?, :readable?, :writable?].all? { |米| File.send(m, @@filepath.to_s) } 因为 nil.to_s 是一个空字符串。但是是的,我同意,不要那样做。
【解决方案3】:

您可以使用File#stat 并检查mode 的值。

s = File.stat("testfile")
other_can_rwx = s.mode && 0007

【讨论】:

    【解决方案4】:

    当我主要关心可读性时,我经常使用这种技术:

    def self.file_usable?
      [@@filepath,
       File.exists?(@@filepath),
       File.readable?(@@filepath),
       File.writable?(@@filepath)].all?
    end
    

    但是请注意,这种方法有很大的不同,因为所有的表达式都会被计算。

    因为nil.some_method 从未被调用过,所以以下方法有效:

    nil and nil.some_method
    

    但是这会抛出异常,因为总是对所有内容进行评估:

    [nil, nil.some_method].all?
    

    【讨论】:

      【解决方案5】:

      这可能不是一个好主意,但理论上你可以这样做:

      def self.file_usable?
        File.writable? @@filepath rescue nil
      end
      

      【讨论】:

      • 像这样投反对票是阻止人们将来为您的问题提供答案的好方法。像这样的 Fwiw 救援肯定很臭,但可以让你度过难关。
      • 我可以看到总体上对这个答案投了反对票,但我确实说这是个坏主意,而且他似乎想要最短的解决方案。
      • 只是要明确一点:我没有投反对票。感谢您的贡献 pguardiario
      【解决方案6】:

      另一种变化:

      CHECK_METHODS = [:exists?, :readable?, :writable?] \
                        .map{ |m| File.method(m) } \
                        .unshift(lambda{ |x| x })
      
      
      def self.file_usable?
        CHECK_METHODS.all? { |m| m[@@filepath] }
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-31
        • 1970-01-01
        • 2021-09-20
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        相关资源
        最近更新 更多