向数据库中的 2 个表格提交一份表格 - ruby rails

Submit one form to 2 tables in database - ruby on rails

我有 2 个 table,landslidessources(可能彼此不相关)。我想要一个让用户填写信息然后提交给两个 table 的表格。这是我当前没有 sources 字段的表格:

 = form_for :landslide, :url => {:controller => 'landslides', :action => 'create'} do |f|

      .form-inputs
        %form#landslideForm
          .form-group.row
            %label.col-sm-2.col-form-label{for: "textinput"}Date
            .col-sm-10
              = f.date_select :start_date, :class => "form-control"
          #Some fields
     .form-actions
        = f.button :submit, class: "btn btn-lg btn-primary col-sm-offset-5", id: "submitButton"

和参数:

    def landslide_params
          params.require(:landslide).permit(:start_date, :continent, :country, :location, :landslide_type, :lat, :lng, :mapped, :trigger, :spatial_area, :fatalities, :injuries, :notes)
    end

    def source_params
      params.require(:source).permit(:url, :text, :landslide_id)
    end

sources 调用 landslide_id 中还有一列从 table landslides 中获取滑坡 ID。那么当用户提交新的滑坡时,如何获取即将到来的滑坡ID(自动递增,用户无需填写)?

谢谢!

您需要使用 accept_nested_attributes_for 并相应地嵌套您的表单:

(关于应该嵌套在哪个表单中的保留,我使用通过 landslide-form 提交的源的示例。)

在landslide.rb

accept_nested_attributes_for :sources

在你看来(我不知道 haml 但无论如何)

<%= form_for :landslide do |f|%>
  <%= f.select :start_date %>

    <%= fields_for :sources do |s| %>
      <%= s.input :your_column %>
    <% end %>

   <%= f.button :submit %>
<% end %>

顺便说一句,关于这个已经有很多问题了,它被称为'Nested Forms'

Nested forms in rails - accessing attribute in has_many relation

Rails -- fields_for not working?

fields_for in rails view

HTML 不允许嵌套 <form> 元素,您不能通过表单传递尚未持久化的记录的 ID(因为它没有 ID)。

要在您使用的同一请求中创建嵌套资源 accepts_nested_attributes_for:

class Landslide
  # or has_many
  has_one :source
  accepts_nested_attributes_for :source    
end

class Source
  belongs_to :landslide
end

这意味着您可以执行 Landslide.create(source_attributes: { foo: 'bar' }),它将创建 LandslideSource 记录,并会自动 link 通过 sources.landslide_id .

要创建表单输入,请使用 fields_for:

# use convention over configuration
= form_for @landslide do |f|
  .form-inputs
    .form-group.row
      # use the form builder to create labels instead
      = f.label :start_date, class: 'col-sm-2 col-form-label'
      .col-sm-10
        = f.date_select :start_date, class: "form-control"
   %fieldset
      %legend Source
      = f.fields_for :sources do |s|
        .form-group.row
          = s.label :url, class: 'col-sm-2 col-form-label'
          .col-sm-10
            = s.text_field :url, class: "form-control"
        # ...

class LandslidesController

  # ...

  def new
    @landslide = Landslide.new
    # this is needed to seed the form with inputs for source
    @landslide.source.new 
  end

  def create
    @landslide = Landslide.new(landslide_params)
    if @landslide.save
      redirect_to @landslide
    else
      @landslide.source.new unless @landslide.source.any?
      render :new
    end
  end

  private
  def landslide_params
    params.require(:landslide).permit(
      :start_date, :continent, :country, 
      :location, :landslide_type, 
      :lat, :lng, :mapped, :trigger, :spatial_area, 
      :fatalities, :injuries, :notes,
      source_attributes: [ :url, :text ]
    )
  end
end