Rails如何以一种形式保存来自不同模型(国家,州,城市,地址)的地址?

时间:2018-10-11 05:42:01

标签: ruby-on-rails ruby database forms model

所以我想做的就是以一种单一形式保存一堆数据。该数据的一部分是地址此地址已分为几种模式:国家,州,城市和地址。

我的问题是,老实说,我不知道如何在控制器中进行管理。我将分享我目前的情况,并希望有人可以给我一个提示。

我应该为所有模型进行 accepts_nested_attributes_for 吗?如何连接所有这些继承字段或外键以处理信息?

国家/地区型号:

class Country < ApplicationRecord
  has_many :states
end

状态模型:

class State < ApplicationRecord
  belongs_to :country
  has_many :cities
end

城市模型:

class City < ApplicationRecord
  belongs_to :state
  has_many :addresses

  accepts_nested_attributes_for :addresses
end

地址模型:

class Address < ApplicationRecord
  belongs_to :city
  belongs_to :office
end

Office模型:

class Office < ApplicationRecord

  has_many :addresses, inverse_of: :office

  accepts_nested_attributes_for :addresses
end

适用于国家/地区,州,城市和地址的Office Controller强参数(还有更多参数,我只是将这些参数与我遇到的问题有关):

def office_params
      params.require(:office).permit(
     {
        countries_attributes: [
          :id, :name,
          states_attributes: [
            :id, :name,
            cities_attributes: [
            :id, :name,
              addresses_attributes: [
                :id, :street, :state_id
                ]
            ]
          ]
        ]
      },         
)

Office新方法:

def new
    @office = Office.new
    @countries = Country.all.map{|c| [ c.name, c.id ] }
    @states = State.all.map{|c| [ c.name, c.id ] }
    #@office.addresses.build.cities.build
    #@office.addresses.counties.states.cities.build
    #@office.addresses.build
  end

Office表单:在此表单中,我使用fields_for来嵌套从各自模型调用的所有字段。所以在这里,我需要一次将所有信息保存到几个模型中。

<%= form_with(model: office, local: true, html: {class: "form-office"}) do |form| %>
        <% if office.errors.any? %>
          <div id="error_explanation">
            <h2><%= pluralize(office.errors.count, "error") %> prohibited this office from being saved:</h2>

            <ul>
            <% office.errors.full_messages.each do |message| %>
              <li><%= message %></li>
            <% end %>
            </ul>
          </div>
        <% end %>

        <div class="row">
          <div class="col-md-6 col-sm-6 col-xs-12">
            <div class="form-group">
              <span><%= form.label :office_name %></span>
              <%= form.text_field :office_name, class: 'form-control' %>
            </div>
          </div>

          <div class="col-md-6 col-sm-6 col-xs-12">
            <div class="form-group">
              <span><%= form.label :office_slug %></span>
              <%= form.text_field :office_slug, class: 'form-control' %>
            </div>
          </div>
        </div>

        <div class="row">
          <div class="col-md-6 col-sm-6 col-xs-12">
            <div class="form-group">
              <span><%= form.label :office_email %></span>
              <%= form.text_field :office_email, class: 'form-control' %>
            </div>
          </div>

          <div class="col-md-6 col-sm-6 col-xs-12">
            <div class="form-group">
              <span><%= form.label :phone %></span>
              <%= form.text_field :phone, class: 'form-control' %>
            </div>
          </div>
        </div>

        <hr>
        <h3 style="color: #B0B0B0;">Office Address</h3>
**Office Address**
        <div class="row">
          <div class="col-md-6 col-sm-6 col-xs-12 col-md-offset-6">
            <%= form.fields_for :countries do |country| %>
              <div class="form-group">
                <span><%= country.label :country %></span>
                <%= select_tag(:country_id, options_for_select(@countries), class: 'form-control', :prompt => "Select Country") %>
              </div>

              <div class="form-group">
                <%= country.fields_for :states do |state| %>
                  <span><%= state.label :state %></span>
                  <%= select_tag(:state_id, options_for_select(@states), class: 'form-control', :prompt => "Select State") %>
              </div>
            </div>
            <div class="col-md-6 col-sm-6 col-xs-12 col-md-offset-6">
                <div class="form-group">
                  <%= state.fields_for :cities do |city| %>
                    <span><%= city.label :city %></span>
                    <%= city.text_field :name, class: 'form-control' %>
                </div>

                  <div class="form-group">
                    <%= city.fields_for :addresses do |address| %>
                      <span><%= address.label :street %></span>
                      <%= address.text_field :street, class: 'form-control' %>
                  </div>

                    <div class="form-group">
                      <span><%= address.label :zip_code %></span>
                      <%= address.text_field :zip_code, class: 'form-control' %>
                    </div>
                    <% end %>
                <% end %>
              <% end %>
            <% end %>
            </div>
        </div>

      <hr>
      <h4 style="color: #B0B0B0;">Comment</h4>

        <div class="row">
          <div class="col-md-12 col-sm-6 col-xs-12 st">
            <div class="comments">
              <%= form.fields_for :comments do |comment_form| %>
                <%= render 'comment_fields', f: comment_form %>
              <% end %>
            </div>
          </div>
        </div>

        <div>
          <div class="col-md-4 offset-md-4">
            <%= form.submit class: 'btn btn-lg' %>
          </div>
        </div>
 <% end %>

1 个答案:

答案 0 :(得分:0)

是的,您必须为要通过Remove-PreviousOfficeInstalls更新的每个关联添加accepts_nested_attributes_for

fields_for

但是,如果您这样做并且正确定义了class Country < ApplicationRecord has_many :states accepts_nested_attributes_for :states end class State < ApplicationRecord belongs_to :country has_many :cities accepts_nested_attributes_for :states end ,则可以通过一次office_params调用来保存所有嵌套模型,而不必担心设置外键。 更新同样如此,但是您必须为嵌套模型提供隐藏的Office.create(office_params)表单字段,以便可以在数据库中找到现有的模型实例。

您还应该考虑将validates_associated添加到模型中。