Ruby on Rails: before_save 将字段转换为小写

24
我想在表单提交到数据库之前将表单字段转换为小写。这是我的代码,但从数据库输出的仍然是大写字母,为什么代码没有起作用?
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

2
before_save { |transaction| transaction.name.downcase! } 在保存之前 { |transaction| transaction.name.downcase! } - bkunzi01
这是一个老问题,但我认为值得指出的是,这个想法有一些意想不到的后果。如果你等到像 name 这样的东西被 downcase 了,你实际上无法获得你认为会得到的唯一性约束。这会给你的客户带来麻烦。你可能想在你的唯一性验证器中结合大小写不敏感来解决这个问题。 - Alex Moore-Niemi
6个回答

38

downcase 返回字符串的一个副本,不修改原始字符串。请使用 downcase!

代替。
def downcase_fields
  self.name.downcase!
end

详细信息请参见文档


这对我有用,我只需要添加安全导航运算符&,使其在我的rspec spec中的名称为nil时正常工作。 self.name&.downcase! - alexventuraio

7

你没有通过运行self.name.downcasename设置为小写,因为#downcase不会修改字符串,它只是返回一个新的字符串。你应该使用带有感叹号的downcase方法。

self.name.downcase!

然而,我喜欢在模型中另一种方式来实现它:

before_save { name.downcase! }

4

另一个简单的示例,代码更少:

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

   before_save { self.name.downcase!}

end

希望这可以帮到您!

1
冗余的 self,你可以避免它
before_save { name.downcase! }
- Mauro

4

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

def downcase_fields
  name.downcase!
end

然而,如果你想继续使用downcase方法,那么你可以按照以下步骤进行:

def downcase_fields
  self.name = name.downcase
end

这将把名字实例变量重新赋值为对原始名称调用downcase方法的结果。

2
你需要在调用downcase方法后使用感叹号,如果你还想将操作的结果保存到变量中。因此,对于你来说可用的代码如下:
self.name.downcase!

请注意,.downcase! 只在 ASCII 区域内起作用。


-7
另一种解决方案是删除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"

@Yoni 这就是为什么我们使用 super。它通过运行 initialize 的先前定义来确保先前的行为被保留。 - Cruz Nunez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接