Reputation: 115
I would like on the form page for a campaign for a user to be able to create cities as well. I followed http://railscasts.com/episodes/196-nested-model-form-part-1?view=comments and https://medium.com/karuna-sehgal/building-a-rails-app-using-tdd-devise-omniauth-and-nested-forms-f7b9769ba2ae (this one uses devise) but cant seem to get it to work.
The error I get is: ActiveRecord::RecordInvalid: Validation failed: Cities campaign must exist
Can anyone tell me what's wrong?
Models:
class City < ApplicationRecord
belongs_to :campaign#, optional: true
end
class Campaign < ApplicationRecord
has_many :cities, :dependent => :destroy
belongs_to :user
accepts_nested_attributes_for :cities, allow_destroy: true, reject_if: :all_blank
end
Controller:
def new
@campaign = current_user.campaigns.build
3.times { @campaign.cities.build }
end
def create
#binding.pry
@campaign = current_user.campaigns.build campaign_params
binding.pry
if @campaign.save
flash[:notice] = "#{@campaign.name} created"
redirect_to @campaign
else
flash[:notice] = "#{@campaign.name} not created"
redirect_to @campaign
end
end
private
def campaign_params
params.require(:campaign).permit(:name, :titles, :sentences, :keywords, cities_attributes: [:name, :phone_number, :zip_code])
end
Form:
<%= form_for @campaign do |f| %>
<%= f.label "Name" %>
<br />
<%= f.text_field :name %>
<br /> <br />
<%= f.label "Titles" %>
<br />
<%= f.text_area :titles, cols: 80, rows: 20 %>
<br /> <br />
<%= f.label "Sentences" %>
<br />
<%= f.text_area :sentences, cols: 80, rows: 20 %>
<br /> <br />
<%= f.label "Keywords" %>
<br />
<%= f.text_area :keywords, cols: 80, rows: 20 %>
<br /> <br />
<%= f.fields_for :cities do | city_form | %>
<%= city_form.label :name %>
<%= city_form.text_field :name%>
<%= city_form.label :phone_number %>
<%= city_form.text_field :phone_number %>
<%= city_form.label :zip_code %>
<%= city_form.text_field :zip_code %>
</br>
<% end %>
<%= f.submit "Submit" %>
<% end %>
Upvotes: 0
Views: 199
Reputation: 1359
It seems you have missed out to pass campaign_id
inside cities_attributes
error happened because when rails tried to save inside the cities active_record there were no campaign_id
that's why you are getting a validation error like:
ActiveRecord::RecordInvalid: Validation failed: Cities campaign must exist
So you can change campaign_params
as follows:
def campaign_params
params.require(:campaign).permit(:name, :titles, :sentences, :keywords, cities_attributes: [:campaign_id, :name, :phone_number, :zip_code])
end
Upvotes: 0
Reputation: 2624
You can use :inverse_of
like this:
Active Record provides the :inverse_of option so you can explicitly declare bi-directional associations:
class City < ApplicationRecord
belongs_to :campaign, inverse_of: :cities
end
class Campaign < ApplicationRecord
has_many :cities, inverse_of: :campaign
end
Upvotes: 1