5. 语法 (Syntax)

  • 永远不要用 for,除非有非常特殊的理由。
  • 绝大部分情况都应该用 eachfor 是用 each 实现的(所以你间接加了一层),但区别是 - for 不会有新 scope (不像 each) 里面定义的变量外面可见。
    arr = [1, 2, 3]
      #  错误
      for elem in arr do
        puts elem
      end
      #  正确
      arr.each { |elem| puts elem }
    
  • 单行的情况下, 尽量用 {...} 而不是 do...end。多行的情况下避免用 {...}。对于 “control flow” 和 “方法定义”(举例: 在 Rakefiles 和某些 DSLs 里) 总是用 do...end。方法连用(chaining)时 避免使用 do...end
    names = ["Bozhidar", "Steve", "Sarah"]
      #  正确
      names.each { |name| puts name }
      #  错误
      names.each do |name| puts name end
      #  正确
      names.each do |name|
        puts name
        puts 'yay!'
      end
      #  错误
      names.each { |name|
        puts name
        puts 'yay!'
      }
      #  正确
      names.select { |name| name.start_with?("S") }.map { |name| name.upcase }
      #  错误
      names.select do |name|
        name.start_with?("S")
      end.map { |name| name.upcase }
    
  • 有些人会说多行连用(chaining) 用 {...} 符号 其实也没那么难看, 但他们应该问问自己这代码真的可读吗, 而且 block 里的内容是否可以抽出来弄好看些。
  • 尽可能用短的自赋值操作符 (self assignment operators)。
    #  错误
      x = x + y
      x = x * y
      x = x**y
      x = x / y
      x = x || y
      x = x && y
      #  正确
      x += y
      x *= y
      x **= y
      x /= y
      x ||= y
      x &&= y
    
  • 避免用分号。 除非是单行 class 定义的情况下。 而且当使用分号时, 分号前面不应该有空格。
  • :: 的使用场景是引用常量,(比如classes 和 modules 里的常量) 以及调用构造函数 (比如 Array() 或者 Nokogiri::HTML() )。普通方法调用就不要使用 :: 了。
    #  错误
      SomeClass::some_method
      some_object::some_method
      #  正确
      SomeClass.some_method
      some_object.some_method
      SomeModule::SomeClass::SOME_CONST
      SomeModule::SomeClass()
    
  • 尽量避免用 return
  •   #  错误
      def some_method(some_arr)
        return some_arr.size
      end
      #  正确
      def some_method(some_arr)
        some_arr.size
      end
    
  • 条件语句里不要用返回值
      #  错误 - shows intended use of assignment
      if (v = array.grep(/foo/))
        ...
      end
      #  错误
      if v = array.grep(/foo/)
        ...
      end
      #  正确
      v = array.grep(/foo/)
      if v
        ...
      end
    
  • 请随意用 ||= 来初始化变量。
      #  把 name 赋值为 Bozhidar, 仅当 name 是 nil 或者 false 时
      name ||= 'Bozhidar'
    
  • 不要用 ||= 来初始化布尔变量。(想象下如果值刚好是 false 会咋样)
      #  错误 - would set enabled to true even if it was false
      enabled ||= true
      #  正确
      enabled = true if enabled.nil?
    
  • 当调用 lambdas 时,明确使用 .call
      #  错误
      lambda.(x, y)
      #  正确
      lambda.call(x, y)
    
  • 避免使用 Perl 风格的特殊变量名( 比如 $0-9, $, 等等. ). 因为看起来蛮神秘的. 建议只在单行里使用。建议用长名字, 比如 $PROGRAM_NAME
  • 当一个方法块只需要 1 个参数,而且方法体也只是读一个属性, 或者无参数的调用一样方法,这种情况下用 &:
      #  错误
      bluths.map { |bluth| bluth.occupation }
      bluths.select { |bluth| bluth.blue_self? }
      #  正确
      bluths.map(&:occupation)
      bluths.select(&:blue_self?)
    
  • 当调用当前实例的某个方法时, 尽量用 some_method 而不是 self.some_method
      #  错误
      def end_date
        self.start_date + self.nights
      end
      #  正确
      def end_date
        start_date + nights
      end
    
  • 在下面 3 种常见情况里, 需要用, 而且应该用self.
    • 当定义一个类方法时: def self.some_method.
    • 当调用一个赋值方法 (assignment method) 时,左手边 应该用 self, 比如当 self 是 ActiveRecord 模型然后你需要赋值一个属性: self.guest = user
    • 指向 (Referencing) 当前实例的类: self.class