我正面临一个奇怪的错误。任何人都可以解释一下这个原因..
我有一个名为网站,设置和体验的模型。
设置和体验包含数据库列“位”
在我的网站模型中,我有这段代码
def populate_experiences_bit_set
self.experiences.map(&:bit).inject(0, :|)
end
def populate_settings_bit_set
self.settings.map(&:bit).inject(0, :|)
end
在名为2_28.rake的rake文件中,有一种名为 bit 的方法
def bit(klass)
current_class = klass.find(:all)
if current_class.count == 0
return 1
else
return (current_class.last.bit * 2)
end
end
此方法用于同一rake文件中的rake任务'get_value'之一。
另一个rake任务名为create_sites_report_data,在同一个文件中有一行:
site.populate_experiences_bit_set
现在我运行rake任务
rake releases:2.28:create_sites_report_data
我收到错误说明
“尝试调用私有方法 /Users/rakeshshetty/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.5/lib/active_record/attribute_methods.rb:236:in `method_missing'“
In console, this works fine
>> s = Site/364
=> #<Site id: 364, name: "1 Field Ambulance - Detachment Wainwright", type: "Site", created_at: "2009-12-29 16:53:58", updated_at: "2009-12-29 16:53:58", short_name: "1 Field Am", self_updated_at: nil, last_updater_id: nil, vfp_id: "2BL0NFMI1", dup_reference_id: nil, field_id: nil, marked_as_deleted: false>
>> s.experiences.map(&:bit).inject(0, :|)
=> 0
>> s.settings.map(&:bit).inject(0, :|)
=> 64
我将2_28.rake文件中的方法名称从bit替换为bit_x Rake工作得很好
blsi1181a:cpi_2.24 rakeshshetty$ rails -v
Rails 2.3.5
blsi1181a:cpi_2.24 rakeshshetty$ ruby -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.3.0]
我的问题是bit是设置和体验中的一个字段。它如何调用rake方法函数bit()? 加载应用程序后是否加载了此rake文件?
答案 0 :(得分:1)
我认为这是问题所在:
该模型没有bit
方法,它使用“方法缺失”方法创建它(也就是说,当您在对象上调用不存在的方法时,它会调用其method_missing方法,这会引发异常默认情况下)。
ActiveRecord使用缺少的方法来设置相关表的列的方法(即:
Site.new.bit -> the method does not exist -> method_missing ->
is there a column called 'bit'? -> yes -> create the method bit with this code
现在,您在对象级别创建了一个bit
方法。可能它打破了ActiveRecord的method_missing
方法:
Site.new.bit -> the method exists -> call that method
资源:
如果查看ActiveRecord源(接近错误):
def method_missing(method_id, *args, &block)
method_name = method_id.to_s
if self.class.private_method_defined?(method_name)
raise NoMethodError.new("Attempt to call private method", method_name, args)
end
[...]
现在,尝试以下任务:
namespace :rake_test do
desc 'With bit method'
task :with => :environment do
def bit(klass)
# Implementation
end
puts Object.private_method_defined?("bit")
puts Settings.private_method_defined?("bit")
end
desc 'Without bit method'
task :without => :environment do
puts Object.private_method_defined?("bit")
puts Settings.private_method_defined?("bit")
end
end
让我们运行它们:
rake rake_test:with ; rake rake_test:without
输出:
true
true
false
false
定义bit
方法时,您处于Object上下文中(这不仅适用于rake任务文件,而且适用于每个ruby脚本文件)。所以你定义了一个Object.bit
方法;正如您在Rails源代码中看到的那样,在定义模型bit
方法之前,它会尝试查看是否存在Model.method
,如果存在,则会引发异常。
作为Settings
的{{1}}类子类(与每个标准类一样),您的Object
定义会破坏事物。