【发布时间】:2017-10-12 18:19:13
【问题描述】:
我搜索过 Stackoverflow 和其他地方,但无法解决这个问题。
问题:当尝试通过 Rails 销毁操作销毁实例变量时,我收到这篇文章标题中的错误消息。
相关代码:
class Company < ApplicationRecord
has_many :describes, dependent: :destroy
has_many :descriptors, through: :describes, source: :metadatum
end
class Metadatum < ApplicationRecord
has_many :describes, dependent: :destroy
has_many :descriptees, through: :describes, source: :company
...
end
class Describe < ApplicationRecord
belongs_to :company
belongs_to :metadatum
end
class CompaniesController < ApplicationController
...
def destroy
@company = Company.find(params[:id])
@company.destroy
redirect_to companies_url
end
...
end
ActiveRecord::Schema.define(version: <some version #) do
create_table "companies", force: :cascade do |t|
t.string "name"
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["name"], name: "index_companies_on_name", unique: true
end
create_table "describes", id: false, force: :cascade do |t|
t.integer "company_id"
t.integer "metadatum_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["company_id"], name: "index_describes_on_company_id"
t.index ["metadatum_id"], name: "index_describes_on_metadatum_id"
end
create_table "metadata", force: :cascade do |t|
t.string "name"
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["name"], name: "index_metadata_on_name", unique: true
end
end
class CreateCompanies < ActiveRecord::Migration[5.0]
def change
create_table :companies do |t|
t.string :name
t.string :description
t.timestamps
end
add_index :companies, :name, unique: true
end
end
class CreateMetadata < ActiveRecord::Migration[5.0]
def change
create_table :metadata do |t|
t.string :name
t.string :description
t.timestamps
end
add_index :metadata, :name, unique: true
end
end
class CreateDescribes < ActiveRecord::Migration[5.0]
def change
create_table :describes, id: false do |t|
t.references :company, foreign_key: true
t.references :metadatum, foreign_key: true
t.timestamps
end
end
end
“CreateDescribes”迁移文件将“create_table”“id”选项设置为“false”,因为我永远不需要直接访问“describes”连接表。我找到了一个 Stackoverflow 帖子(链接让我无法理解),其中建议执行级联删除操作要求连接表条目具有唯一标识符。传统的 Rails 强制唯一数据库表记录的方法是拥有一个默认名为“id”的主键。我尝试通过删除“CreateDescribes”迁移文件中的“id: false”键/值对并确保 schema.rb 文件中的“describes”表在重新运行“db:migrate”后反映这一点来实施此建议。
不幸的是,这种方法产生了同样的错误。 Rails 服务器日志将 'CompaniesController' 'destroy' 操作中的以下代码行标识为此错误的来源:
@company.destroy
生成的错误信息是:
undefined method `to_sym' for nil:NilClass Did you mean? to_s
当我创建一个新的 'Company' 对象并将其对应的记录保存到数据库时,我确认了它的存在,例如,通过交叉检查 'params' 哈希中的 'id' 值与 'id' 字段在数据库表的记录中。
“CompaniesController”“创建”操作通过公司和元数据模型之间的关联,通过 has_many 将一组元数据对象关联到新的公司对象。
def create
@company = Company.new(company_attributes)
params[:metadata][:ids].each do |m|
if !m.empty?
@company.descriptors << Metadatum.find(m)
end
end
if @company.save
...
end
我确认关联已被捕获。
有趣的是,当我没有将 Metadatum 对象与新的 Company 对象关联时,我稍后能够成功地销毁 Company 对象。只有当我将 Metadatum 对象关联到 Company 对象时,我以后才会遇到此错误。
该错误表明在 nil 类上尝试了销毁操作。当我确认被销毁的公司对象存在时,它不能为零。识别为 nil 类的 Rails Server 日志是什么?更重要的是,为什么对具有关联 Metadatum 对象的 Company 对象的破坏操作不会在适当的“描述”连接表上传播强制级联删除?
【问题讨论】:
标签: ruby-on-rails ruby