今天从 3.2.7 升级到 Rails 3.2.9,似乎方法“to_i”已从 ActiveRecord 中删除。
这是设计使然吗?或者它是一个错误?我在更改说明中找不到任何提及。这将影响很多代码。
谢谢!
今天从 3.2.7 升级到 Rails 3.2.9,似乎方法“to_i”已从 ActiveRecord 中删除。
这是设计使然吗?或者它是一个错误?我在更改说明中找不到任何提及。这将影响很多代码。
谢谢!
该#to_i
方法从未存在,但是在 Rails 3.2.8 中将对象分配给值的方式发生了变化。
鉴于以下情况:
class Lecture < ActiveRecord::Base
has_one :professor
end
以前,您可以将教授分配给这样的讲座:
@lecture.professor = Professor.find_by_id(1)
或者像这样:
@lecture.professor_id = Professor.find_by_id(1)
在第一种情况下,一切都很简单,因为professor
关联需要一个教授对象。在第二种情况下,尽管 ActiveRecord 执行了一些魔法来强制从教授那里获取 id,因为它professor_id
需要一个整数。
在 Rails 3.2.8 及更高版本中,这种魔法不再有效。这在某种程度上很好,因为它暗示你可能做错了什么。例如,如果professor_id
数据库中没有列,而只是professor
需要一个整数,则这样的分配将不再有效。
看起来这将恢复到 Rails 3.2.11 中的先前行为。
我遇到了同样的错误。不是 ActiveRecord 缺少 #to_i 而是其他东西,在我的例子中涉及 factory_girl gem。
factory_girl (4.1.0)
factory_girl_rails (4.1.0)
这是差异的一个孤立案例:
rails _3.1.0_ new rails31
cd rails31
bundle install
rails g scaffold note title:string contents:text
rails g scaffold user name:string
rails g migration add_user_id_to_notes user_id:integer
rake db:migrate
然后在控制台中:
require 'factory_girl'
FactoryGirl.define { factory :note }
Factory(:note, :user_id => User.first, :title => 'foo')
User Load (0.1ms) SELECT "users".* FROM "users" LIMIT 1
SQL (0.5ms) INSERT INTO "notes" ("contents", "created_at", "title", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?) [["contents", nil], ["created_at", Sun, 13 Jan 2013 21:29:36 UTC +00:00], ["title", "foo"], ["updated_at", Sun, 13 Jan 2013 21:29:36 UTC +00:00], ["user_id", 1]]
=> #<Note id: 3, title: "foo", contents: nil, created_at: "2013-01-13 21:29:36", updated_at: "2013-01-13 21:29:36", user_id: 1>
但是,如果我执行相同的步骤序列:
rails _3.2.11_ new rails3211
然后在控制台中我看到:
1.9.2-p290 :001 > require 'factory_girl'
=> true
1.9.2-p290 :002 > FactoryGirl.define { factory :note }
=> []
1.9.2-p290 :003 > Factory(:note, :user_id => User.first, :title => 'foo')
User Load (0.1ms) SELECT "users".* FROM "users" LIMIT 1
(0.0ms) begin transaction
SQL (24.5ms) INSERT INTO "notes" ("contents", "created_at", "title", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?) [["contents", nil], ["created_at", Sun, 13 Jan 2013 21:33:03 UTC +00:00], ["title", "foo"], ["updated_at", Sun, 13 Jan 2013 21:33:03 UTC +00:00], ["user_id", nil]]
(2.4ms) commit transaction
=> #<Note id: 1, title: "foo", contents: nil, created_at: "2013-01-13 21:33:03", updated_at: "2013-01-13 21:33:03", user_id: nil>
注意 Rails 3.2.11 的 nil user_id
Rails 3.2.9 中的“to_i”方法有一个变化,但它处理的是列而不是表。见这里。
因此,在您的代码中,如果您传递的是整个对象而不是列值,那么它之前会默默地失败。但现在它实际上会调用对象上的“to_i”方法并引发异常。
我不相信该to_i
方法在他们自己的 AR 对象上可用。您能否更具体地了解该方法的早期用途,但现在失败了?
是的,当我将 rails 3.2.3 版升级到 rails 3.2.11 时,我也遇到了同样的问题。
这是一些代码片段有什么确切的问题
在 Rails 3.2.3中,
医生 = Doctor.first
patient = Patient.new
patient.doctor_id =doctor (右侧对象分配有效)
Patient.save!(有效)
在 rails 3.2.11
中医生 = Doctor.first
患者 = Patient.new 患者.doctor_id
= 医生(右侧对象分配无效)
Patient.save!(无效)
NoMethodError: undefined method 'to_i' error 我们得到了这种分配。
结论是我们只使用 _ID = INTEGER 而不是像对象分配一样。
更多细节
为了跟进 Luca,我使用的是 Rails 3.2.11,我不确定我是否有这样的代码,但我确实发现它不再起作用:
@lecture.update_attribute(:professor_id, Professor.find_by_id(1))