我正在使用带有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
答案 0 :(得分:0)
您可以屏蔽客户端上的值,而不必担心数据库。
"%05d" % zip_code.to_i
答案 1 :(得分:0)
所以我认为你被insert
和prepend
原地修改字符串这一事实所困扰:
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.zip
和new_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