“undefined方法`scan'for nil:NilClass”用于多态ActiveRecord关联:inverse_of

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“undefined方法`scan'for nil:NilClass”用于多态ActiveRecord关联:inverse_of相关的知识,希望对你有一定的参考价值。

我有一个“has_many”关系的问题,我从ActiveRecord中得到一个随机异常:

product = Product.create!(valid_attributes)
product.prices 
# throws:
NoMethodError:
       undefined method `scan' for nil:NilClass

这似乎与“inverse_of”有关,但我显然做了一些ActiveRecord没想到的东西,但是不能为一个好的错误而烦恼。最好的猜测是它与我的名为“列”的列有关(虽然这不在黑名单AFAIK上)。我正在使用PostgreSQL。编辑:尝试将列重命名为“column_name”和“parent_column”,但没有修复它。会尝试其他一些事情。

以下是相关的型号代码和架构:

class Price < ApplicationRecord
  belongs_to :parent, polymorphic: true
end

class Product < ApplicationRecord
  has_many :prices, as: :parent, inverse_of: :parent
end

class CreatePrices < ActiveRecord::Migration[5.2]
  def change
    create_table :prices do |t|
      t.string :parent_type, null: false
      t.bigint :parent_id, null: false
      t.string :column, null: false
      t.decimal :price, null: false, precision: 15, scale: 2
      t.timestamp :effective_date, null: false
    end

    add_index :prices, [:parent_type, :parent_id, :column]
  end
end

完整的堆栈跟踪:

NoMethodError:
       undefined method `scan' for nil:NilClass
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/inheritance.rb:185:in `compute_type'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/reflection.rb:422:in `compute_class'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/reflection.rb:379:in `klass'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/reflection.rb:234:in `inverse_of'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/reflection.rb:239:in `check_validity_of_inverse!'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/reflection.rb:474:in `check_validity!'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/associations/association.rb:26:in `initialize'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/associations.rb:237:in `new'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/associations.rb:237:in `association'
     # /Users/william/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2.1/lib/active_record/associations/builder/association.rb:108:in `prices'
答案

答案是我以一种我没有意识到的方式违反ActiveRecord的期望,并且应该包括在原始问题中,但不是因为傲慢。我在测试中使用匿名模型。例如:

module Priced
  extend ActiveSupport::Concern

  included do
    has_many :prices, as: :parent, inverse_of: :parent
  end
end

RSpec.describe Priced do
  let(:model_class) {
    Class.new(ActiveRecord::Base).tap do |klass|
      klass.table_name = "products"
      klass.send(:include, Priced)
    end
  end

  it "defines a 'has_many :prices' association" do
    model = model_class.create!
    price = Price.create!(parent: model, price: 100)
    expect(model.prices).to eq([price])
  end
end

这让我可以将ActiveRecord模型与现有表一起使用,但是将它与实际Product模型中的所有逻辑分开。

我之前从未遇到任何关于此设置的问题,因此我多年来一直在愉快地使用它来测试模块。所以mea culpa;如果我把这段代码放在原来的问题中,我可能会在发布之前意识到答案,但我回答我自己的问题,作为对其他“聪明”Ruby编码员的警告。

以上是关于“undefined方法`scan'for nil:NilClass”用于多态ActiveRecord关联:inverse_of的主要内容,如果未能解决你的问题,请参考以下文章