【问题标题】:ActiveRecord raises `UndefinedColumn` for namespaced modelsActiveRecord 为命名空间模型引发“UndefinedColumn”
【发布时间】:2020-01-10 15:14:36
【问题描述】:

我目前正在为一家在线商店编写一个新的基础,但我被选项类型和值卡住了。

我正在尝试为现有的OptionType 创建一个新的OptionValue。两个模型都在 Product 命名空间(它本身就是一个模型。

现在我看到 Rails 生成了错误的 ARel:

PG::UndefinedColumn: ERROR: column product_option_values.option_type_id does not exist LINE 1: ...es" WHERE "product_option_values"."name" = $1 AND "product_o... ^ : SELECT 1 AS one FROM "product_option_values" WHERE "product_option_values"."name" = $1 AND "product_option_values"."option_type_id" IS NULL LIMIT $2

但列不应该是product_option_values.option_type_id,而应该是product_option_values.product_option_type_id


以下是模型:

product/option_type.rb:

class Product::OptionType < ApplicationRecord
  translates :presentation, :description

  belongs_to :product

  validates_presence_of :name, :presentation, :description

  has_many :product_variants, through: :product, source: :variants_including_master

  has_many :product_option_values, class_name: 'Product::OptionValue', foreign_key: :product_option_type_id, inverse_of: :product_option_type

  accepts_nested_attributes_for :product_option_values
end

product/option_value.rb:

class Product::OptionValue < ApplicationRecord
  translates :presentation, :description

  validates :name, presence: true, uniqueness: { scope: :option_type_id }
  validates :presentation, presence: true
  validates :description, presence: true

  belongs_to :product_option_type, class_name: 'Product::OptionType', inverse_of: :product_option_values, foreign_key: :product_option_type_id

  # has_many :option_values_variants, dependent: :destroy, class_name: 'Product::OptionValuesVariant', foreign_key: :product_option_value_id
  # has_many :variants, through: :option_values_variants, source: :product_variant

  after_save :touch, if: :saved_changes?
  after_touch :touch_all_variants

  # Updates the updated_at column on all the variants associated with this
  # option value.
  def touch_all_variants
    variants.find_each(&:touch)
  end
end

【问题讨论】:

  • 我实际上是在扫描这里的源代码时看到的,我正在根据错误的列验证唯一性。将在此处反映并返回答案。
  • 哪个 Rails 版本?

标签: ruby-on-rails ruby postgresql activerecord


【解决方案1】:

它适用于我(使用 Rails 6):

$ rails g model product/option_type

$ rails g model product/option_value product_option_type:references

models/product/option_type.rb

class Product::OptionType < ApplicationRecord
  has_many :product_option_values, class_name: 'Product::OptionValue', foreign_key: :product_option_type_id, inverse_of: :product_option_type
end

models/product/option_value.rb

class Product::OptionValue < ApplicationRecord
   belongs_to :product_option_type, class_name: 'Product::OptionType', inverse_of: :product_option_values, foreign_key: :product_option_type_id
end

models/product.rb

module Product
  def self.table_name_prefix
    'product_'
  end
end

打开 Rails 控制台:

$ rails c

结果:

irb(main):004:0> p_option_type.product_option_values
=> #<ActiveRecord::Associations::CollectionProxy []>
irb(main):008:0> p_option_type.product_option_values += [Product::OptionValue.new]
=> [#<Product::OptionValue id: nil, product_option_type_id: nil, created_at: nil, updated_at: nil>]
irb(main):009:0> p_option_type.save!
   (0.2ms)  begin transaction
  Product::OptionType Create (1.1ms)  INSERT INTO "product_option_types" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", "2020-01-10 21:20:12.956558"], ["updated_at", "2020-01-10 21:20:12.956558"]]
  Product::OptionValue Create (0.8ms)  INSERT INTO "product_option_values" ("product_option_type_id", "created_at", "updated_at") VALUES (?, ?, ?)  [["product_option_type_id", 1], ["created_at", "2020-01-10 21:20:12.963793"], ["updated_at", "2020-01-10 21:20:12.963793"]]
   (16.7ms)  commit transaction
=> true

我的数据库/schema.rb:

ActiveRecord::Schema.define(version: 2020_01_10_211433) do

  create_table "product_option_types", force: :cascade do |t| 
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end 

  create_table "product_option_values", force: :cascade do |t| 
    t.integer "product_option_type_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["product_option_type_id"], name: "index_product_option_values_on_product_option_type_id"
  end 

  add_foreign_key "product_option_values", "product_option_types"
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多