Rails / ActiveRecord:字段规范化

发布于 2024-07-20 13:59:56 字数 281 浏览 2 评论 0原文

我正在尝试从模型中的字段中删除逗号。 我希望用户输入一个数字,即 10,000,并且该数字应作为 10000 存储在数据库中。我希望我可以进行一些模型端规范化以删除逗号。 我不想依赖视图或控制器来正确格式化我的数据。

我试过了:

before_validation :normalize

def normalize 
 self['thenumber'] = self['thenumber'].to_s.gsub(',','')
end

没有工作。

I'm trying to remove the commas from a field in a model. I want the user to type a number, i.e. 10,000 and that number should be stored in the database as 10000. I was hoping that I could do some model-side normalization to remove the comma. I don't want to depend on the view or controller to properly format my data.

I tried:

before_validation :normalize

def normalize 
 self['thenumber'] = self['thenumber'].to_s.gsub(',','')
end

no worky.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

只有影子陪我不离不弃 2024-07-27 13:59:56

http://github.com/mdeering/attribute_normalizer 看起来是解决这个常见问题的有希望的解决方案。 以下是主页中的一些示例:

  # By default it will strip leading and trailing whitespace
  # and set to nil if blank.
  normalize_attributes :author, :publisher

  # Using one of our predefined normalizers.
  normalize_attribute  :price, :with => :currency

  # You can also define your normalization block inline.
  normalize_attribute :title do |value|
    value.is_a?(String) ? value.titleize.strip : value
  end

因此,根据您的情况,您可能会执行以下操作:

  normalize_attribute :title do |value|
    value.to_s.gsub(',', '')
  end

http://github.com/mdeering/attribute_normalizer looks like a promising solution to this common problem. Here are a few examples from the home page:

  # By default it will strip leading and trailing whitespace
  # and set to nil if blank.
  normalize_attributes :author, :publisher

  # Using one of our predefined normalizers.
  normalize_attribute  :price, :with => :currency

  # You can also define your normalization block inline.
  normalize_attribute :title do |value|
    value.is_a?(String) ? value.titleize.strip : value
  end

So in your case you might do something like this:

  normalize_attribute :title do |value|
    value.to_s.gsub(',', '')
  end
甜嗑 2024-07-27 13:59:56

我认为你做得对。 该测试通过:

test "should remove commas from thenumber" do
  f = Foo.new(:thenumber => "10,000")
  f.save
  f = Foo.find(f.id)
  assert f.thenumber == "10000"    
end

并且我使用了您的代码。

 class Foo < ActiveRecord::Base
  before_validation :normalize

  def normalize 
    self['thenumber'] = self['thenumber'].to_s.gsub(',','')
  end

 end

现在,我的模式设置为数字是字符串,而不是整数。

Started
.
Finished in 0.049666 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

如果你想将其作为整数存储在数据库中,那么你肯定需要重写设置器:

 def thenumber=(value)
   self['thenumber'] = value.to_s.gsub(',','').to_i
 end

如果你按照自己的方式使用整数列,它会被 AR 截断......

>> f.thenumber = "10,000"
=> "10,000"
>> f.thenumber
=> 10

这是一个鲜为人知的事情Ruby 和整数...它通过截断任何不再是整数的内容来自动转换。

irb(main):004:0> i = "155-brian-hogan".to_i
=> 155

对于诸如此类的事情来说可能很酷,

/users/155-brian-hogan

@user = User.find_by_id(params[:id])

但对于你正在做的事情来说就不那么酷了。

因此,要么将 col 更改为字符串并使用过滤器,要么更改 setter :)

祝你好运!

I think you're doing it right. This test passes:

test "should remove commas from thenumber" do
  f = Foo.new(:thenumber => "10,000")
  f.save
  f = Foo.find(f.id)
  assert f.thenumber == "10000"    
end

And I used your code.

 class Foo < ActiveRecord::Base
  before_validation :normalize

  def normalize 
    self['thenumber'] = self['thenumber'].to_s.gsub(',','')
  end

 end

Now, my schema is set up for thenumber to be a string though, not an integer.

Started
.
Finished in 0.049666 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

If you wanted to store this in the db as an integer, then you definitely need to override the setter:

 def thenumber=(value)
   self['thenumber'] = value.to_s.gsub(',','').to_i
 end

If you do it your way, with an integer column, it gets truncated by AR....

>> f.thenumber = "10,000"
=> "10,000"
>> f.thenumber
=> 10

That's a little-known thing with Ruby and integers... it auto-casts by truncating anything that's no longer an integer.

irb(main):004:0> i = "155-brian-hogan".to_i
=> 155

Can be cool for things like

/users/155-brian-hogan

@user = User.find_by_id(params[:id])

But not so cool for what you're doing.

So either change the col to a string and use the filter, or change the setter :)

Good luck!

太阳哥哥 2024-07-27 13:59:56

这样做的问题是,在一段时间内,非标准化的东西会存在于对象中; 如果您有在标准化之前对属性起作用的代码,那么这将是一个问题。

您可以定义一个 setter:

def thenumber=(value)
  # normalise stuff here, call write_attribute
end

不幸的是,我认为很多 Rails 表单内容直接写入属性,这是我不倾向于使用它的原因之一。

或者,您可以在传递控制器中的参数之前对其进行标准化。

The problem with doing it that way is that for a while, the non-normalized stuff will exist in the object; if you have code that works on the attributes before stuff gets normalised, then that will be a problem.

You could define a setter:

def thenumber=(value)
  # normalise stuff here, call write_attribute
end

Unfortunately I think a lot of the Rails form stuff writes the attributes directly, which is one of the reasons I don't tend to use it.

Or you could normalise the params in the controller before you pass them through.

怎樣才叫好 2024-07-27 13:59:56

Rails 7.1 引入了 ActiveRecord::Base::规范化

class User < ApplicationRecord
  normalizes :email, with: ->(email) { email.strip.downcase }
end

它在验证之前调用

它是安全的,因为它不(但可以选择)应用于nil

它适用于持久性和查找器方法

User.create(email: " [email protected] \n")
# => #<User email: "[email protected]">

User.find_by(email: "\[email protected] \t")
# => #<User email: "[email protected]">

如果您需要对<应用规范化code>nil 值也一样,使用 apply_to_nil: true 选项

class User < ApplicationRecord
  normalizes :email, with: ->(email) { email&.strip&.downcase || "[email protected]" }, apply_to_nil: true
end

("[email protected]" 电子邮件将在 nil 情况下分配)

如果您有遗留的非标准化记录,您可以使用 <代码>ActiveRecord::Base#normalize_attribute

user.email # => "[email protected]  "
user.normalize_attribute(:email)
user.email # => "[email protected]"
user.save

Rails 7.1 introduced ActiveRecord::Base::normalizes

class User < ApplicationRecord
  normalizes :email, with: ->(email) { email.strip.downcase }
end

It invokes before validation

It is safe because doesn't (but optionally can) apply to nil

It works with both persistence and finder methods

User.create(email: " [email protected] \n")
# => #<User email: "[email protected]">

User.find_by(email: "\[email protected] \t")
# => #<User email: "[email protected]">

If you need apply normalization for nil values too, use apply_to_nil: true option

class User < ApplicationRecord
  normalizes :email, with: ->(email) { email&.strip&.downcase || "[email protected]" }, apply_to_nil: true
end

("[email protected]" email will be assigned in nil case)

If you have legacy non-normalized record, you can normalize it with ActiveRecord::Base#normalize_attribute

user.email # => "[email protected]  "
user.normalize_attribute(:email)
user.email # => "[email protected]"
user.save
彩虹直至黑白 2024-07-27 13:59:56

ruby 是否允许您在 . 和 [''] ?
我不知道,我稍后会尝试,但我认为你应该使用 .

self.thenumber = self.thenumber.to_s.gsub(',','')

Does ruby let you interchange between a . and [''] ?
I don't know, I'll try later, but I think you are supposed to use .

self.thenumber = self.thenumber.to_s.gsub(',','')
谈场末日恋爱 2024-07-27 13:59:56

您应该从 before_validation 方法返回 true,否则如果分配给 self['thenumber'] 的表达式最终为零或 false,则根据 Rails 文档,数据将不会被保存:

如果 before_* 回调返回 false,
所有后来的回调和
相关操作被取消。

表面上,您尝试在这里进行规范化,然后使用 Rails 验证检查规范化的结果,这将决定 nil/false/blank 是否可以。

before_validation :normalize

def normalize 
  self['thenumber'] = self['thenumber'].to_s.gsub(',','')
  return true
end

You should return true from your before_validation method, otherwise if the expression being assigned to self['thenumber'] ends up being nil or false, the data will not be saved, per the Rails documention:

If a before_* callback returns false,
all the later callbacks and the
associated action are cancelled.

Ostensibly, you are trying to normalize here then check the result of the normalization with your Rails validations, which will decide if nil/false/blank are okay or not.

before_validation :normalize

def normalize 
  self['thenumber'] = self['thenumber'].to_s.gsub(',','')
  return true
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文