I am having a complex issue in Rails 4, which I will try to describe below. I am using simple form and awesome_nested_fields gems.
I have a bunch of events with some fields in my app
Here's my working event_controller params before the implementation of accepts_nested_attributes:
private
def event_params
params.require(:event).permit(:title, :description, :type_id, :price, :program,
:start_date, :end_date, :image, category_ids: [])
end
Now I would like to add some speakers to my events, and make the user decide, how many speakers he wants per event. So I'm adding the nested fields gem and making speakers a nested field, as per their documentation.
Event.rb
class Event < ActiveRecord::Base
has_many :speakers
accepts_nested_attributes_for :speakers, allow_destroy: true
end
Speaker.rb
class Speaker < ActiveRecord::Base
belongs_to :event
end
Adding speakers (inside my add event simple_form_for):
<%= f.nested_fields_for :speakers do |f| %>
<fieldset class="item">
<%= f.label :name %>
<%= f.text_field :name %>
<a href="#" class="remove">remove</a>
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy %>
</fieldset>
<% end %>
Update controller for strong parameters:
private
def event_params
params.require(:event).permit(:title, :description, :type_id, :price, :program,
:start_date, :end_date, :image, category_ids: [],
speakers_attributes: [ :name ])
end
Now when I launch my app, upon creation of the new event I'm getting:
can't write unknown attribute `event_id'
If I remove the
speakers_attributes: [ :name ]
from the strong parameters I will be able to create my event, however when trying to view or edit it I will get
SQLite3::SQLException: no such column: speakers.event_id: SELECT "speakers".* FROM "speakers" WHERE "speakers"."event_id" = ?
And of course there are no speakers created in the database.
>> s = Speaker.first
=> nil
I will appreciate any help or advice. Thank you!
=====
UPDATED for the duplications issue
Events controller
def update
@event = Event.find(params[:id])
if @event.update(event_params)
flash[:success] = "Event updated"
redirect_to @event
else
render @event
end
end
event.rb
class Event < ActiveRecord::Base
belongs_to :type
has_many :categorizations
has_many :categories, through: :categorizations
has_many :speakers
accepts_nested_attributes_for :speakers, allow_destroy: true
@today = Date.today
def self.future_events
order('start_date ASC').where('start_date >= ?', @today)
end
scope :current_events, lambda { where('start_date < ? and end_date > ?', @today, @today) }
scope :past_events, lambda { order('end_date DESC').where('end_date < ?', @today) }
scope :future_by_type, lambda { |type| order('start_date ASC').where('type_id = ? and start_date >= ?', type, @today) }
scope :current_by_type, lambda { |type| order('start_date ASC').where('type_id = ? and start_date < ? and end_date > ?', type, @today, @today) }
scope :past_by_type, lambda { |type| order('start_date ASC').where('type_id = ? and end_date < ?', type, @today) }
validates :title, presence: true
mount_uploader :image, ImageUploader
before_save :define_end_date
before_save :zero_price
private
def define_end_date
self.end_date ||= self.start_date
end
def zero_price
if self.price.empty?
self.price = 0
end
end
end
Now that I think about it, it might be related to strong parameters. For update to work you need to allow id
attributes also. In your permit params add id for speakers
and any other nested nested resources in use that will be updated.
Please give this a try:
def event_params
params.require(:event).permit(:title, :description, :type_id, :price, :program,
:start_date, :end_date, :image, category_ids: [],
speakers_attributes: [ :id, :name ])
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With