【问题标题】:Ruby on Rails: before_save fields to lowercaseRuby on Rails:before_save 字段为小写
【发布时间】:2014-07-14 09:52:54
【问题描述】:

我正在尝试将表单中的字段更改为小写,然后再将它们保存到数据库中。这是我的代码,但是数据库的输出仍然是大写的,为什么代码不起作用?

class Transaction < ActiveRecord::Base
   validates :name, presence: true
   validates :amount, presence: true, numericality: true
   before_save :downcase_fields

   def downcase_fields
      self.name.downcase
   end
end

【问题讨论】:

  • before_save { |transaction| transaction.name.downcase! }
  • 这是一个老问题,但我认为值得指出的是这个想法会产生意想不到的后果。如果您等待像name 这样的小写,您实际上无法获得您认为得到的唯一性约束。这使您的客户的事情变得复杂。您可能希望在唯一性验证器中将此与不区分大小写结合起来。

标签: ruby-on-rails ruby database sqlite activerecord


【解决方案1】:

downcase 返回字符串的副本,不修改字符串本身。请改用downcase!

def downcase_fields
  self.name.downcase!
end

更多详情请见documentation

【讨论】:

  • 如果我只想小写表单的一个值(而不是全部),这将如何工作。抱歉,RoR 新手
【解决方案2】:

您没有通过运行self.name.downcasename 设置为小写,因为#downcase 不会修改字符串,它会返回它。你应该使用 bang downcase 方法

self.name.downcase!

但是,我喜欢在模型中使用另一种方式:

before_save { name.downcase! }

【讨论】:

  • 更好的使用尝试像before_save { name.try(:downcase!) }
  • @AshishGaur 不需要Object#try,因为 OP 有一个存在验证集。
  • 我的错。我直接看到的是答案而不是问题。
【解决方案3】:

String#downcase 不会改变字符串,它只是返回该字符串的修改副本。正如其他人所说,您可以使用downcase! 方法。

def downcase_fields
  name.downcase!
end

但是,如果您想坚持使用downcase 方法,那么您可以执行以下操作:

def downcase_fields
  self.name = name.downcase
end

这会将 name 实例变量重新分配给对 name 的原始值调用小写的结果。

【讨论】:

    【解决方案4】:

    其他代码更少的简单示例:

    class Transaction < ActiveRecord::Base
       validates :name, presence: true
       validates :amount, presence: true, numericality: true
    
       before_save { self.name.downcase!}
    
    end
    

    希望这会有所帮助!

    【讨论】:

    • 这是最好的答案。
    • 冗余self你可以避免它before_save { name.downcase! }
    【解决方案5】:

    调用downcase方法后需要使用感叹号,如果还想将运算结果保存到变量中。 所以对你来说将是可用的:

    self.name.downcase!
    

    不要忘记 .downcase! 替换仅适用于 ASCII 区域。

    【讨论】:

      【解决方案6】:

      另一种解决方案是删除before_save 并猴子补丁initialize 方法

      def initialize(args = {})
        args[:name].downcase! if args[:name]
        super
      end
      

      然后你可以说类似

      irb(main)> t = Transaction.new name: 'BIGTRANSACTION'
      
      irb(main)> t.name
      
      => "bigtransaction
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-04
        • 1970-01-01
        • 1970-01-01
        • 2017-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-04
        相关资源
        最近更新 更多