【发布时间】:2017-01-24 18:09:31
【问题描述】:
我是 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
在订阅.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
创建一个人时,我设置了一个表单,通过同一个表单(使用复选框)向该人添加多个订阅 - 我将这些收集到一个名为“订阅”的数组中。订阅是使用另一种形式预先创建的。我使用以下代码(对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 表中创建了人员,但在 subscription_details 表中没有创建相关的订阅详细信息
我检查了多个模型文件、关联,甚至检查了拼写错误,尝试在模型中使用 :class_name 属性,我在没有person.save 的情况下尝试了它,并花了最后 2 个小时在谷歌上搜索,但我不能t弄清楚为什么这会失败。
更新
表单视图(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>
【问题讨论】:
-
第一:我不知道你为什么会收到这个错误。我会对如何定义路由、如何命名模型和控制器以及如何定义表单以开始调查感兴趣。我在这里使用模型和关联模仿了您的设置,并让事情正常工作。你在用
accepts_nested_attributes_for吗?我有更多的想法,但没有足够的字符 - 你能在你的问题中包含你的表单、控制器和模型代码吗?然后我也许可以尝试一下答案。 -
@wendybeth 哇,好吧,显然我更像是一个初学者,我认为 - 几乎没有听懂你说的。我的模型和控制器的命名空间是什么意思?我假设表单定义只是表单的结构?我从来没有听说过你所说的
accepts_nested_attributes_for。另外,我上面的模型代码就是全部了,关于创建人的部分来自控制器 - 你还需要多少代码? -
只是一个旁注,但 Ruby/Rails 约定将本地迭代器变量称为
subscription而不是each_subscription。该变量仅代表一个订阅,每次迭代都会发生变化。 -
不用担心。 :) 你的问题很好,所以我不会太担心。按命名空间:我看到你有'institutions/1/add_person',所以我想知道你的控制器是否设置了'app/controllers/institutions/people_controller'。此外,“add_person”不是默认的 Rails 路由——通常是“/people/new”——所以我想查看你的 config/routes.rb 文件。同时,如果您查看
accepts_nested_attributes_for,我想您可能会在这里找到很多好东西来帮助您:api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/… -
另外,通过定义的表单,我只是指您用于创建表单的视图文件中的代码。
标签: ruby activerecord has-many-through