当前位置 : 主页 > 编程语言 > ruby >

ruby-on-rails – 深层嵌套的accepts_nested_attributes_for不在编辑模板中呈现属性数据

来源:互联网 收集:自由互联 发布时间:2021-06-23
理解accepts_nested_attributes_for,我遇到了一些挑战. 我有一个由各种儿童班(地址,医生,监护人等)组成的居民班.我对使accept_nested_attributes_for工作所需步骤的理解如下: 创建必要的关联 将ac
理解accepts_nested_attributes_for,我遇到了一些挑战.

我有一个由各种儿童班(地址,医生,监护人等)组成的居民班.我对使accept_nested_attributes_for工作所需步骤的理解如下:

>创建必要的关联
>将accepts_nested_attributes_for:resource添加到父类,其形式我将用于提交嵌套属性
>白名单嵌套属性就像这样. attr_accessible:address_attributes,:doctor_attributes等…
>在父控制器中,构建关联的资源.即@ resident.addresses.build(用于has_many关联),@ resident.build_doctor(用于has_one关联)
>为每个子资源添加fields_for块以包含其属性值.

我的地址适用于我的常驻记录,但是当我尝试添加其他类时,我的挑战就出现了.例如,医生也需要一个地址,监护人也是如此.

我还会在我的doctor.rb模型中添加接受nested_attributes_for:地址吗?如果是这样,这是否意味着我需要一个控制器来为这个资源调用它的组件的构建方法?这是时候在我的表单模板中使用嵌套的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 %>

以下是相关文件:

resident.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

address.rb

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

  belongs_to :addressable, polymorphic: true
end

doctor.rb

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

  belongs_to :addressable, polymorphic: true
end

emergency_contact.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

resident_controller.rb – (构建代码在’new’方法内)

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

views / resident / _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 %>

views / resident / _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之前我想简单地延迟加载我的对象或通过初始化器传递它们.但是我需要先做更多的阅读,因为到目前为止,我无法使用这些技术得到我想要的结果.

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

提前致谢.

更新:05-25-14 – 我仍然在努力解决这个问题,并且已经写了this blog post关于我目前在理解的地方.

好的,要创建一个双(或两个以上)嵌套表单.以下是我为使事情发挥作用而采取的步骤.

>定义正确的关联(记得添加class_name:“NameOfClass”和/或inverse_of :: model_name,如果有必要,以消除Rails不必猜测)

例如:

teacher.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

teacher_aid.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

student.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

请注意我如何在Student和TeacherAid类中添加accepts_nested_attributes_for.这是因为它们也由一个地址和两个phone_number对象组成.

>将嵌套属性哈希添加到类’attr_accessible中,以便列出这些嵌套属性的白名单.

例如:

老师有一个地址……

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从单数到多数拼写的变化.

>将accepts_nested_attribtues_for:name_of_nested_resource添加到所有希望其父表单模板上列出的组合对象的属性或属性的类.
>在父控制器(即您要用于存储所有组合对象的属性的控制器)中,在新方法中构建嵌套实例,就像这样.

例如:

teachers_controller.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通过父级创建嵌套对象(即本例中为教师).

以下是Rails指南中有关嵌套哈希的外观的示例:

例如:

teacher_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

students_controller.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

>当添加双重(或多于两个)嵌套:address_attributes或任何名称时,我们需要在视图模板中嵌套fields_for,如此.

例如:

教师/ _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,如:: phoneable,class_name:“PhoneNumber”和has_one:secondary_phone,如::phoneable,class_name:“PhoneNumber”不被视为两个单独的东西.但这是另一个问题的主题.

网友评论