Rails has_many:通过嵌套形式
Posted
技术标签:
【中文标题】Rails has_many:通过嵌套形式【英文标题】:Rails has_many :through nested form 【发布时间】:2012-11-10 11:59:16 【问题描述】:我刚刚加入has_many :through
协会。我正在尝试通过一个表单实现为所有 3 个表(Physician
、Patient
和关联表)保存数据的能力。
我的迁移:
class CreatePhysicians < ActiveRecord::Migration
def self.up
create_table :physicians do |t|
t.string :name
t.timestamps
end
end
end
class CreatePatients < ActiveRecord::Migration
def self.up
create_table :patients do |t|
t.string :name
t.timestamps
end
end
end
class CreateAppointments < ActiveRecord::Migration
def self.up
create_table :appointments do |t|
t.integer :physician_id
t.integer :patient_id
t.date :appointment_date
t.timestamps
end
end
end
我的模型:
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, :through => :appointments
accepts_nested_attributes_for :appointments
accepts_nested_attributes_for :physicians
end
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, :through => :appointments
accepts_nested_attributes_for :patients
accepts_nested_attributes_for :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
我的控制器:
def new
@patient = Patient.new
@patient.physicians.build
@patient.appointments.build
end
我的看法(new.html.rb
):
<% form_for(@patient) do |patient_form| %>
<%= patient_form.error_messages %>
<p>
<%= patient_form.label :name, "Patient Name" %>
<%= patient_form.text_field :name %>
</p>
<% patient_form.fields_for :physicians do |physician_form| %>
<p>
<%= physician_form.label :name, "Physician Name" %>
<%= physician_form.text_field :name %>
</p>
<% end %>
<p>
<%= patient_form.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', patients_path %>
我可以为Appointment
创建一个新的Patient
、Physician
和关联记录,但现在我也想在表单中为appointment_date
提供字段。我应该在哪里放置Appointment
s 的字段以及我的控制器需要进行哪些更改?我尝试了谷歌搜索并尝试了this,但在实现它时遇到了一些或其他错误。
【问题讨论】:
另一个提示:您可以使用t.references :patient
而不是t.integer :patient_id
来创建适当类型的列。见guides.rubyonrails.org/migrations.html#special-helpers
【参考方案1】:
好的,这个问题的小问题困扰了我几个小时,所以我将在这里发布我的工作解决方案,希望它可以节省一些时间进行窥视。这适用于 Rails 4.0 和 Ruby 2.0。这也克服了我遇到的“符号到整数转换”的问题。
型号:
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, :through: :appointments
accepts_nested_attributes_for :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
accepts_nested_attributes_for :physician
end
class Physicians < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
控制器:
def new
@patient= Patient.new
@appointments = @patient.appointments.build
@physician = @appointments.build_physician
end
def create
Patient.new(patient_params)
end
def patient_params
params.require(:patient).permit(:id, appointments_attributes: [:id, :appointment_time, physician_attributes: [:id ] )
end
查看
<% form_for(@patient) do |patient_form| %>
<%= patient_form.error_messages %>
<p>
<%= patient_form.label :name, "Patient Name" %>
<%= patient_form.text_field :name %>
</p>
<% patient_form.fields_for :appointments do |appointment_form| %>
<p>
<%= appointment_form.label :appointment_date, "Appointment Date" %>
<%= appointment_form.date_field :appointment_date %>
</p>
<% appointment_form.fields_for :physician do |physician_form| %>
<p>
<%= physician_form.label :name, "Physician Name" %>
<%= physician_form.text_field :name %>
</p>
<% end %>
<% end %>
<p>
<%= patient_form.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', patients_path %>
【讨论】:
哦,谢谢!这个混蛋也让我忙了好一阵子。 难道医生的姓名属性也需要strong-param-permit吗?【参考方案2】:“我得到了它的工作。我只是改变了模型如下”:引用来自上面 cmets 中的 Shruti
class Patient < ActiveRecord::Base
has_many :appointments, :dependent => :destroy
has_many :physicians, :through => :appointments
accepts_nested_attributes_for :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
accepts_nested_attributes_for :physician
end
【讨论】:
【参考方案3】:您的患者类接受医生和预约的嵌套属性。尝试添加另一个fields_for
预约方法。
<% form_for(@patient) do |patient_form| %>
<%= patient_form.error_messages %>
<p>
<%= patient_form.label :name, "Patient Name" %>
<%= patient_form.text_field :name %>
</p>
<% patient_form.fields_for :physicians do |physician_form| %>
<p>
<%= physician_form.label :name, "Physician Name" %>
<%= physician_form.text_field :name %>
</p>
<% end %>
<% patient_form.fields_for :appointments do |appointment_form| %>
<p>
<%= appointment_form.label :appointment_date, "Appointment Date" %>
<%= appointment_form.date_field :appointment_date %>
</p>
<% end %>
<p>
<%= patient_form.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', patients_path %>
【讨论】:
感谢@andrew 的快速回复。我尝试了代码,它导致 2 条记录被插入到约会表中:在第一条记录中,patent_id 和约会日期被保存,在第二条记录中,医生 ID 和病人 ID 被保存。需要对控制器或模型进行任何更改吗? @Shruti 我认为您应该删除@patient.appointments.build
,并在您的创建操作中使用@patient.save
来保存对象。
@kien 如果我这样做,约会日期文本字段在我的表单上不可见:(
我搞定了。我只是将模型更改如下:class Patient < ActiveRecord::Base has_many :appointments, :dependent => :destroy has_many :physicians, :through => :appointments accepts_nested_attributes_for :appointments end class Appointment < ActiveRecord::Base belongs_to :physician belongs_to :patient accepts_nested_attributes_for :physician end
我正在处理类似的情况,但我一直遇到错误。您可以发布最终的工作代码吗?也许作为答案?我怀疑它不仅会帮助我,还会帮助处理同样问题的其他人。以上是关于Rails has_many:通过嵌套形式的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 Rails 的改革 gem,我如何填充 has_many :通过嵌套模型