1

シリアル化された属性を (定義済みのクラスで) 使用しようとすると、Rails はオブジェクトが保存されるまで満足します。ActiveRecord モデルとシリアル化されたオブジェクト (ActiveModel::Validations を使用) の両方に検証があります。私の検証の一環として、親モデルはシリアル化されたオブジェクトがvalid?. これが問題の核心だと思いますが、(a)なぜ問題を引き起こしているのか、または (b) 問題を修正する最善の方法がわからない.

問題を最小限の Rails プロジェクトに単純化しました。

コード

新しい Rails プロジェクト (バージョン 3.2.6) を作成し、I defineでAモデルを作成します。rails g model a data:text

アプリ/モデル/a.rb

class A < ActiveRecord::Base
  attr_accessible :data
  serialize :data, B

  validate :custom

  def custom
    errors.add :data, "whoopsies!" unless data.valid?
  end
end

アプリ/モデル/b.rb

class B
  include ActiveModel::Validations
  attr_accessor :foo
  validates_presence_of :foo
end

テスト/ユニット/a_test.rb

require 'test_helper'

class ATest < 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? # -> throws exception
  end
end

例外

このテストを実行すると、次の例外がスローされます。

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 <class:ATest>'

もう一つの手がかり

実行すると、次puts a.data.inspectの前後で異なる結果が得られますa.save

before: #<B:0x0000010327e710 @foo="bar", @validation_context=nil, @errors=#<ActiveModel::Errors:0x0000010321b7a0 @base=#<B:0x0000010327e710 ...>, @messages={}>>
after:  #<B:0x00000103197158 @foo="bar", @validation_context=nil, @errors=#<ActiveModel::Errors:0x000001031965f0 @base=nil, @messages={}>>

そのため、nil は nil であり、それはnil:NilClass` の例外 read_attribute_for_validation@baseで参照されます。@errorsnilundefined method


何が起こっているか知っている人はいますか?これはRailsのバグですか? 私は何か間違ったことをしていますか?

ありがとう!

4

1 に答える 1

0

ruby 1.9.3-p194 にアップグレードすると問題が解決しました。以前は 1.9.2-p290 を使用していました。関連する github の問題: https://github.com/rails/rails/issues/6889

于 2012-06-28T19:09:54.047 に答える