【问题标题】:Outputing value of TrueClass / FalseClass to integer or string/将 TrueClass / FalseClass 的值输出为整数或字符串 /
【发布时间】:2010-03-26 16:12:23
【问题描述】:

我试图弄清楚是否有一种简单的方法可以在 TrueClass/FalseClass 中添加 to_i 方法。

这是一个难题: 我的 Rails 应用程序中有一个布尔字段 - 显然在 mysql 中存储为 Tinyint。但是 - 我需要根据 mysql 中的数据生成 xml 并将其发送给客户 - SOAP 服务要求相关字段具有 0 或 1 作为该字段的值。因此,在生成 xml 时,我需要将我的 False 转换为 0,将我的 True 转换为 1(这就是它们在数据库中的存储方式)。由于 True & False 缺少 to_i 方法,我可以编写一些 if 语句,根据真/假状态生成 1 或 0。但是,我有大约 10 个这样的指标,并且为每个指标创建 if/else 并不是很干燥。那你建议我做什么?

或者我可以在 True / False 类中添加一个 to_i 方法。但我不确定我应该在我的 rails 应用程序中将它的范围放在哪里?就在这个特定的模型内部还是其他地方?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    您可以按照您的建议创建一个诸如lib/boolean_ints.rb 之类的文件并将to_i 方法修改为TrueClassFalseClass。然后,在你需要使用to_i方法的模型或控制器中,你可以放

    require 'boolean_ints'
    

    在顶部,它们可以使用。

    【讨论】:

    • @mipadi - 与此相关,是否有关于如何在 lib 中构造/命名/布局事物的特定约定?
    • 我不知道lib 本身的约定。我通常只是尝试尽可能清晰简洁地命名事物。
    【解决方案2】:

    humanizeto_i 扩展TrueClass 和FalseClass。

    这出现在我的大多数项目中,所以我使用了一个初始化器(如果您使用的是 Rails),它将这两个有用的方法添加到每个类中,如下所示:

    config/initializers/true_and_false.rb

    class TrueClass
      def humanize
        'Yes'
      end
    
      def to_i
        1
      end
    end
    
    class FalseClass
      def humanize
        'No'
      end
    
      def to_i
        0
      end
    end
    

    然后它使 “人类消费”“机器消费” 的渲染true 变得非常容易:

    > true.humanize     #=> Yes
    > true.to_i         #=> 1
    
    > false.humanize    #=> No
    > false.to_i        #=> 0
    

    【讨论】:

      【解决方案3】:

      您可以在您的应用程序中,在该特定模型附近对 TrueClassFalseClass 进行猴子补丁:任何在 true 和 false 上的 to_i 实现都可能是相同的。

      irb(main):004:0> true.to_i
      NoMethodError: undefined method `to_i' for true:TrueClass
              from (irb):4
      irb(main):005:0> class TrueClass
      irb(main):006:1>  def to_i
      irb(main):007:2>   1
      irb(main):008:2>  end
      irb(main):009:1> end
      => nil
      irb(main):010:0>
      irb(main):011:0* true.to_i
      => 1
      

      但是为了避免猴子补丁,你有什么理由不能只使用三元运算符吗?如果这对您来说还不够 DRY,请将其包装在一个方法中。

      irb(main):012:0> true ? 1 : 0
      => 1
      irb(main):013:0> false ? 1 : 0
      => 0
      

      当然,这也适用于非布尔变量:

      irb(main):019:0* 1234 ? 1 : 0
      => 1
      irb(main):020:0> nil ? 1 : 0
      => 0
      

      【讨论】:

      • @Mark - 我已经这样做了 - 但我问是否有办法做到这一点“没有将 to_i 方法添加到 TrueClass/FalseClass。”或使用 if else 语句 - 这是三元运算符的真正含义,我试图看看是否有另一种我不知道的方法来做到这一点。然而,这对我来说没有意义 - False.to_s 工作并产生“假”字符串,但 to_i 没有在核心类中实现。感谢您的回复。
      【解决方案4】:

      更新:此“解决方案”很危险,不应使用!

      你也可以试试:

      value.object_id / 2
      

      我不确定这在不同实现中的效果如何。

      为了摆脱必须重复 10 次的重复,我仍然建议创建一个方法:

      def boolean_to_i value
        value.object_id / 2
      end
      

      不过,确实不需要猴子补丁。

      【讨论】:

      • 刚刚对此进行了测试,它适用于 MRI 1.8 和 1.9 以及 JRuby,但不适用于 Rubinius(其中 true 和 false 的对象 ID 分别为 19 和 10)。
      • 这绝对是错误的,甚至是危险的。在 Ruby 2.0 中,TrueClass.object_id 定义为 20。
      • 我同意。它过于依赖于实现细节。
      【解决方案5】:

      你可以使用:

      5 - bool.to_s.length
      

      这将始终有效,因为 true.to_s"true"false.to_s"false""true".length 是 4,而 "false".length 是 5。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-20
        • 2017-06-11
        • 1970-01-01
        • 1970-01-01
        • 2015-10-22
        • 1970-01-01
        相关资源
        最近更新 更多