在postgres / active record

时间:2016-02-09 17:59:55

标签: ruby-on-rails postgresql ruby-on-rails-4

我正在使用带有Postgres数据库的Rails 4,并且遇到一个问题,即我的邮政编码列中没有保存前导零。此列的数据类型为字符串。当我在rails控制台并且我更新并且帐户的邮政编码从“7040”到“07040”并且前导零时我被告知它已被保存。但是,当我查找对象时,邮政编码仍然是“7040”,而不是“07040”。

我在SO上看到了这个问题,但答案建议重新启动你的服务器(我没有改变行为),并提到问题出在该用户的情况下,列的数据类型曾经是一个整数。我的数据类型一直是一个字符串。

keep leading zeros when saving string in active record

您可以在下面的图片中看到我在rails控制台中执行此工作的快照。我得到一个帐户。我用前导零保存拉链。保存似乎有效。然后我按其ID查找帐户并查找zip并且尾随“0”不保存:

我已经在这里更新了我的控制台图像!

rails console example with save!

此外,我在模型上有这些验证:

验证:contact_name,:company_name,:organization_id,:billing_address,:city,:state,:zip,presence:true

验证:account_number,唯一性:{scope :: organization_id}

为了更具体地解决这个问题,我在下面有两个测试。非常奇怪的是,测试A在测试B通过时失败。所以这不是在前面保存0的问题 - 不知何故我在保存一个前缀为'0'的字符串时遇到了问题。那为什么会这样?我有很多拉链要更新,所以我不能像TEST B那样手动设置它们 - 我需要找到一种方法来以TEST A的方式保存它们。

it 'TEST A' do
  @a= create(:account, zip: '299')
  new_zip = @a.zip.prepend("0")
  @a.zip = new_zip
  @a.save!
  @a.reload
  @z = Account.find @a.id
  expect(@z.zip).to eq('0299')
end

it 'TEST B' do
  @a= create(:account, zip: '299')
  @a.zip = "0299"
  @a.save!
  @a.reload
  @z = Account.find @a.id
  expect(@z.zip).to eq('0299')
end

3 个答案:

答案 0 :(得分:0)

您可以屏蔽客户端上的值,而不必担心数据库。

"%05d" % zip_code.to_i

答案 1 :(得分:0)

所以我认为你被insertprepend原地修改字符串这一事实所困扰:

1.9.3-p194 :001 > s = "a"
 => "a" 
1.9.3-p194 :002 > s.prepend "b"
 => "ba" 
1.9.3-p194 :003 > s
 => "ba" 
1.9.3-p194 :004 > s.insert 0, "c"
 => "cba" 
1.9.3-p194 :005 > s
 => "cba" 

当你这样做时,Rails不知道你已经改变了字符串内容。即使分配@a.zip = new_zip也无济于事,因为@a.zipnew_zip仍然是同一个对象,如果rails在zip=方法中对它们进行比较,它们似乎是相同。因此Rails认为该属性没有改变。这就是为什么在您的控制台会话中,当您说a.save!没有发出UPDATE时。 Rails没有意识到属性是脏的。

您可以致电s.zip_will_change!来解决此问题。或者对s.zip = "0#{s.zip}"等新字符串进行分配。

答案 2 :(得分:0)

奇怪的是,我发现由于这些线路拉链没有保存:

new_zip = @ a.zip.prepend(" 0")

@ a.zip = new_zip

@ a.save!

出于某种原因,上面的代码带有' prepend'不会保存,但下面的代码确实有效。所以我用这个更新了我的拉链并且它正在工作。

@ a.zip =(" 0" + @ a.zip)

@ a.save