我搜索过Stackoverflow和其他地方,但无法解决此问题。
问题:当尝试通过Rails destroy动作销毁实例变量时,我收到此帖子标题中的错误消息。
相关守则:
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',因为我永远不需要直接访问'describe'连接表。我找到了一个Stackoverflow帖子(该链接逃脱了我),其中建议强制执行级联删除操作要求连接表条目具有唯一标识符。传统的Rails强制执行唯一数据库表记录的方法是默认使用一个名为“id”的主键。我尝试通过删除'CreateDescribes'迁移文件中的'id:false'键/值对来确保实现此建议,并确保schema.rb文件中的'describe'表在重新运行'db:migrate'后反映出来。
不幸的是,这种方法产生了同样的错误。 Rails服务器日志将'CompaniesController''destroy'操作中的以下代码行标识为此错误的来源:
@company.destroy
生成的错误消息是:
undefined method `to_sym' for nil:NilClass Did you mean? to_s
当我创建一个新的'Company'对象并将其相应的记录保存到数据库时,我确认了它的存在,例如,通过交叉检查'params'哈希中的'id'值与'id'字段在数据库表的记录中。
'CompaniesController''create'动作通过has_many通过公司和Metadatum模型之间的关联将一组Metadatum对象与新公司对象相关联。
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对象与公司对象关联时,我才会遇到此错误。
该错误表示在nil类上尝试了destroy操作。当我确认公司对象被销毁时,它不能是零。什么是Rails服务器日志标识为零类?更重要的是,为什么对具有关联Metadatum对象的Company对象的销毁操作不会在相应的“describe”连接表上传播强制级联删除?
答案 0 :(得分:0)
我在别处收到的对这个问题的回应导致了解决方案。首先,我需要添加&#39;依赖:: destroy&#39;约束到&#39; has_many到&#39;公司&#39;中的协会和&#39; Metadatum&#39;模型。
class Company < ApplicationRecord
has_many :describes, dependent: :destroy
has_many :descriptors, through: :describes, source: :metadatum, dependent: :destroy
...
class Metadatum < ApplicationRecord
has_many :describes, dependent: :destroy
has_many :descriptees, through: :describes, source: :company, dependent: :destroy
...
其次,我需要坚持允许&#39; create_table&#39;自动生成“id”的方法首要的关键。因此,关于&#39;描述&#39;在数据库模式中的表中,我实现了以下步骤:
步骤01:删除&#39; id:false&#39;来自适当的迁移文件的约束。
class CreateDescribes < ActiveRecord::Migration[5.0]
def change
# create_table :describes, id: false do |t|
create_table :describes do |t|
t.references :company, foreign_key: true
t.references :metadatum, foreign_key: true
t.timestamps
end
end
end
步骤02:重建生成的数据库,然后重新运行迁移。
rails db:reset
rails db:migrate
警告:&#39; rails db:reset&#39;清除数据库。由于我在数据库中播放了测试数据,我现在并不关心这一点。但是,如果您进一步开发并且“种子”,那么它确实会成为问题。单独的文件不足以重新创建测试状态。
现在,&#39;描述&#39;表格&#39; schema.rb&#39;读得正确:
create_table "describes", 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
在测试应用时,会发生级联删除,并且相应的“#”描述了&#39;表记录已删除。