Note that there are some explanatory texts on larger screens.

plurals
  1. PORails 3 serialized attribute validation error: undefined method `read_attribute_for_validation' for nil:NilClass
    text
    copied!<p>When trying to use a serialized attribute (with a defined class) Rails is happy until after the object is saved. I have validations both in my ActiveRecord model and the serialized object (which uses ActiveModel::Validations). As part of my validations, the parent model checks to make sure the serialized object is <code>valid?</code>. I believe this is the heart of the issue, but I'm (a) not sure <em>why</em> it's causing a problem or (b) the best way to fix it.</p> <p>I've simplified the problem to a minimal rails project:</p> <h2>Code</h2> <p>Creating a fresh rails project (version 3.2.6) and creating an <code>A</code> model with <code>rails g model a data:text</code> I define:</p> <p><strong>app/models/a.rb</strong></p> <pre><code>class A &lt; ActiveRecord::Base attr_accessible :data serialize :data, B validate :custom def custom errors.add :data, "whoopsies!" unless data.valid? end end </code></pre> <p><strong>app/models/b.rb</strong></p> <pre><code>class B include ActiveModel::Validations attr_accessor :foo validates_presence_of :foo end </code></pre> <p><strong>test/unit/a_test.rb</strong></p> <pre><code>require 'test_helper' class ATest &lt; ActiveSupport::TestCase test "weird failure" do a = A.new b = B.new b.foo = 'bar' a.data = b assert a.valid? assert b.valid? assert a.save assert a.valid? # -&gt; throws exception end end </code></pre> <h2>Exception</h2> <p>Running this test throws the following exception:</p> <pre><code>NoMethodError: undefined method `read_attribute_for_validation' for nil:NilClass /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/errors.rb:254:in `block in add_on_blank' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/errors.rb:253:in `each' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/errors.rb:253:in `add_on_blank' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/validations/presence.rb:8:in `validate' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:310:in `_callback_before_7' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:407:in `_run__2107971919899649095__validate__2662006763039653414__callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:405:in `__run_callback' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:385:in `_run_validate_callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:81:in `run_callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/validations.rb:226:in `run_validations!' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/validations.rb:193:in `valid?' /Users/gbelote/tmp/serialize-fail/app/models/a.rb:8:in `custom' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:407:in `_run__3204678033069886840__validate__2662006763039653414__callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:405:in `__run_callback' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:385:in `_run_validate_callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:81:in `run_callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/validations.rb:226:in `run_validations!' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/validations/callbacks.rb:53:in `block in run_validations!' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:403:in `_run__3204678033069886840__validation__2662006763039653414__callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:405:in `__run_callback' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:385:in `_run_validation_callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activesupport-3.2.6/lib/active_support/callbacks.rb:81:in `run_callbacks' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/validations/callbacks.rb:53:in `run_validations!' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activemodel-3.2.6/lib/active_model/validations.rb:193:in `valid?' /Users/gbelote/.rvm/gems/ruby-1.9.2-p290@serialize-fail/gems/activerecord-3.2.6/lib/active_record/validations.rb:69:in `valid?' /Users/gbelote/tmp/serialize-fail/test/unit/a_test.rb:14:in `block in &lt;class:ATest&gt;' </code></pre> <h2>Another clue</h2> <p>When running <code>puts a.data.inspect</code> I get differing results before and after the <code>a.save</code>:</p> <pre><code>before: #&lt;B:0x0000010327e710 @foo="bar", @validation_context=nil, @errors=#&lt;ActiveModel::Errors:0x0000010321b7a0 @base=#&lt;B:0x0000010327e710 ...&gt;, @messages={}&gt;&gt; after: #&lt;B:0x00000103197158 @foo="bar", @validation_context=nil, @errors=#&lt;ActiveModel::Errors:0x000001031965f0 @base=nil, @messages={}&gt;&gt; </code></pre> <p>So <code>@base</code> within <code>@errors</code> is nil, and that's the <code>nil</code> referred to in the exception <code>undefined method</code>read_attribute_for_validation' for nil:NilClass`.</p> <hr> <p>Anyone know what's going on? Is this a Rails bug? Am I doing something wrong?</p> <p>Thanks!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload