5

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
The Whiz of Oz
  • 6,763
  • 9
  • 48
  • 85
  • 1
    Things to check: Does your speakers table have `event_id` column? Did you run the migration? – vee Aug 19 '13 at 07:44
  • If it was a strong params problem, you'd more likely see an error saying 'unpermitted params -> name of params'. I'd look at the db table as vinodadhika suggests. – simonmorley Aug 19 '13 at 07:50
  • @simonmorley adding event_id to speakers table worked. I can't understand why this was not mentioned in the documentation for the plugin. Now however I'm facing a new problem: when editing and saving an event with nested speakers, it duplicates them. Without any possibility of deleting. Strong parameters again? – The Whiz of Oz Aug 19 '13 at 08:01
  • @vinodadhikary adding event_id to speakers table worked. I can't understand why this was not mentioned in the documentation for the plugin. Now however I'm facing a new problem: when editing and saving an event with nested speakers, it duplicates them. Without any possibility of deleting. Strong parameters? – The Whiz of Oz Aug 19 '13 at 08:01
  • @DenisG, No I don't think that's strong parameters issue, please post your controller's update action and your model code. The reason for model is to make sure you don't have any any filters that might cause this issue. – vee Aug 19 '13 at 08:04
  • @DenisG, I don't see anything doing that duplication here. When you say duplicates them, what is duplicated, speakers? – vee Aug 19 '13 at 08:46
  • @vinodadhikary yes, I push update and all the speakers fields get duplicated – The Whiz of Oz Aug 19 '13 at 08:59
  • @DenisG, I wanted to post a comment but added an answer for you try because of the code. – vee Aug 19 '13 at 09:09

1 Answers1

13

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 
vee
  • 38,255
  • 7
  • 74
  • 78
  • 2
    It works! However I do not have the event :id permission. I have also added '_destroy' to the speaker_attributes array, so now it looks like this: speakers_attributes: [ :id, :name, '_destroy' ] Thank you so much – The Whiz of Oz Aug 19 '13 at 09:33
  • I will add the :id to event just in case though – The Whiz of Oz Aug 19 '13 at 09:34
  • @DenisG, You're welcome. Don't need to add :id on event for just in case. I'll update my answer. – vee Aug 19 '13 at 09:36
  • sorry to bother you again, but any idea on how can I remove the nested image I upload for every speaker? I tried nesting even further but failed miserably – The Whiz of Oz Aug 19 '13 at 14:04
  • @DenisG, You are not bothering me. I suggest asking this as a new question for it as the topic is different. – vee Aug 19 '13 at 14:12
  • 1
    please join the fun then http://stackoverflow.com/questions/18316566/nesting-carrierwave-images-in-rails-4 – The Whiz of Oz Aug 20 '13 at 08:46