before_save rails 5未按预期工作

时间:2017-12-28 15:35:22

标签: ruby-on-rails

我的模型中有一个before_save,可以将逗号转换为点正常工作。但不知怎的,它破了。示例:用户输入1,22和值无条件存储,如1.00

我需要将值存储为小数,即使用户键入逗号而不是点。因为我住的地方逗号是分隔符。

before_save { self.price.to_s.gsub(',', '.').to_f }

我也试过改变这个:

before_save :convert_comma

private

  def convert_comma
      self.price = self.price.to_s.gsub(',', '.').to_f 
  end

我在控制台中对上面的逗号替换进行了测试并且它可以正常工作,但是对于before_save,数据的存储舍入为1.00

Rails控制台:

2.3.4 :001 > p = Ticket.new("driver_id"=>"3", "origin_id"=>"AP", "origin_city_id"=>"Amapá", "destination_id"=>"GO", "destination_city_id"=>"Abadia de Goiás", "start_date"=>"29/12/2017 19:28", "return_date"=>"29/12/2017 19:28", "annotation"=>"1", "rate"=>"1", "price"=>"1233,22", "status"=>"Aberto") => # <Ticket id: nil, start_date: "2017-12-29 19:28:00", return_date: "2017-12-29 19:28:00", rate: #<BigDecimal:68e22a8,'0.1E1',9(18)>, price: #<BigDecimal:68e21e0,'0.1233E4',9(18)>, annotation: "1", status: "Aberto", department_id: nil, origin_id: "AP", destination_id: "GO", driver_id: 3, created_at: nil, updated_at: nil, origin_city_id: "Amapá", destination_city_id: "Abadia de Goiás", manager: nil, day: nil, user_id: nil, deleted_at: nil>

2.3.4 :002 > p.save (0.2ms) SAVEPOINT active_record_1 SQL (0.6ms) INSERT INTO "tickets" ("start_date", "return_date", "rate", "price", "annotation", "status", "origin_id", "destination_id", "driver_id", "created_at", "updated_at", "origin_city_id", "destination_city_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["start_date", "2017-12-29 19:28:00"], ["return_date", "2017-12-29 19:28:00"], ["rate", 1.0], ["price", 1233.0], ["annotation", "1"], ["status", "Aberto"], ["origin_id", "AP"], ["destination_id", "GO"], ["driver_id", 3], ["created_at", "2017-12-29 21:55:22.119679"], ["updated_at", "2017-12-29 21:55:22.119679"], ["origin_city_id", "Amapá"], ["destination_city_id", "Abadia de Goiás"]] (0.1ms) RELEASE SAVEPOINT active_record_1 => true

这真的很奇怪。知道会发生什么事吗? 谢谢!

3 个答案:

答案 0 :(得分:2)

这里的问题是,只要在初始化程序(Ticket.new)中写入属性,活动记录就会将字符串强制转换为BigDecimal。请注意,在控制台输出中,您的实例为price属性保存BigDecimal,值为“0.1233E4”,而不是“0.123322e4”。这意味着当你的:convert_comma方法运行时:

self.price.to_s #=> '1233.0'

一种可能的解决方案是覆盖模型中的属性writer,在ticket.rb文件中编写以下实例方法:

def price=(new_price)
  super(BigDecimal.new(new_price.to_s.gsub(',', '.')))
end

答案 1 :(得分:1)

我不确定是否理解了您的问题,我认为该错误正在尝试转换','in'。'在一个数字类型。您可以在视图中使用NumberHelper方法更改其打印方式,例如:

<%= number_with_delimiter(@product.price, delimiter: ",", separator: ".") %>

分隔符是千位和分隔符的小数,如果货币可能是更好的number_to_currency方法

<%= number_to_currency(@product.price, delimiter: ".", separator: ",", unit: "€") %>

修改 a link to ActionView::Helpers::NumberHelper references

再次编辑 由于你需要允许用户使用数字逗号作为分隔符,我建议你自己查找或写一个18n文件放入你的config / locales文件夹,对于巴西它应该是br.yml。在语音“number:”处,您可以设置货币和格式,并设置分隔符和分隔符。 要在默认情况下设置此文件,请在config / application.rb上添加以下行:

module YourApp
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.
    config.i18n.default_locale = :br
  end
end

然后你的number_field需要有正确的步骤选项:

<%= f.number_field :price, step: 0.01 %>

这应该有效并且还允许您翻译系统消息:)

答案 2 :(得分:1)

我在https://stackoverflow.com/a/11585385/2188585找到了解决方法并修改为:

before_save :pricecomma

def pricecomma
  price     
end

def pricecomma=(price)
  self.price = price.gsub(',', '.') unless price.blank?
end

将表单更改为:

<%= f.text_field :pricecomma %>

仍然没有得到正在发生的事情。我尝试了没有此虚拟属性的相同代码,并且没有获得替换。但这种方式很好。