Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stange random crashes with Rails 3.1 in production

I see some stange random crashes with my brand new Rails 3.1 rc5 application running in production mode. The backend is nginx with 3 thin instances.

[Exception] users#show (NoMethodError) "undefined method `text?' for nil:NilClass"

 undefined method `text?' for nil:NilClass
 activerecord (3.1.0.rc5) lib/active_record/validations/uniqueness.rb:57:in `build_relation'

I turned on log: debug. However the only information is "Internal Server Error" Anyone seen this before? Identity map is turned om...

If I restart the thin, Rails will run without problems for a few hours.

Update1: Looks like it is pretty much all my controller actions that generate this error randomly. This morning I got an email with the error above. If I follow the link, the page is generated with no problems.

I was wondering if this issue somehow could be related to problems loading the User from a cookie?

class ApplicationController < ActionController::Base
  protect_from_forgery
  layout "content_with_sidebar"
  before_filter :system

  rescue_from CanCan::AccessDenied do |exception|
    flash[:warning] = "Ingen adgang!"
    redirect_to root_url
  end  

  def system
    if current_user
      unless current_user.email_verified == "t"
        flash[:warning] = 'Please activate your account.'
      end
      current_user.last_seen = Time.now
      current_user.save # <--- line 18
      @new_messages = Message.new_messages(current_user).count
    end
  end

  helper_method :current_user

  private

  def current_user
    if cookies[:auth_token]
      @current_user ||= User.find_by_auth_token!(cookies[:auth_token]) 
    end
  end   
end

Code Example from Users#Show

class UsersController < ApplicationController
  before_filter :ensure_current_user_url, :only => :show
  load_and_authorize_resource

  def ensure_current_user_url
    @user = User.find(params[:id].downcase)
    redirect_to @user, :status => :moved_permanently unless @user.friendly_id_status.best?
  end  

  def show
    if params[:do] == "guestbook"
      @comment = @user.comments.new
      @comments = @user.comments.includes(:author).order("created_at DESC").all(:limit => 5)
    else
      @recent_comments = @user.comments(:order => "created_at DESC")
    end
    @arts = @user.arts.order("created_at desc").includes([:author, :category]).page(params[:page]).per(24)
    render :layout => "content_with_sidebar_whitebox"
  end

Update2 This is the information I got with the debug added.

************** username
************** ["id", "username", "email", "email_verified", "birthday", "firstname", "lastname", "phone", "website", "profile", "last_seen", "administrator", "cached_slug", "password_salt", "crypted_password", "avatar", "avatar_cache", "comments_count", "arts_count", "auth_token", "account_activation_token", "account_activation_sent_at", "password_reset_token", "password_reset_sent_at", "created_at", "updated_at", "cheapest", "most_expensive"]
************** email
************** ["id", "username", "email", "email_verified", "birthday", "firstname", "lastname", "phone", "website", "profile", "last_seen", "administrator", "cached_slug", "password_salt", "crypted_password", "avatar", "avatar_cache", "comments_count", "arts_count", "auth_token", "account_activation_token", "account_activation_sent_at", "password_reset_token", "password_reset_sent_at", "created_at", "updated_at", "cheapest", "most_expensive"]

This is a full stack trace from a crash this morning.

Started GET "/messages" for filtered-ip at 2011-08-15 12:13:17 -0400


Processing by MessagesController#index as HTML
  User Load (1.5ms)  SELECT "users".* FROM "users" WHERE "users"."auth_token" = '380e8b776cb8e3c5fd7d8b777b6d2073' ORDER BY last_seen desc LIMIT 1
   (0.3ms)  BEGIN
   (0.9ms)  SELECT 1 FROM "users" WHERE ("users"."username" = 'samia-dk' AND "users"."id" != 483) LIMIT 1
   (0.9ms)  SELECT 1 FROM "users" WHERE ("users"."email" = '[email protected]' AND "users"."id" != 483) LIMIT 1
   (0.4ms)  ROLLBACK
Completed 500 Internal Server Error in 14ms
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/_request.text.erb (0.8ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/_title.text.erb (0.4ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/_session.text.erb (0.9ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/_title.text.erb (0.1ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/_environment.text.erb (55.3ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/_title.text.erb (0.3ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/_backtrace.text.erb (1.7ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/_title.text.erb (0.2ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/gems/exception_notification_rails3-1.2.0/lib/exception_notifier/views/exception_notifier/exception_notification.text.erb (71.8ms)

Sent mail to [email protected] (3072ms)
Date: Mon, 15 Aug 2011 12:13:18 -0400
From: Exception Notifier <[email protected]>
To: [email protected]
Message-ID: <[email protected]>
Subject: [Exception] messages#index (NoMethodError) "undefined method `text?'
 for nil:NilClass"
Mime-Version: 1.0
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

A NoMethodError occurred in messages#index:

  undefined method `text?' for nil:NilClass
  config/initializers/some_debug.rb:6:in `build_relation'

-------------------------------
Request:
-------------------------------

  * URL       : http://www.myblog.dk/messages
  * IP address: filtered
  * Parameters: {"action"=>"index", "controller"=>"messages"}
  * Rails root: /home/atmorell/Dropbox/myblog5

-------------------------------
Session:
-------------------------------

  * session id: nil
  * data: {"_csrf_token"=>"filtered=",
   "user_credentials"=>true,
   "user_credentials_id"=>483}

-------------------------------
Environment:
-------------------------------

  * GATEWAY_INTERFACE                         : CGI/1.2
  * HTTP_ACCEPT                               : text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  * HTTP_ACCEPT_CHARSET                       : ISO-8859-1,utf-8;q=0.7,*;q=0.7
  * HTTP_ACCEPT_ENCODING                      : gzip, deflate
  * HTTP_ACCEPT_LANGUAGE                      : en,da;q=0.7,en-us;q=0.3
  * HTTP_CONNECTION                           : close
  * HTTP_COOKIE                               : __utma=52641074.268317442.1313423882.1313423882.1313423882.1; __utmb=52641074.53.10.1313423882; __utmc=52641074; __utmz=52641074.1313423882.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _myblog_session5=ed471364634fcd3b44c7bb0eae758b14; user_credentials=true%3A%3A483; auth_token=filtered
  * HTTP_HOST                                 : www.myblog.dk
  * HTTP_REFERER                              : http://www.myblog.dk/messages/new
  * HTTP_USER_AGENT                           : Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0
  * HTTP_VERSION                              : HTTP/1.0
  * PATH_INFO                                 : /messages
  * QUERY_STRING                              : 
  * REMOTE_ADDR                               : filtered-ip
  * REQUEST_METHOD                            : GET
  * REQUEST_PATH                              : /messages
  * REQUEST_URI                               : /messages
  * SCRIPT_NAME                               : 
  * SERVER_NAME                               : www.myblog.dk
  * SERVER_PORT                               : 80
  * SERVER_PROTOCOL                           : HTTP/1.1
  * SERVER_SOFTWARE                           : thin 1.2.11 codename Bat-Shit Crazy
  * action_controller.instance                : messages#index
  * action_dispatch.cookies                   : #<ActionDispatch::Cookies::CookieJar:0x00000008766b98>
  * action_dispatch.parameter_filter          : [:password, /RAW_POST_DATA/]
  * action_dispatch.remote_ip                 : filtered-ip
  * action_dispatch.request.content_type      : 
  * action_dispatch.request.formats           : [text/html]
  * action_dispatch.request.parameters        : {"action"=>"index", "controller"=>"messages"}
  * action_dispatch.request.path_parameters   : {:action=>"index", :controller=>"messages"}
  * action_dispatch.request.query_parameters  : {}
  * action_dispatch.request.request_parameters: {}
  * action_dispatch.routes                    : #<ActionDispatch::Routing::RouteSet:0x00000002eaf658>
  * action_dispatch.secret_token              : 93479c2e63bdb766a51f18397345cdc9a8b22ee009334171207f6b0bc2e71105d1f849de46e34965febc3b178cea662e89986e73d8922ec4915c44dca6ae4000
  * action_dispatch.show_exceptions           : true
  * async.callback                            : #<Method: Thin::Connection#post_process>
  * async.close                               : #<EventMachine::DefaultDeferrable:0x000000087809a8>
  * exception_notifier.options                : {:email_prefix=>"[Exception] ", :sender_address=>"\"Exception Notifier\" <[email protected]>", :exception_recipients=>["[email protected]"], :ignore_exceptions=>[ActiveRecord::RecordNotFound, AbstractController::ActionNotFound, ActionController::RoutingError]}
  * rack-cache.allow_reload                   : false
  * rack-cache.allow_revalidate               : false
  * rack-cache.cache_key                      : Rack::Cache::Key
  * rack-cache.default_ttl                    : 0
  * rack-cache.entitystore                    : rails:/
  * rack-cache.metastore                      : rails:/
  * rack-cache.private_headers                : ["Authorization", "Cookie"]
  * rack-cache.storage                        : #<Rack::Cache::Storage:0x000000029e9b50>
  * rack-cache.verbose                        : true
  * rack.errors                               : #<IO:0x00000000c27860>
  * rack.input                                : #<StringIO:0x00000008784c10>
  * rack.multiprocess                         : false
  * rack.multithread                          : false
  * rack.request.cookie_hash                  : {"__utma"=>"52641074.268317442.1313423882.1313423882.1313423882.1", "__utmb"=>"52641074.53.10.1313423882", "__utmc"=>"52641074", "__utmz"=>"52641074.1313423882.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)", "_myblog_session5"=>"ed471364634fcd3b44c7bb0eae758b14", "user_credentials"=>"true::483", "auth_token"=>"filtered"}
  * rack.request.cookie_string                : __utma=52641074.268317442.1313423882.1313423882.1313423882.1; __utmb=52641074.53.10.1313423882; __utmc=52641074; __utmz=52641074.1313423882.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _myblog_session5=ed471364634fcd3b44c7bb0eae758b14; user_credentials=true%3A%3A483; auth_token=filtered
  * rack.request.query_hash                   : {}
  * rack.request.query_string                 : 
  * rack.run_once                             : false
  * rack.session                              : {"_csrf_token"=>"jlK/filtered=", "user_credentials"=>true, "user_credentials_id"=>483}
  * rack.session.options                      : {:key=>"_myblog_session5", :path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :id=>"ed471364634fcd3b44c7bb0eae758b14"}
  * rack.session.record                       : #<ActiveRecord::SessionStore::Session:0x000000087762f0>
  * rack.url_scheme                           : http
  * rack.version                              : [1, 0]

  * Process: 1938
  * Server : li267-196

-------------------------------
Backtrace:
-------------------------------

  config/initializers/some_debug.rb:6:in `build_relation'
  activerecord (3.1.0.rc5) lib/active_record/validations/uniqueness.rb:25:in `validate_each'
  activemodel (3.1.0.rc5) lib/active_model/validator.rb:153:in `block in validate'
  activemodel (3.1.0.rc5) lib/active_model/validator.rb:150:in `each'
  activemodel (3.1.0.rc5) lib/active_model/validator.rb:150:in `validate'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:302:in `_callback_before_483'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:622:in `_run_validate_callbacks'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:81:in `run_callbacks'
  activemodel (3.1.0.rc5) lib/active_model/validations.rb:212:in `run_validations!'
  activemodel (3.1.0.rc5) lib/active_model/validations/callbacks.rb:53:in `block in run_validations!'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:401:in `_run_validation_callbacks'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:81:in `run_callbacks'
  activemodel (3.1.0.rc5) lib/active_model/validations/callbacks.rb:53:in `run_validations!'
  activemodel (3.1.0.rc5) lib/active_model/validations.rb:179:in `valid?'
  activerecord (3.1.0.rc5) lib/active_record/validations.rb:69:in `valid?'
  activerecord (3.1.0.rc5) lib/active_record/validations.rb:77:in `perform_validations'
  activerecord (3.1.0.rc5) lib/active_record/validations.rb:50:in `save'
  activerecord (3.1.0.rc5) lib/active_record/attribute_methods/dirty.rb:22:in `save'
  activerecord (3.1.0.rc5) lib/active_record/transactions.rb:241:in `block (2 levels) in save'
  activerecord (3.1.0.rc5) lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
  activerecord (3.1.0.rc5) lib/active_record/connection_adapters/abstract/database_statements.rb:183:in `transaction'
  activerecord (3.1.0.rc5) lib/active_record/transactions.rb:208:in `transaction'
  activerecord (3.1.0.rc5) lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
  activerecord (3.1.0.rc5) lib/active_record/transactions.rb:241:in `block in save'
  activerecord (3.1.0.rc5) lib/active_record/transactions.rb:252:in `rollback_active_record_state!'
  activerecord (3.1.0.rc5) lib/active_record/transactions.rb:240:in `save'
  app/controllers/application_controller.rb:18:in `system'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:430:in `_run__163591495713425608__process_action__3187008165500041637__callbacks'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:386:in `_run_process_action_callbacks'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (3.1.0.rc5) lib/abstract_controller/callbacks.rb:17:in `process_action'
  actionpack (3.1.0.rc5) lib/action_controller/metal/rescue.rb:17:in `process_action'
  actionpack (3.1.0.rc5) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
  activesupport (3.1.0.rc5) lib/active_support/notifications.rb:55:in `block in instrument'
  activesupport (3.1.0.rc5) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
  activesupport (3.1.0.rc5) lib/active_support/notifications.rb:55:in `instrument'
  actionpack (3.1.0.rc5) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
  actionpack (3.1.0.rc5) lib/action_controller/metal/params_wrapper.rb:202:in `process_action'
  activerecord (3.1.0.rc5) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (3.1.0.rc5) lib/abstract_controller/base.rb:121:in `process'
  actionpack (3.1.0.rc5) lib/abstract_controller/rendering.rb:45:in `process'
  actionpack (3.1.0.rc5) lib/action_controller/metal.rb:193:in `dispatch'
  actionpack (3.1.0.rc5) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
  actionpack (3.1.0.rc5) lib/action_controller/metal.rb:236:in `block in action'
  actionpack (3.1.0.rc5) lib/action_dispatch/routing/route_set.rb:65:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/routing/route_set.rb:65:in `dispatch'
  actionpack (3.1.0.rc5) lib/action_dispatch/routing/route_set.rb:29:in `call'
  rack-mount (0.8.2) lib/rack/mount/route_set.rb:152:in `block in call'
  rack-mount (0.8.2) lib/rack/mount/code_generation.rb:96:in `block in recognize'
  rack-mount (0.8.2) lib/rack/mount/code_generation.rb:68:in `optimized_each'
  rack-mount (0.8.2) lib/rack/mount/code_generation.rb:95:in `recognize'
  rack-mount (0.8.2) lib/rack/mount/route_set.rb:141:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/routing/route_set.rb:531:in `call'
  oa-core (0.2.6) lib/omniauth/strategy.rb:44:in `call!'
  oa-core (0.2.6) lib/omniauth/strategy.rb:30:in `call'
  oa-core (0.2.6) lib/omniauth/strategy.rb:44:in `call!'
  oa-core (0.2.6) lib/omniauth/strategy.rb:30:in `call'
  oa-core (0.2.6) lib/omniauth/strategy.rb:44:in `call!'
  oa-core (0.2.6) lib/omniauth/strategy.rb:30:in `call'
  oa-core (0.2.6) lib/omniauth/builder.rb:30:in `call'
  exception_notification_rails3 (1.2.0) lib/exception_notifier.rb:34:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
  rack (1.3.2) lib/rack/etag.rb:23:in `call'
  rack (1.3.2) lib/rack/conditionalget.rb:25:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/head.rb:14:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/flash.rb:243:in `call'
  rack (1.3.2) lib/rack/session/abstract/id.rb:195:in `context'
  rack (1.3.2) lib/rack/session/abstract/id.rb:190:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/cookies.rb:326:in `call'
  activerecord (3.1.0.rc5) lib/active_record/query_cache.rb:62:in `call'
  activerecord (3.1.0.rc5) lib/active_record/connection_adapters/abstract/connection_pool.rb:466:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:392:in `_run_call_callbacks'
  activesupport (3.1.0.rc5) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/callbacks.rb:28:in `call'
  rack (1.3.2) lib/rack/sendfile.rb:101:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/remote_ip.rb:48:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/show_exceptions.rb:47:in `call'
  railties (3.1.0.rc5) lib/rails/rack/logger.rb:13:in `call'
  rack (1.3.2) lib/rack/methodoverride.rb:24:in `call'
  rack (1.3.2) lib/rack/runtime.rb:17:in `call'
  activesupport (3.1.0.rc5) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
  rack (1.3.2) lib/rack/lock.rb:15:in `call'
  actionpack (3.1.0.rc5) lib/action_dispatch/middleware/static.rb:53:in `call'
  rack-cache (1.0.2) lib/rack/cache/context.rb:132:in `forward'
  rack-cache (1.0.2) lib/rack/cache/context.rb:243:in `fetch'
  rack-cache (1.0.2) lib/rack/cache/context.rb:181:in `lookup'
  rack-cache (1.0.2) lib/rack/cache/context.rb:65:in `call!'
  rack-cache (1.0.2) lib/rack/cache/context.rb:50:in `call'
  railties (3.1.0.rc5) lib/rails/engine.rb:455:in `call'
  railties (3.1.0.rc5) lib/rails/railtie/configurable.rb:30:in `method_missing'
  thin (1.2.11) lib/thin/connection.rb:84:in `block in pre_process'
  thin (1.2.11) lib/thin/connection.rb:82:in `catch'
  thin (1.2.11) lib/thin/connection.rb:82:in `pre_process'
  thin (1.2.11) lib/thin/connection.rb:57:in `process'
  thin (1.2.11) lib/thin/connection.rb:42:in `receive_data'
  eventmachine (0.12.10) lib/eventmachine.rb:256:in `run_machine'
  eventmachine (0.12.10) lib/eventmachine.rb:256:in `run'
  thin (1.2.11) lib/thin/backends/base.rb:61:in `start'
  thin (1.2.11) lib/thin/server.rb:159:in `start'
  thin (1.2.11) lib/thin/controllers/controller.rb:86:in `start'
  thin (1.2.11) lib/thin/runner.rb:185:in `run_command'
  thin (1.2.11) lib/thin/runner.rb:151:in `run!'
  thin (1.2.11) bin/thin:6:in `<top (required)>'
  /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/bin/thin:19:in `load'
  /usr/local/rvm/gems/ruby-1.9.2-p290-dev@myblog5/bin/thin:19:in `<main>'



NoMethodError (undefined method `text?' for nil:NilClass):
  config/initializers/some_debug.rb:6:in `build_relation'
  app/controllers/application_controller.rb:18:in `system'

User.rb

    # -*- encoding : utf-8 -*-
class User < ActiveRecord::Base
  attr_accessible :username, :email, :birthday, :firstname, :lastname, :phone, :website, :profile, :avatar, :password, :avatar_cache, :name, :last_seen, :arts_count, :cheapest, :most_expensive #, :email_verified, :crypted_password, :password_salt, :administrator, :id

  # Virtual attributes
  attr_accessor :password, :password_confirmation

  belongs_to :cheapest, :class_name => "Art", :foreign_key => :cheapest
  belongs_to :most_expensive, :class_name => "Art", :foreign_key => :most_expensive

  has_many :blogs, :dependent => :destroy
  has_many :arts, :dependent => :destroy
  has_many :authentications, :dependent => :destroy
  has_friendly_id :username, :use_slug => true 
  has_many :comments, :as => :commentable, :validate => :false

  mount_uploader :avatar, AvatarUploader  
  before_save :encrypt_password
  before_create { generate_token(:auth_token) }
  after_create { send_account_activation }

  validates_uniqueness_of :username, :email
  validates_presence_of :username, :email
  validate :password_length_without_authentications
  validates_format_of :username, :with => /^[-a-z\d_]+$/, :message => "kun små bogstaver, tal og bindestreger. f.eks. galleri-toke"
  validates_length_of :username, :maximum=>30, :message=>"Dit brugernavn må max være 30 karakter."
  validates_length_of :username, :minimum=>3, :message=>"Dit brugernavn skal minimum være 3 karakter."
  validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i

  default_scope :order => "last_seen desc" #, :conditions => "username NOT LIKE 'robot'"
  scope :with_arts, where("arts_count > 0")
...

Each time the user refreshed the page I update the last_seen column and save the logged_in user. For some reason the saving breaks. I have not been able to reproduce this on my development server.

like image 563
atmorell Avatar asked Aug 08 '11 17:08

atmorell


3 Answers

solution: if your validation line says this ...

validates :tag, :uniqueness => {:scope => :post}

... then change it to reference column name instead of association name like this ...

validates :tag_id, :uniqueness => {:scope => :post_id}

I recreated your failure in rails 3.1.0.rc5 and produced the same error message. The short explanation is that the code in the build_relation method is expecting a literal column name, not an association name.

For a more thorough explanation including code snippets see my blog at http://thetenelements.blogspot.com/2011/08/undefined-method-text-for-nilnilclass.html

like image 167
Luke Griffiths Avatar answered Nov 06 '22 16:11

Luke Griffiths


Luke Griffiths has given you most of the answer. The essence is this, you have a uniqueness validation somewhere. According to your comment the only one you have is this one:

validates_uniqueness_of :body, :scope => [:commentable_id, :user_id], :message => "Duplicate record.."

If that is the case, then we must assume it is the culprit (it would help to know which model that validation was, also would help to see the relevant parts of your User model code as well as the relevant parts of the model where that validation is found). But no matter we can still have a guess as to what your problem is.

The issue you're getting occurs in the build_relation method in the rails source rails/activerecord/lib/active_record/validations/uniqueness.rb on line 57. This method is trying to look up a column based on the name of an attribute and then tries to see if it is text. The errors occurs because the attribute it is getting does not seem to be in the column hash to the value of column is nil.

It has been suggested in another answer that you output some debugging info in the build_relation method. This is not a bad idea (all you really need to know is what are the keys in the columns_hash and what the the value of the attribute that is passed in to the method), here is how you do that. Create an initializer in config/initializers, lets call it debugging_stuff.rb. Inside there you can put the following:

ActiveRecord::Validations::UniquenessValidator.class_eval do
  def build_relation(klass, table, attribute, value) #:nodoc:
    puts "************** #{attribute}"
    puts "************** #{klass.columns_hash.keys.inspect}"
    column = klass.columns_hash[attribute.to_s]
    value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text?

    if !options[:case_sensitive] && value && column.text?
      # will use SQL LOWER function before comparison
      relation = table[attribute].lower.eq(table.lower(value))
    else
      value    = klass.connection.case_sensitive_modifier(value)
      relation = table[attribute].eq(value)
    end

    relation
  end
end

What we're looking for is to find out when none of the keys in the columns_hash match the attribute value that is passed.

If that uniqueness validator above is really the only one you have, it should be one of the three attributes in there (:body, :commentable_id, :user_id). My money is on :body but I could be wrong. Does :body refer to another model. If it does perhaps it should be :body_id as Luke Griffiths indicated. If you still can't find the issue, you would need to provide more debugging info like, full stack trace and code for the relevant models (User etc.) - we've gone as far as we can with the information we have.

like image 26
skorks Avatar answered Nov 06 '22 16:11

skorks


If you're still unable to resolve this add some debugging to the build_relation method yourself. Just let it write some data to the console to see where it actually goes wrong.

Change

def build_relation(klass, table, attribute, value) #:nodoc:
  column = klass.columns_hash[attribute.to_s]
  value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text?

to

def build_relation(klass, table, attribute, value) #:nodoc:
  puts "build_relation klass: #{klass.inspect}"
  puts "build_relation table: #{table.inspect}"
  puts "build_relation attribute: #{attribute.inspect}"
  puts "build_relation value: #{value.inspect}"
  puts "build_relation columns_hash: #{klass.columns_hash.inspect}"
  column = klass.columns_hash[attribute.to_s]
  value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text?

Then you'll at least know what attribute is causing this. Now hope it's the same everytime it goes wrong...

like image 2
Rene van Lieshout Avatar answered Nov 06 '22 16:11

Rene van Lieshout