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.
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
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.
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With