Reputation: 1808
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!
Upvotes: 0
Views: 1656
Reputation: 101901
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
Upvotes: 1
Reputation: 1279
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?
Upvotes: 0