Why am I getting a "NameError: uninitialized constant" using has_many :through in Ruby
Why am I getting a "NameError: uninitialized constant" using has_many :through in Ruby
我是 Ruby 的初学者,一直在尝试使用 has_many :through 关联将 3 个模型连接在一起。首先,我有一个 Person 模型、一个 Subscription 模型和一个 SubscriptionDetail 模型。
基本上,一个人可以通过订阅详情拥有多个订阅,同样,一个订阅可以通过订阅详情拥有多人。我使用的模型是:
在person.rb中:
class Person < ActiveRecord::Base
belongs_to :institution
has_many :subscription_details
has_many :subscriptions, through: :subscription_details
end
在subscription.rb中:
class Subscription < ActiveRecord::Base
belongs_to :product
has_many :subscription_details
has_many :people, through: :subscription_details
end
在subscription_detail.rb中:
class SubscriptionDetail < ActiveRecord::Base
belongs_to :person
belongs_to :subscription
end
相关的迁移是:
class CreatePeopleTable < ActiveRecord::Migration[5.0]
def change
create_table :people do |t|
t.string :name, null:false
t.string :email, null:false
t.belongs_to :institution, index: true
t.boolean :removed, :default => false
t.timestamps
end
end
end
class CreateSubscriptionsTable < ActiveRecord::Migration[5.0]
def change
create_table :subscriptions do |t|
t.string :name, null:false
t.belongs_to :product, index: true
end
end
end
class CreateSubscriptionDetailsTable < ActiveRecord::Migration[5.0]
def change
create_table :subscription_details do |t|
t.belongs_to :subscription, index:true
t.belongs_to :person, index:true
t.boolean :trial, :default => true
t.string :mailing_preference, :default => "Cc"
t.datetime :trial_start
t.datetime :trial_end
end
end
end
创建一个人时,我设置了一个表单,通过同一个表单(使用复选框)向该人添加多个订阅 - 我将这些收集到一个名为 "subscriptions" 的数组中。订阅是使用另一种形式预先创建的。我使用以下代码(对 has_many through additional attributes 中的内容稍作修改)来创建此人:
info = {
name: name,
email: email,
institution_id: institution.id
}
person = Person.create(info)
person.save
subscriptions.each do |each_subscription|
person.subscription_details.create(
:subscription => each_subscription,
:trial_start => trial_start,
:trial_end => trial_end
)
end
但我总是得到以下错误:
NameError at /institutions/1/add_person
uninitialized constant Person::SubscriptionDetail
更新: 它在 person.subscription_details.create(
行抛出异常。
当控制台中 运行 相同的代码时,我得到 NameError: uninitialized constant Person::SubscriptionDetail from C:/Ruby22-x64/lib/ruby/gems/2.2.0/gems/activerecord-5.0.1/lib/active_record/inheritance.rb:152:in 'compute_type'
更新 2: 我应该注意,在检查 Postgres 中的数据库时,它在 people table 中创建了人,但没有在中创建相关的订阅详细信息subscription_detailstable
我检查了多个模型文件、关联,甚至检查了拼写错误,尝试在模型中使用 :class_name 属性,我在没有 person.save
的情况下尝试过,最后 2小时谷歌搜索这个,但我无法弄清楚为什么这是失败的。
更新
窗体视图 (people/new.erb)
<form action="/institutions/<%= @institution.id %>/add_person" method="post">
<table>
<tr>
<th><label for="name">Name</label></th>
<td><input type="text" id="name" name="person[name]" placeholder="Name"></td>
</tr>
<tr>
<th><label for="email">E-mail</label></th>
<td><input type="text" id="email" name="person[email]" placeholder="E-mail"></td>
</tr>
<tr>
<th><label for="institution">Institution</label></th>
<td><input type="text" id="institution" name="person[institution]" placeholder="<%= @institution.name %>" value="<%= @institution.name %>"></td>
</tr>
<tr>
<th>Subscriptions</th>
<td>
<% @subscriptions.each do |subscription| %>
<label><input type="checkbox" name="person[subscriptions][]" value="<%= subscription.id %>"><%= subscription.name %></label><br>
<% end %>
</td>
</tr>
<tr>
<th><label for="trial-start">Trial-start Date</label></th>
<td>
<input type="text" id="trial-start" name="person[trial][start]" placeholder="DD-MM-YYYY">
</td>
</tr>
<tr>
<th><label for="trial-end">Trial-end Date</label></th>
<td>
<input type="text" id="trial-end" name="person[trial][end]" placeholder="DD-MM-YYYY">
</td>
</tr>
</table>
<input class="button" type="submit" value="Add Person">
</form>
在 Rails 4.2 中,您的 SubscriptionDetails 迁移看起来像这样:
class CreateSubscriptionDetailsTable < ActiveRecord::Migration
def change
create_table :subscription_details do |t|
t.belongs_to :subscription, index: true, foreign_key: true, null: false
t.belongs_to :person, index: true, foreign_key: true, null: false
t.boolean :trial, default: true
t.string :mailing_preference, default: "Cc"
t.datetime :trial_start
t.datetime :trial_end
end
add_index :subscription_details, ["subscription_id", "person_id"], unique: true
end
end
不确定 5.0 中进行了哪些更改,但可能值得添加索引和外键约束以查看是否可以解决问题。当然,您需要回滚迁移并再次 运行 它们。
嗯,现在我觉得我真的很愚蠢。我向所有可能在这里浪费时间的人道歉,并真诚地感谢你们付出的所有努力。
但这是我的错。我忘了检查我的 config.ru
文件。我通过将以下行添加到我的 config.ru 文件中解决了这个问题:
require './models/subscription_detail'
这就是为什么我的应用程序看不到 SubscriptionDetail 模型的原因。我只是回答这个问题,以防它能帮助任何犯同样错误的人。
再次感谢所有answered/commented的人。
我是 Ruby 的初学者,一直在尝试使用 has_many :through 关联将 3 个模型连接在一起。首先,我有一个 Person 模型、一个 Subscription 模型和一个 SubscriptionDetail 模型。
基本上,一个人可以通过订阅详情拥有多个订阅,同样,一个订阅可以通过订阅详情拥有多人。我使用的模型是:
在person.rb中:
class Person < ActiveRecord::Base
belongs_to :institution
has_many :subscription_details
has_many :subscriptions, through: :subscription_details
end
在subscription.rb中:
class Subscription < ActiveRecord::Base
belongs_to :product
has_many :subscription_details
has_many :people, through: :subscription_details
end
在subscription_detail.rb中:
class SubscriptionDetail < ActiveRecord::Base
belongs_to :person
belongs_to :subscription
end
相关的迁移是:
class CreatePeopleTable < ActiveRecord::Migration[5.0]
def change
create_table :people do |t|
t.string :name, null:false
t.string :email, null:false
t.belongs_to :institution, index: true
t.boolean :removed, :default => false
t.timestamps
end
end
end
class CreateSubscriptionsTable < ActiveRecord::Migration[5.0]
def change
create_table :subscriptions do |t|
t.string :name, null:false
t.belongs_to :product, index: true
end
end
end
class CreateSubscriptionDetailsTable < ActiveRecord::Migration[5.0]
def change
create_table :subscription_details do |t|
t.belongs_to :subscription, index:true
t.belongs_to :person, index:true
t.boolean :trial, :default => true
t.string :mailing_preference, :default => "Cc"
t.datetime :trial_start
t.datetime :trial_end
end
end
end
创建一个人时,我设置了一个表单,通过同一个表单(使用复选框)向该人添加多个订阅 - 我将这些收集到一个名为 "subscriptions" 的数组中。订阅是使用另一种形式预先创建的。我使用以下代码(对 has_many through additional attributes 中的内容稍作修改)来创建此人:
info = {
name: name,
email: email,
institution_id: institution.id
}
person = Person.create(info)
person.save
subscriptions.each do |each_subscription|
person.subscription_details.create(
:subscription => each_subscription,
:trial_start => trial_start,
:trial_end => trial_end
)
end
但我总是得到以下错误:
NameError at /institutions/1/add_person
uninitialized constant Person::SubscriptionDetail
更新: 它在 person.subscription_details.create(
行抛出异常。
当控制台中 运行 相同的代码时,我得到 NameError: uninitialized constant Person::SubscriptionDetail from C:/Ruby22-x64/lib/ruby/gems/2.2.0/gems/activerecord-5.0.1/lib/active_record/inheritance.rb:152:in 'compute_type'
更新 2: 我应该注意,在检查 Postgres 中的数据库时,它在 people table 中创建了人,但没有在中创建相关的订阅详细信息subscription_detailstable
我检查了多个模型文件、关联,甚至检查了拼写错误,尝试在模型中使用 :class_name 属性,我在没有 person.save
的情况下尝试过,最后 2小时谷歌搜索这个,但我无法弄清楚为什么这是失败的。
更新
窗体视图 (people/new.erb)
<form action="/institutions/<%= @institution.id %>/add_person" method="post">
<table>
<tr>
<th><label for="name">Name</label></th>
<td><input type="text" id="name" name="person[name]" placeholder="Name"></td>
</tr>
<tr>
<th><label for="email">E-mail</label></th>
<td><input type="text" id="email" name="person[email]" placeholder="E-mail"></td>
</tr>
<tr>
<th><label for="institution">Institution</label></th>
<td><input type="text" id="institution" name="person[institution]" placeholder="<%= @institution.name %>" value="<%= @institution.name %>"></td>
</tr>
<tr>
<th>Subscriptions</th>
<td>
<% @subscriptions.each do |subscription| %>
<label><input type="checkbox" name="person[subscriptions][]" value="<%= subscription.id %>"><%= subscription.name %></label><br>
<% end %>
</td>
</tr>
<tr>
<th><label for="trial-start">Trial-start Date</label></th>
<td>
<input type="text" id="trial-start" name="person[trial][start]" placeholder="DD-MM-YYYY">
</td>
</tr>
<tr>
<th><label for="trial-end">Trial-end Date</label></th>
<td>
<input type="text" id="trial-end" name="person[trial][end]" placeholder="DD-MM-YYYY">
</td>
</tr>
</table>
<input class="button" type="submit" value="Add Person">
</form>
在 Rails 4.2 中,您的 SubscriptionDetails 迁移看起来像这样:
class CreateSubscriptionDetailsTable < ActiveRecord::Migration
def change
create_table :subscription_details do |t|
t.belongs_to :subscription, index: true, foreign_key: true, null: false
t.belongs_to :person, index: true, foreign_key: true, null: false
t.boolean :trial, default: true
t.string :mailing_preference, default: "Cc"
t.datetime :trial_start
t.datetime :trial_end
end
add_index :subscription_details, ["subscription_id", "person_id"], unique: true
end
end
不确定 5.0 中进行了哪些更改,但可能值得添加索引和外键约束以查看是否可以解决问题。当然,您需要回滚迁移并再次 运行 它们。
嗯,现在我觉得我真的很愚蠢。我向所有可能在这里浪费时间的人道歉,并真诚地感谢你们付出的所有努力。
但这是我的错。我忘了检查我的 config.ru
文件。我通过将以下行添加到我的 config.ru 文件中解决了这个问题:
require './models/subscription_detail'
这就是为什么我的应用程序看不到 SubscriptionDetail 模型的原因。我只是回答这个问题,以防它能帮助任何犯同样错误的人。
再次感谢所有answered/commented的人。