我刚刚将旧版应用从Rails 3.2.7
升级到3.2.21
,从Ruby 1.9.3
升级到2.0.0
,我在尝试应用时遇到以下错误:
Started PUT "/books/17" for 127.0.0.1 at 2015-01-20 16:15:10 -0800
Processing by BooksController#update as HTML
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"mXizjcxG5Yq0BYG9vvvuqjW6O3/KhG6fUkoEeU6ORP8=",
"book"=>{"new_book_item_attributes"=>{"1421799301.062898"=>{"content_id"=>"16"}}},
"commit"=>"Add selected content", "id"=>"17"}
ActiveRecord::UnknownAttributeError (unknown attribute: new_book_item_attributes):
app/controllers/books_controller.rb:70:in `block in update'
app/controllers/books_controller.rb:69:in `update'
以下是我的相关代码:
books_controller.rb:69
if @book.update_attributes(params[:book])
book.rb
class Book < ActiveRecord::Base
attr_accessible ... :new_book_item_attributes
def new_book_item_attributes=(attributes)
attributes.each do |attribute|
book_items.build(skip_over_time(attribute))
end
end
我查看了来自 Rails的http://weblog.rubyonrails.org/releases/中的每个博客条目3.2.8.rc1已经发布!到 Rails 3.2.21,4.0.12和4.1.8已被释放,我没有发现可能解释这个问题的任何激烈的事情。无论如何,这是一个&#34;补丁级别&#34;升级,所以我不希望任何重大变化。知道什么可能有问题吗?
更新
3.2.21
和Ruby 1.9.3
不会发生此问题(只有Ruby 2.0.0
才会出现此问题(无论Rails(3.2.21
还是3.2.7
) )。我修改了@ xavier-shay标识的代码块,如下所示:
puts "-1- attributes: #{attributes.inspect}"
attributes.each do |k, v|
puts "-2- testing k: #{k}, v: #{v}"
if k.include?("(")
puts "-3- true to k.include?(\"(\")"
multi_parameter_attributes << [ k, v ]
elsif respond_to?("#{k}=")
puts "-4- true to respond_to?(\"#{k}=\")"
if v.is_a?(Hash)
puts "-5- true to v.is_a?(Hash)"
nested_parameter_attributes << [ k, v ]
else
puts "-6- else"
send("#{k}=", v)
end
else
puts "-7- UnknownAttributeError"
raise(UnknownAttributeError, "unknown attribute: #{k}")
end
end
在Ruby 2.0.0
和Rails 3.2.21
上运行它会引发上述参数的异常:
-1- attributes: {"new_book_item_attributes"=>{"1421825320.571702"=>{"content_id"=>"8"}}}
-2- testing k: new_book_item_attributes, v: {"1421825320.571702"=>{"content_id"=>"8"}}
-7- UnknownAttributeError
...但是,在另一个控制器中,(显然有不同的参数)没有问题:
-1- attributes: {"title"=>"test title", "subtitle"=>"test subtitle"}
-2- testing k: title, v: test title
-4- true to respond_to?("title=")
-6- else
-2- testing k: subtitle, v: test subtitle
-4- true to respond_to?("subtitle=")
-6- else
在Ruby 1.9.3
和Rails 3.2.21
上运行它没有问题:
-1- attributes: {"new_book_item_attributes"=>{"1421828430.9315462"=>{"content_id"=>"8"}}}
-2- testing k: new_book_item_attributes, v: {"1421828430.9315462"=>{"content_id"=>"8"}}
-4- true to respond_to?("new_book_item_attributes=")
-5- true to v.is_a?(Hash)
-1- attributes: {"content_id"=>"8"}
-2- testing k: content_id, v: 8
-4- true to respond_to?("content_id=")
-6- else
-1- attributes: {"book_id"=>17}
-2- testing k: book_id, v: 17
-4- true to respond_to?("book_id=")
-6- else
这个演绎指向Ruby,而不是Rails。关于我应该如何进一步调试的任何想法?
答案 0 :(得分:2)
我怀疑这里缺少一些造成问题的背景,因为从你所提供的内容来看,它是不明显的。
以下是一些如何跟踪此选项的选项。
找出 rails中的哪些代码引发此异常。 Ruby使这非常简单。你可以删除你的回溯消音器(可能在config/initializers/backtrace_silencers.rb
中),或者你可以grep UnknownAttributeError
的Rails源代码。事实证明,只有one place where this error is raised:
attributes.each do |k, v|
if k.include?("(")
multi_parameter_attributes << [ k, v ]
elsif respond_to?("#{k}=")
if v.is_a?(Hash)
nested_parameter_attributes << [ k, v ]
else
send("#{k}=", v)
end
else
raise(UnknownAttributeError, "unknown attribute: #{k}")
end
end
由此可以看出,您的模型没有正确响应方法名称。您可以在此处添加一些puts
语句(使用bundle show rails
查找磁盘上的位置)或在控制台中使用它来查看正在发生的事情。
通过二等分确切地确定哪个修补程序版本导致了问题。换句话说,转到3.2.15并查看是否看到错误。一旦您隔离了破坏它的版本,您可以查看差异和/或更改日志以查看更改的内容。至少,缩小范围将有助于其他人在这里为您提供帮助。
您能否进行最小化再现?您可以从模型中删除多少代码但仍会出现问题?您可以使用独立的ActiveRecord脚本重现该问题吗?即Active record in standalone Ruby
希望有所帮助,让我知道你的去向!
答案 1 :(得分:2)
我认为ruby 1.9.3和ruby 2.0之间没有任何区别:
class Dog
def new_book_item_attributes=()
end
end
d = Dog.new
k = "new_book_item_attributes"
if d.respond_to?("#{k}=")
p %Q{-4- true to respond_to?("#{k}=")}
end
注意:您不需要在ruby中转义内部引号。
输出:
~/ruby_programs$ ruby -v
ruby 1.9.3p547 (2014-05-14 revision 45962) [x86_64-darwin10.8.0]
~/ruby_programs$ ruby 1.rb
"-4- true to respond_to?(\"new_book_item_attributes=\")"
~/ruby_programs$ rvm use 2.0.0
Using /Users/7stud/.rvm/gems/ruby-2.0.0-p481
~/ruby_programs$ ruby -v
ruby 2.0.0p481 (2014-05-08 revision 45883) [x86_64-darwin10.8.0]
~/ruby_programs$ ruby 1.rb
"-4- true to respond_to?(\"new_book_item_attributes=\")"
~/ruby_programs$
您可以重新运行测试并使用p
代替puts来输出字符串吗?
我在两个版本的ruby下得到相同的输出:
class Dog
def new_book_item_attributes=()
end
end
d = Dog.new
attributes = {"new_book_item_attributes"=>{"1421825320.571702"=>{"content_id"=>"8"}}}
puts "-1- attributes: #{attributes.inspect}"
multi_parameter_attributes = []
nested_parameter_attributes = []
attributes.each do |k, v|
puts "-2- testing k: #{k}, v: #{v}"
if k.include?("(")
puts "-3- true to k.include?(\"(\")"
multi_parameter_attributes << [ k, v ]
elsif d.respond_to?("#{k}=")
puts "-4- true to respond_to?(\"#{k}=\")"
if v.is_a?(Hash)
puts "-5- true to v.is_a?(Hash)"
nested_parameter_attributes << [ k, v ]
else
puts "-6- else"
send("#{k}=", v)
end
else
puts "-7- UnknownAttributeError"
raise(UnknownAttributeError, "unknown attribute: #{k}")
end
end
--output:--
~/ruby_programs$ ruby -v
ruby 1.9.3p547 (2014-05-14 revision 45962) [x86_64-darwin10.8.0]
~/ruby_programs$ ruby 1.rb
-1- attributes: {"new_book_item_attributes"=>{"1421825320.571702"=>{"content_id"=>"8"}}}
-2- testing k: new_book_item_attributes, v: {"1421825320.571702"=>{"content_id"=>"8"}}
-4- true to respond_to?("new_book_item_attributes=")
-5- true to v.is_a?(Hash)
~/ruby_programs$ rvm use 2.0.0
Using /Users/7stud/.rvm/gems/ruby-2.0.0-p481
~/ruby_programs$ ruby -v
ruby 2.0.0p481 (2014-05-08 revision 45883) [x86_64-darwin10.8.0]
~/ruby_programs$ ruby 1.rb
-1- attributes: {"new_book_item_attributes"=>{"1421825320.571702"=>{"content_id"=>"8"}}}
-2- testing k: new_book_item_attributes, v: {"1421825320.571702"=>{"content_id"=>"8"}}
-4- true to respond_to?("new_book_item_attributes=")
-5- true to v.is_a?(Hash)
~/ruby_programs$
令人沮丧。 :(