Rails / Active Record FAILSAFE错误“用户无法被引用”

时间:2010-09-14 21:07:43

标签: ruby-on-rails ruby validation activerecord

使用Rails 2.3.2(目前不是很好的升级版本),使用ruby 1.8.7(2009-06-12 patchlevel 174)[universal-darwin10.0]。如果验证为:on => :update,则在对模型进行验证时尝试保存时会出现以下错误。如果我将验证更改为:on => :create并创建新记录,我看不到错误,如果没有验证,我没有问题保存。

Completed in 392ms (View: 10, DB: 296) | 200 OK [http://localhost/barfoos/update]
/!\ FAILSAFE /!\  Tue Sep 14 16:38:49 -0400 2010
  Status: 500 Internal Server Error
  User can't be referred
    /path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:67:in `dump'
    /path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:67:in `marshal'
    /path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:123:in `marshal_data!'
    /path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:178:in `send'
    /path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:178:in `evaluate_method'
    /path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:166:in `call'
    /path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:93:in `run'
    /path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `each'
    /path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `send'
    /path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `run'
    /path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:276:in `run_callbacks'
    /path/to/project/vendor/rails/activerecord/lib/active_record/callbacks.rb:344:in `callback'
    /path/to/project/vendor/rails/activerecord/lib/active_record/callbacks.rb:249:in `create_or_update'
    /path/to/project/vendor/rails/activerecord/lib/active_record/base.rb:2539:in `save_without_validation'
    /path/to/project/vendor/rails/activerecord/lib/active_record/validations.rb:1009:in `save_without_dirty'
    /path/to/project/vendor/rails/activerecord/lib/active_record/dirty.rb:79:in `save_without_transactions'
    /path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:229:in `send'
    /path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:229:in `with_transaction_returning_status'
    /path/to/project/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
    /path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:182:in `transaction'
    /path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:228:in `with_transaction_returning_status'
    /path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:196:in `save_without_unsaved_flag'
    /path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
    /path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:196:in `save_without_unsaved_flag'
    /path/to/project/vendor/plugins/active_scaffold/lib/extensions/unsaved_record.rb:15:in `save'
    /path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:300:in `set_session'
    /path/to/project/vendor/rails/activerecord/lib/active_record/base.rb:1453:in `silence'
    /path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:297:in `set_session'
    /path/to/project/vendor/rails/actionpack/lib/action_controller/session/abstract_store.rb:132:in `call'
    /path/to/project/vendor/rails/activerecord/lib/active_record/query_cache.rb:29:in `call'
    /path/to/project/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
    /path/to/project/vendor/rails/activerecord/lib/active_record/query_cache.rb:9:in `cache'
    /path/to/project/vendor/rails/activerecord/lib/active_record/query_cache.rb:28:in `call'
    /path/to/project/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in `call'
    /path/to/project/vendor/rails/actionpack/lib/action_controller/reloader.rb:9:in `call'
    /path/to/project/vendor/rails/actionpack/lib/action_controller/failsafe.rb:11:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `synchronize'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
    /path/to/project/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:106:in `call'
    /path/to/project/vendor/rails/railties/lib/rails/rack/static.rb:31:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:46:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `each'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `call'
    /path/to/project/vendor/rails/railties/lib/rails/rack/log_tailer.rb:17:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/content_length.rb:13:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/handler/webrick.rb:50:in `service'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:162:in `start'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:95:in `start'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:92:in `each'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:92:in `start'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:23:in `start'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:82:in `start'
    /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/handler/webrick.rb:14:in `run'
    /path/to/project/vendor/rails/railties/lib/commands/server.rb:111
    /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
    /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
    script/server:3

该模型如下所示:

class Barfoo < ActiveRecord::Base
  default_scope :conditions => {:scoping_model_id => ScopingModel.current_version.id}
  belongs_to :scoping_model

  # validate is false to keep from attempting to validate Foobar on Barfoo save, as Foobar can be saved, even if invalid, unlike Barfoo.
  has_one :foobar, :validate => false
  validates_presence_of :foobar_id, :on => :create, :message => "can't be blank"
  validates_inclusion_of :accepted_an_agreement, :in => [true, false], :on => :update, :message => "please choose whether you agree or disagree"
  validates_presence_of :some_option_string, :on => :update, :message => "before agreeing, you must specify the some string", :if => Proc.new { |detail| detail.accepted_an_agreement == true }
  validates_presence_of :some_text, :on => :update, :message => "you must provide details if option is 'Other'", :if => Proc.new { |detail| detail.some_option_string == 'Other' }
end

我指定的这些字段的值无关紧要,并且在下面的评论中注明Shadwell,它似乎与会话相关。我们在ApplicationController中执行会话相关和用户相关的一件事可能会导致此问题,即使它在此之前从未出现过问题。 ApplicationController看起来像:

class ApplicationController < ActionController::Base
  include ExceptionNotifiable
  require 'something_that_defines_update_method_that_we_redefine_in_controller'
  include Userstamp

  ActionController::Base.session_options[:httponly] = true
  ActionController::Base.session_options[:secure] = true

  prepend_before_filter :user_setting_method

  ...

  protected

  def user_setting_method
    session[:username] ||= optional_override_username
    session[:username] = session[:username]  # touch the session for timeout purposes
    @user ||= User.find_by_username session[:username]
    true
  end

  ...

end

搜索没有提及/!\ FAILSAFE /!\User can't be referred的关系。任何关于什么会导致这种情况的想法,是否存在可以解决这个问题的常见解决方案?

请注意,附加到此的foobar实例已保存,但在此特定情况下,foobar之前已保存很久,但未进行验证(未经验证即保存,这是正常的可能的状态,因为它是来自多页表单的数据,可以部分保存数据,用户可以返回并在以后更正完成。

2 个答案:

答案 0 :(得分:1)

继续开发模型之后,我开始收到另一个错误:

/!\ FAILSAFE /!\  Fri Sep 17 14:53:50 -0400 2010
  Status: 500 Internal Server Error
  can't dump hash with default proc

我尝试在控制台中保存模型并且成功了,但看到了一些奇怪的事情。当我已经在模型上设置了有效的foobar_id时,它要求foobar有效(例如)。所以,我和一个团队成员讨论过这个问题,听说他已经读过有关试图验证相关对象id的问题。

我删除了:

validates_presence_of :foobar_id, :on => :create, :message => "can't be blank"

并且有效。

但是,另一位同事向我建议,我所遇到的问题可能与执行validates_presence_of :foobar_id有关,当我在控制器中尝试设置foobar时:

barfoo.foobar = foobar

而不是像foobar_id那样设置:

barfoor.foobar_id = foobar.id

我还注意到,在前一个示例中,它没有在数据库的相关行中设置foobar_id

将其更改为在foobar_id上设置barfoo后,只要没有更新验证,它似乎会保存在创建和更新上。但是,如果我添加验证:on => :update的验证,则会失败。

答案 1 :(得分:0)

我在这儿这么晚了。但我也有同样的问题,我得到了一个临时的解决方案

activerecord/lib/active_record/session_store.rb

中覆盖marshal方法
ActiveRecord::SessionStore::ClassMethods.module_eval do
  def marshal(data)
    # To prevent from Marshal dump error
    begin       
      ::Base64.encode64(Marshal.dump(data)) if data
    rescue      
      # Checks for any ActiveRecord object in session variables and reloads it
      data.each_pair do |key,obj|
        if obj.is_a?(ActiveRecord::Base) || obj.is_a?(Array)
          unless obj.is_a?(Array)       
            data[key] = obj.reload              
            next                                
          end                           
          data[key].collect do |it_obj| 
            if obj.is_a?(ActiveRecord::Base)    
              it_obj.reload                             
            else                                
              it_obj                                    
            end                                 
          end                           
        end                     
      end               
      ::Base64.encode64(Marshal.dump(data)) if data
    end         

  end   
end

简单来说,它将重新加载会话变量

中存在的所有ActiveRecord对象