I have a button which is sending a get request over XHR to a specific action in a rails server. This action calls a function I defined in the model "Category". This function does something like x=Category.subcategories, and in the next line something like x.map(&:id), or x.each {|x| y << x.id}. (Category has_many :subcategories). In my development environment this works for 1-10 clicks on this button, but then stops working for the following reason:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.include?
With the following dump:
C:/MyApp/vendor/rails/activerecord/lib/active_record/attribute_methods.rb:142:in `create_time_zone_conversion_attribute?'
C:/MyApp/vendor/rails/activerecord/lib/active_record/attribute_methods.rb:75:in `define_attribute_methods'
C:/MyApp/vendor/rails/activerecord/lib/active_record/attribute_methods.rb:71:in `each'
C:/MyApp/vendor/rails/activerecord/lib/active_record/attribute_methods.rb:71:in `define_attribute_methods'
C:/MyApp/vendor/rails/activerecord/lib/active_record/attribute_methods.rb:355:in `respond_to?'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:215:in `method_missing'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:215:in `map'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:215:in `send'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:215:in `method_missing'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:369:in `method_missing'
C:/MyApp/app/models/category.rb:24:in `fetch_prices_grouped_by_date'
C:/MyApp/app/controllers/categories_controller.rb:103:in `show'
Restarting the server fixes the problem for the next 1-10 clicks and then it reappears. When debugging that line (on NetBeans IDE, ruby-debug-ide-0.3.1), I get (after crossing the 1-10 "good clicks") to the method_missing (method="map", self="{Array, 23 elements}"), and if I try to expand the watch on variable x, the debug server crashes. Following the advice of this post, I edited my environment.rb and turned class caching on:
config.cache_classes = true
and the problem is solved. However, it is very annoying to restart the server after each change in code, and I was wondering if anyone has an idea of what is going on, why changing the cache_classes solves it, and if there is any other workaround that doesn't carry the pain of restarting after every edit.
I'm using Rails 2.3.8.
Many thanks, Amit
EDIT:
OK, so after some more debugging I realize it fails on having skip_time_zone_conversion_for_attributes set to nil for some reason in create_time_zone_conversion_attribute? method (active_record/attribute_methods.rb).
Found this article after some research. Adding:
self.skip_time_zone_conversion_for_attributes = []
to the model doesn't work.
Replacing in environment.rb
config.time_zone = 'UTC'
with
config.active_record.default_timezone = :utc
doesn't work for me either, as I get "stack level too deep" with:
C:/MyApp/vendor/rails/activerecord/lib/active_record/attribute_methods.rb:237:in `method_missing'
C:/MyApp/vendor/rails/activerec开发者_JAVA百科ord/lib/active_record/attribute_methods.rb:253:in `method_missing'
C:/MyApp/vendor/rails/activerecord/lib/active_record/attribute_methods.rb:211:in `to_proc'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:369:in `method_missing'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:215:in `map'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:215:in `send'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:215:in `method_missing'
C:/MyApp/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:369:in `method_missing'
C:/MyApp/app/models/category.rb:24:in `fetch_prices_grouped_by_date'
C:/MyApp/app/controllers/categories_controller.rb:103:in `show'
I'll investigate it further to see if it's just a specific issue with my code.
EDIT #2
Ok, per this article's recommendation I edited attributes_methods.rb line 252 and changed it from:
if self.class.primary_key.to_s == method_name
to:
if false and self.class.primary_key.to_s == method_name
And now it works. However, not sure I like messing around with the framework's code. Would appreciate any other suggestions for workarounds.
Thanks! Amit
Edit #3
Ok, this last change broke other parts of my application. I have reposted this question here.
Finally solved! After posting a third question and with help of trptcolin, I could confirm a working solution.
The problem: I was using require
to include models from within Table-less models (classes that are in app/models but do not extend ActiveRecord::Base). For example, I had a class FilterCategory
that performed require 'category'
. This messed up with Rails' class caching.
I had to use require
in the first place since lines such as Category.find :all
failed.
The solution (credit goes to trptcolin): replace Category.find :all
with ::Category.find :all
. This works without the need to explicitly require any model, and therefore doesn't cause any class caching problems.
The "stack too deep" problem also goes away when using config.active_record.default_timezone = :utc
精彩评论