0

I have 2 tables, landslides and sources (maybe doesn't relate to each other). I want a form which lets user to fill in information and then submit to both tables. Here's my current form without sources fields:

 = 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"

And parameters:

    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

Also there's a column in sources calls landslide_id which take the landslide ID from table landslides. So when a user submits a new landslide, how can I take the upcoming landslide ID (which is auto increment, user doesn't need to fill in)?

Thanks!

2 Answers 2

1

HTML does not allow nested <form> elements and you can't pass the id of record that has not been persisted yet through a form (because it does not have an id).

To create a nested resource in the same request you use accepts_nested_attributes_for:

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

class Source
  belongs_to :landslide
end

This means that you can do Landslide.create(source_attributes: { foo: 'bar' }) and it will create both a Landslide and a Source record and will automatically link them through sources.landslide_id.

To create the form inputs use 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
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. This answer is really detail. However I still got the error found unpermitted parameter: sources
Ask a new question with this as a starting point if you want debugging help.
I think it's about source/sources, if a landslide has many sources, do I need to change every source to sources?
Please respect my time and ask a new question with this as a starting point if you want debugging help. There is no way I can know what you are doing at this point and debugging through comments is pointless since it just leads to endless follow up questions.
0

You need to use accept_nested_attributes_for and nest your form accordingly:

(With reservation in regards to what form should be nested in which, I use the example of Sources submitted via landslide-form.)

in landslide.rb

accept_nested_attributes_for :sources

In your view (I don't know haml but anyways)

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

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

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

Btw, there are a lot of questions on this already, it's called 'Nested Forms'

Nested forms in rails - accessing attribute in has_many relation

Rails -- fields_for not working?

fields_for in rails view

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.