深层嵌套的 Accept_nested_attributes_for 不在编辑模板中呈现属性数据

2024-04-06

我在理解 Accept_nested_attributes_for 方面遇到了一些挑战。

我有一个由各种子类(地址、医生、监护人等)组成的住院医师类。我对使 Accepts_nested_attributes_for 工作所需步骤的理解如下:

  1. 创建必要的关联
  2. 将 Accepts_nested_attributes_for :resource 添加到父类,我将使用该父类的形式提交嵌套属性
  3. 像这样的白名单嵌套属性。 attr_accessible :地址属性、:医生属性等...
  4. 在父控制器中,构建关联的资源。即@resident.addresses.build(对于has_many关联),@resident.build_doctor(对于has_one关联)
  5. 为每个子资源添加 fields_for 块以包含其属性值。

我的居民记录中有该地址,但当我尝试添加其他类别时,我遇到了挑战。例如,医生也需要地址,监护人也需要地址。

我是否还会添加接受nested_attributes_for:address到我的doctor.rb模型?如果是这样,这是否意味着我需要一个该资源的控制器,并为其组件调用构建方法?现在是在我的表单模板中使用嵌套 fields_for 的时候了吗? (示例如下)

  <%= f.fields_for :doc1 do |doc| %>
    <%= doc.text_field :fname %>
    <%= doc.text_field :lname %>
  <%= doc.fields_for :address do |doc_address| %>
    <%= doc_address.text_field :street_address %>
    <%= doc_address.text_field :city %>
    <%= doc_address.text_field :state %>
  <% end %>
  <%= doc.fields_for :primary_phone do |phone1| %>
    <%= phone1.phone_field :area_code %>
    <%= phone1.phone_field :number %>
  <% end %>
<% end %>

以下是相关文件:

居民.rb

class Resident < ActiveRecord::Base
  attr_accessible :address_attributes, :guardian_attributes, :desrep_attributes, :doctor_attributes,
                  :em_contact1_attributes, :em_contact2_attributes, :fname, :lname, :gender, :pic, :soc, :dob, 
                  :marital_stat, :placement_name, :placement_address, :res_start_date, 
                  :res_end_date, :religious_prefs, :insurance_info, :burial_provisions, 
                  :case_number, :vet_stat_num, :admission_height, :admission_weight, 
                  :resident_initials, :allergies,:admin_id

  belongs_to :admin
  has_one :address, as: :addressable
  has_one :guardian
  has_one :desrep, class_name: "DesignatedRepresentative"
  has_one :doc1, class_name: "Doctor"
  has_one :em_contact1, class_name: "EmergencyContact"
  has_one :em_contact2, class_name: "EmergencyContact"
  has_one :primary_phone, class_name: "PhoneNumber"
  has_one :secondary_phone, class_name: "PhoneNumber"

  has_many :assessment_plan_forms, dependent: :destroy
  has_many :blood_pressure_record_forms, dependent: :destroy
  has_many :fund_record_form1s, dependent: :destroy
  has_many :fund_record_form2s, dependent: :destroy
  has_many :incident_accident_forms, dependent: :destroy
  has_many :med_record_forms, dependent: :destroy
  has_many :personal_care_forms, dependent: :destroy
  has_many :resident_care_agreement_forms, dependent: :destroy
  has_many :visitation_appointment_forms, dependent: :destroy
  has_many :weight_record_forms, dependent: :destroy

  accepts_nested_attributes_for :address, allow_destroy: true
  accepts_nested_attributes_for :guardian, allow_destroy: true
  accepts_nested_attributes_for :desrep, allow_destroy: true
  accepts_nested_attributes_for :doc1, allow_destroy: true
  accepts_nested_attributes_for :em_contact1, allow_destroy: true
  accepts_nested_attributes_for :em_contact2, allow_destroy: true

  validates_presence_of :fname, :lname

  def full_name
    "#{ fname } #{ lname }"
  end

  def guard_fname
    guarian.fname
  end
end

地址.rb

class Address < ActiveRecord::Base
  attr_accessible :street_address, :city, :state, :zip, :addressable_type, :addressable_id

  belongs_to :addressable, polymorphic: true
end

医生.rb

class Address < ActiveRecord::Base
  attr_accessible :street_address, :city, :state, :zip, :addressable_type, :addressable_id

  belongs_to :addressable, polymorphic: true
end

紧急联系.rb

class EmergencyContact < ActiveRecord::Base
  attr_accessible :address_attributes, :primary_phone_attributes, :secondary_phone_attributes, :fax_attributes,
                  :fname, :lname, :primary, :email, :resident_id

  belongs_to :resident

  has_one :address, as: :addressable
  has_one :primary_phone, class_name: "PhoneNumber"
  has_one :secondary_phone, class_name: "PhoneNumber"
  has_one :fax, as: :phoneable

  accepts_nested_attributes_for :address
  accepts_nested_attributes_for :primary_phone
  accepts_nested_attributes_for :secondary_phone
  accepts_nested_attributes_for :fax
end

居民控制器.rb-(构建代码位于“新”方法内)

class ResidentsController < ApplicationController
  before_filter :authenticate_admin!

  def index
    @residents = Resident.all
  end

  def new
    @resident = Resident.new
    @resident.build_address
    @resident.build_guardian
    @resident.build_desrep
    @resident.build_em_contact1
    @resident.build_em_contact2
  end
end

意见/居民/_form.html.erb(这显示了居民的工作地址 fields_for)

<%= f.fields_for :address do |builder| %>
  <div class="control-group">
    <%= builder.label :street_address, "Address:", class: "control-label" %>
    <div class="controls">
      <%= builder.text_field :street_address, class: "text_field", placeholder: "Resident's Address" %>
    </div>
  </div>
  <div class="control-group">
    <%= builder.label :city, "City:", class: "control-label" %>
    <div class="controls">
      <%= builder.text_field :city, class: "text_field", placeholder: "Resident's City" %>
    </div>
  </div>
  <div class="control-group">
    <%= builder.label :state, "State:", class: "control-label" %>
    <div class="controls">
      <%= builder.text_field :state, class: "text_field", placeholder: "Resident's State" %>
    </div>
  </div>
  <div class="control-group">
    <%= builder.label :zip, "Zip:", class: "control-label" %>
    <div class="controls">
      <%= builder.text_field :zip, class: "text_field", placeholder: "Resident's Zip Code" %>
    </div>
  </div>
<% end %>

意见/居民/_form.html.erb(这将医生对象显示为“doc1”,这是不起作用的)

<%= fields_for :doc1 do |doc| %>
  <div class="control-group">
    <%= doc.label :fname, "Doctor's First Name:", class: "control-label" %>
    <div class="controls">
      <%= doc.text_field :fname, class: "text_field", placeholder: "Doctor's First Name" %>     
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :lname, "Doctor's Last Name:", class: "control-label" %>
    <div class="controls">
      <%= doc.text_field :lname, class: "text_field", placeholder: "Doctor's Last Name" %>
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :initials, "Initials:", class: "control-label" %>
    <div class="controls">
      <%= doc.text_field :initials, class: "text_field", placeholder: "Doctor's Initials" %>     
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :phone1, "Doctor's Primary Phone:", class: "control-label" %>
    <div class="controls">
      <%= doc.phone_field :phone1_area_code, placeholder: "Area Code", style: "width: 25%;" %>
      <%= doc.phone_field :phone1_number, class: "text_field", placeholder: "i.e. 800-555-1212" %>
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :phone2, "Doctor's Secondary Phone:", class: "control-label" %>
    <div class="controls">
      <%= doc.phone_field :phone2_area_code, placeholder: "Area Code", style: "width: 25%;" %>
      <%= doc.phone_field :phone2_number, class: "text_field", placeholder: "i.e. 800-555-1212" %>
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :fax, "Doctor's Fax:", class: "control-label" %>
    <div class="controls">
      <%= doc.phone_field :fax_area_code, placeholder: "Area Code", style: "width: 25%;" %>
      <%= doc.phone_field :fax_number, class: "text_field", placeholder: "Doctor's Fax Number" %>
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :email, "Doctor's Email:", class: "control-label" %>
    <div class="controls">
      <%= doc.text_field :email, class: "text_field", placeholder: "Doctor's Email Address" %>
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :street_address, "Doctor's Address:", class: "control-label" %>
    <div class="controls">
      <%= doc.text_field :street_address, class: "text_field", placeholder: "Doctor's Street Address" %>
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :city, "Doctor's City:", class: "control-label" %>
    <div class="controls">
      <%= doc.text_field :city, class: "text_field", placeholder: "Doctor's City" %>
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :state, "Doctor's State:", class: "control-label" %>
    <div class="controls">
      <%= doc.text_field :state, class: "text_field", placeholder: "Doctor's State" %>
    </div>
  </div>
  <div class="control-group">
    <%= doc.label :zip, "Doctor's Zip:", class: "control-label" %>
    <div class="controls">
      <%= doc.text_field :zip, class: "text_field", placeholder: "Doctor's Zip Code" %>
    </div>
  </div>
<% end %>

在使用accepts_nested_attributes之前,我想简单地延迟加载我的对象或通过初始化程序传递它们。但我首先必须做更多的阅读,因为到目前为止我无法使用这些技术获得我想要的结果。

我可以根据要求显示剩余的视图代码和任何其他文件。

提前致谢。

Update:05-25-14 - 我仍在努力解决这个问题,并已经写了这篇博文 http://projectramon.wordpress.com/2014/05/27/exploring-rails-accepts_nested_attributes_for-pt1/根据我的理解,我目前所处的位置。


好的,创建一个双重(或多于双重)的嵌套形式。以下是我为使事情顺利进行而遵循的步骤。

  1. 定义适当的关联(记住添加class_name: "NameOfClass" and/or inverse_of: :model_name,如有必要,消除 Rails 的猜测)

Ex:

老师.rb

class Teacher < ActiveRecord::Base
  attr_accessible :first_name, :last_name, :address_attributes,  :primary_phone_attributes, :secondary_phone_attributes,
                  :teacher_aids_attributes, :students_attributes


  has_many :students, inverse_of: :teacher
  has_many :teacher_aids, inverse_of: :teacher

  has_one :address, as: :addressable, class_name: "Address"
  has_one :email
  has_one :primary_phone, as: :phoneable, class_name: "PhoneNumber"
  has_one :secondary_phone, as: :phoneable, class_name: "PhoneNumber"

  accepts_nested_attributes_for :address, :primary_phone, :secondary_phone, :teacher_aids, :students
end

教师援助.rb

class TeacherAid < ActiveRecord::Base
  attr_accessible :first_name, :last_name, :address_attributes, :primary_phone_attributes, :secondary_phone_attributes, :teacher_id

  belongs_to :teacher, inverse_of: :teacher_aids

  has_many :students, inverse_of: :teacher_aids

  has_one :address, as: :addressable, class_name: "Address"
  has_one :email
  has_one :primary_phone, as: :phoneable, class_name: "PhoneNumber"
  has_one :secondary_phone, as: :phoneable, class_name: "PhoneNumber"

  accepts_nested_attributes_for :address, :primary_phone, :secondary_phone
end

学生.rb

class Student < ActiveRecord::Base
  attr_accessible :first_name, :last_name, :address_attributes, :primary_phone_attributes, :secondary_phone_attributes,
                  :teacher_id, :teacher_aid_id

  belongs_to :teacher
  belongs_to :teacher_aid

  has_one :address, as: :addressable, class_name: "Address"
  has_one :email
  has_one :primary_phone, as: :phoneable, class_name: "PhoneNumber"
  has_one :secondary_phone, as: :phoneable, class_name: "PhoneNumber"

  accepts_nested_attributes_for :address, :primary_phone, :secondary_phone
end

请注意我是如何添加的accepts_nested_attributes_for在两个Student and TeacherAid类。这是因为它们也由一个地址和两个电话号码对象组成。

  1. 将嵌套属性哈希添加到您的类中'attr_accessible为了将这些嵌套属性列入白名单。

ex:

一位老师有一个地址...

attr_accessible :teacher_first_name, :teacher_last_name, :address_attributes

老师有很多苹果...

attr_accessible :teacher_first_name, :teacher_last_name, :apples_attributes

请注意从单数拼写到复数拼写的变化has_one vs has_many.

  1. Add accepts_nested_attribtues_for :name_of_nested_resource想要将其属性或组合对象的属性列在父表单模板上的所有类。

  2. 在父控制器(即您想要用来存储所有组合对象的属性的控制器)中,在新方法中构建嵌套实例,如下所示。

ex:

教师控制器.rb

class TeachersController < ApplicationController
  def index
    @teachers = Teacher.all
  end

  def new
    @teacher = Teacher.new
    @teacher.build_address
    @teacher.build_primary_phone
    @teacher.build_secondary_phone

    @teacher_aid = @teacher.teacher_aids.build
    @teacher_aid.build_address
    @teacher_aid.build_primary_phone
    @teacher_aid.build_secondary_phone

    @student = @teacher.students.build
    @student.build_address
    @student.build_primary_phone
    @student.build_secondary_phone
  end
end

注意:我没有在我的后代类中创建任何构建方法,即使它们是由其他对象组成的。据我了解,这是由于 Rails 通过父级(即本例中为 Teacher)创建嵌套对象。

下面是 Rails Guides 中嵌套哈希的示例:

Ex:

教师_aids_controller.rb

class TeacherAidsController < ApplicationController
  before_filter :get_teacher_aid, except: [:index, :new, :create]

  def index
    @teacher_aids = TeacherAid.all
  end

  def new
    @teacher_aids = TeacherAid.all
  end
end

学生控制器.rb

class StudentsController < ApplicationController
  before_filter :get_student, except: [:index, :new, :create]

  def index
    @students = Student.all
  end

  def new
    @student = Student.new 
  end
end
  1. 当添加双精度(或多于双精度)嵌套 :address_attributes 或任何名称时,我们确实需要在视图模板中嵌套 fields_for ,如下所示。

ex:

教师/_form.html.erb

  <%= form_for @teacher, html: { multipart: true, class: "form-horizontal" } do |f| %>
    <%= f.text_field :first_name, placeholder: "Teacher's First Name" %><br />
    <%= f.text_field :last_name, placeholder: "Teacher's Last Name" %><br />
    <%= f.fields_for :address do |teacher_address| %>
      <%= teacher_address.text_field :street_address, placeholder: "Teachers street_address" %>
      <%= teacher_address.text_field :city, placeholder: "Teacher's city" %>
      <%= teacher_address.text_field :state, placeholder: "Teacher's state" %>
      <%= teacher_address.text_field :zip, placeholder: "Teacher's zip" %>
    <% end %>
    <%= f.fields_for :primary_phone do |teacher_phone1| %>
      <%= teacher_phone1.phone_field :area_code, placeholder: "Primary Area Code" %>
      <%= teacher_phone1.phone_field :number, placeholder: "Primary Number" %>
    <% end %>
    <%= f.fields_for :secondary_phone do |teacher_phone2| %>
      <%= teacher_phone2.phone_field :area_code, placeholder: "Secondary Area Code" %>
      <%= teacher_phone2.phone_field :number, placeholder: "Secondary Number" %>
    <% end %>
    <%= f.fields_for :teacher_aids do |teach_aid| %>
      <%= teach_aid.text_field :first_name, placeholder: "Aid's First Name" %><br />
      <%= teach_aid.text_field :last_name, placeholder: "Aid's Last Name" %><br />
      <%= teach_aid.fields_for :address do |address| %>
        <%= address.text_field :street_address, placeholder: "Aids Street Address" %><br />
        <%= address.text_field :city, placeholder: "Aids city" %><br />
        <%= address.text_field :state, placeholder: "Aids state" %><br />
        <%= address.text_field :zip, placeholder: "Aids zip" %><br />
      <%end %>
      <%= teach_aid.fields_for :primary_phone do |phone1| %>
        <%= phone1.phone_field :area_code, placeholder: "Aid's Area Code" %>
        <%= phone1.phone_field :number, placeholder: "Aid's Primary Number" %>
      <% end %>
      <%= teach_aid.fields_for :secondary_phone do |phone2| %>
        <%= phone2.phone_field :area_code, placeholder: "Aid's Area Code" %>
        <%= phone2.phone_field :number, placeholder: "Aid's Secondary Number" %>
      <% end %>
    <% end %>

请注意 :address、:primary_phone 和 :secondary_phone 是如何嵌套在各自对象的各个 fields_for 下的。

我当前的障碍是我的 Primary_phone 和 secondary_phone 多态模型仅显示主要电话数据。这意味着由于某种原因,has_one :primary_phone, as: :phoneable, class_name: "PhoneNumber" and has_one :secondary_phone, as: :phoneable, class_name: "PhoneNumber"不被视为两个独立的事物。但这是另一个问题的主题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深层嵌套的 Accept_nested_attributes_for 不在编辑模板中呈现属性数据 的相关文章

随机推荐