1

I have multiple Lessons and most of them have some prerequisites which are themselves other lessons. The Prerequisite model represents the relationship and each has a lesson_id and prerequisite_lesson_id.

class Lesson < ApplicationRecord
  has_many :prerequisites
  has_many :prerequisite_lessons, :through => :prerequisites
end

class Prerequisite < ApplicationRecord
  belongs_to :lesson
  belongs_to :prerequisite_lesson, :class_name => "Lesson"
end

I'm trying to figure out a way so that:

  • When I create a new Lesson and select one or more prerequisites from a collection_select
  • multiple Prerequisite objects are created based on what was selected, with the lesson_id being the created Lesson id.

Here is part of my Lesson controller:

def create
  @lesson = Lesson.new(lesson_params)

  if @lesson.save
    if @lesson.prerequisite_ids.length > 0
      @lesson.prerequisite_ids.each do |p|
        Prerequisite.new(lesson_id: @lesson.id, prerequisite_lesson_id: p)
      end
    end
    flash[:notice] = "Lesson created..."
    redirect_to root_url
  else
    render :new
  end
end

...

def lesson_params
  params.require(:lesson).permit(
    :name,
    :high_tempo,
    :low_tempo,
    :interval,
    :advance_tempo,
    prerequisites_attributes: [
      :lesson_id,
      :prerequisite_lesson_id
    ]
  )
end

and my form:

<%= f.collection_select(:prerequisite_ids, Lesson.all, :id, :name, {}, {:multiple => true}) %>

UPDATE:

In the logs, I see:

"lesson"=>{"name"=>"Lesson 6", "high_tempo"=>"200", "low_tempo"=>"100", "interval"=>"10", "advance_tempo"=>"140", "prerequisite_ids"=>["", "3", "4"]}, "commit"=>"Save"} Unpermitted parameter: prerequisite_ids'`

BananaNeil
  • 10,322
  • 7
  • 46
  • 66
AHinson
  • 661
  • 2
  • 7
  • 15

1 Answers1

0

It looks like there are a couple of problems here:

One is that you are using Prerequisite.new(...) when I think you want to be using Prerequisite.create(...)

So your create action should be:

def create
  @lesson = Lesson.new(lesson_params)

  if @lesson.save
    if @lesson.prerequisite_ids.length > 0
      @lesson.prerequisite_ids.each do |p|
        Prerequisite.create(lesson_id: @lesson.id, prerequisite_lesson_id: p)
      end
    end
    flash[:notice] = "Lesson created..."
    redirect_to root_url
  else
    render :new
  end
end

The other is this (from your logs):

"lesson"=>{"name"=>"Lesson 6", "high_tempo"=>"200", "low_tempo"=>"100", "interval"=>"10", "advance_tempo"=>"140", "prerequisite_ids"=>["", "3", "4"]}, "commit"=>"Save"} Unpermitted parameter: prerequisite_ids'`

In your controller, you are permitting

def lesson_params
  params.require(:lesson).permit(
    :name,
    :high_tempo,
    :low_tempo,
    :interval,
    :advance_tempo,
    prerequisites_attributes: [
      :lesson_id,
      :prerequisite_lesson_id
    ]
  )
end

But note that your actual data is coming in as "lesson" => {..., "prerequisite_ids"=>["", "3", "4"]}

So you should instead permit like this:

def lesson_params
  params.require(:lesson).permit(
    :name,
    :high_tempo,
    :low_tempo,
    :interval,
    :advance_tempo,
    prerequisite_ids: []
  )
end

Additionally, it looks like your prerequisite_ids are including a value that is an empty string. Based on this post, it looks like you may need to add include_hidden: true to your select tag, like this:

<%= f.collection_select(:prerequisite_ids, Lesson.all, :id, :name, {}, {:multiple => true, include_hidden: true}) %>
Community
  • 1
  • 1
BananaNeil
  • 10,322
  • 7
  • 46
  • 66
  • This is what I'm seeing in the log: 'Parameters: {"utf8"=>"✓", "authenticity_token"=>"THaOnTF4jPv6duqqyxRMP7IIfpEPS9MrFJ5Ib50WohwyvP8dd085P0UQeD47jW2a65tI3eNeHVU0IZwL6hYpWw==", "lesson"=>{"name"=>"Lesson 6", "high_tempo"=>"200", "low_tempo"=>"100", "interval"=>"10", "advance_tempo"=>"140", "prerequisite_ids"=>["", "3", "4"]}, "commit"=>"Save"} Unpermitted parameter: prerequisite_ids' – AHinson Nov 01 '16 at 22:41
  • I've updated my answer to address another problem, which I believe you are seeing. – BananaNeil Nov 01 '16 at 22:48
  • I still seem to be getting the same "Unpermitted parameter" error unfortunately. – AHinson Nov 01 '16 at 22:51
  • Looks like for an array parameter, you must permit it as such. I've just updated the last bit of my answer, could you give that a try? – BananaNeil Nov 01 '16 at 22:54
  • 'Parameters: {"utf8"=>"✓", "authenticity_token"=>"bjCBqvh+babDcXymJigWsCuP9AVKsRo2ZbvkEXXXMtwQ+vAqvknYYnwX7jLWsTcVchzCSaak1EhFBDB1Ate5mw==", "lesson"=>{"name"=>"Testing", "high_tempo"=>"200", "low_tempo"=>"100", "interval"=>"10", "advance_tempo"=>"140", "prerequisite_ids"=>["", "3", "4"]}, "commit"=>"Save"} Prerequisite Load (0.4ms) SELECT "prerequisites".* FROM "prerequisites" WHERE "prerequisites"."id" IN (3, 4) Completed 500 Internal Server Error in 27ms (ActiveRecord: 0.9ms) ActiveRecord::AssociationTypeMismatch (Prerequisite(#69945275660660) expected, got NilClass(#5898200)):' – AHinson Nov 01 '16 at 23:04
  • Trying to figure out what is causing it. The array is submitted with a "" item in it for some reason, and that seems like it could be causing the error. – AHinson Nov 01 '16 at 23:05
  • Looks like you may need to add `:include_hidden => true` to your select tag. There is a post about it here: http://stackoverflow.com/questions/8929230/why-is-the-first-element-always-blank-in-my-rails-multi-select-using-an-embedde I've updated my answer – BananaNeil Nov 01 '16 at 23:13
  • If that doesn't work, you can always as this as your first line of your controller action: `lesson_params[:prerequisite_ids].select!(&:present?)`, which will remove the empty value from the array. – BananaNeil Nov 01 '16 at 23:18