1

Is there a way to update a field relative to a many-to-many associations via form_for?

Theses are my models:

  class Grad < ActiveRecord::Base
    belongs_to :school
    has_many :grad_courses
    has_many :courses, through: :grad_courses
    accepts_nested_attributes_for :grad_courses, :courses
  end

  class Course < ActiveRecord::Base
    belongs_to :school
    has_many :grad_courses
    has_many :grads, through: :grad_courses
  end

  class GradCourse < ActiveRecord::Base
    belongs_to :grad
    belongs_to :course
  end

Here is the many-to-many migration with the extra property (semester):

  create_table "grad_courses", force: :cascade do |t|
    t.integer  "grad_id"
    t.integer  "course_id"
    t.integer  "semester"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

What i'm trying to do is add and update the relations with the semester information dynamically with a form collection set (using form_for and chosen).

<%= form_for @grad, html: {class: "form-horizontal"} do |f| %>
    ...    
       <% ([email protected]).each do |semester| %>
            <div class="form-group">
                <%= f.label :course_ids, "#{semester}º semestre", class: "col-sm-2 control-label"  %>
                <div class="col-sm-10">
                  <%= f.collection_select :course_ids, @courses, :id, :name, {include_blank: true}, {multiple: true, :class=>'chosen-select form-control'} %>
                </div>
            </div>
        <% end %>  
...   
    <% end %>

This way, it is creating and updating the grad_courses, but without the semester.

I've tried lot of things, but didn't had success.

I'm able to manage the semester's info directly, like in this post: http://stackoverflow.com/questions/2168442/many-to-many-relationship-with-the-same-model-in-rails#=

I could pass an array with a hidden field, and manage the form manually, but it would take too much work, so I was wondering if there is an easy way to do this.

Something like :grad_course[:course_id][:semester] in :grad params? Is it possible?

the grad_course_controller:

      def update
        respond_to do |format|
          if @grad.update(grad_params)
            format.html { redirect_to @grad, notice: 'Cursos adicionados com sucesso' }
          else
            format.html { render :edit }
          end
        end
      end

      private
        def set_grad
          @grad = Grad.find(params[:id])
        end

        def set_courses
           @courses = Course.where(school_id: @grad.school_id) 
           @gc = GradCourse.where(grad_id: @grad.id)
        end
list through.
        def grad_params
          params.require(:grad).permit(:name, :min, :max, :school_id, course_ids: [] )
        end

Update

I've been trying to solve this using Peter's advices, so I tried nested_attributes and fields_for. But I'm having problems with it too.

I need one collection_sellect for each semester (from 1 to Grad.max number), where the options will be the courses available for that semester (@courses), and for the selected ones a grad_course relation needs to be created or updated.

The problem with field_for is that one field is generated for every grad_course relation, and since each field is related with the grad_course.id I`m not able to add new ones properly.

Here is one of the tries i've made with fields for:

  <%= f.fields_for :grad_courses do |builder| %>
  <p>
    <%= builder.text_field :semester %><br />
    <%= builder.collection_select :course_id, @courses, :id, :name, {include_blank: true}, {multiple: true, :class=>'chosen-select form-control'} %>

  </p>
  <% end %>

with these changes in the grad_controller:

def grad_params
  params.require(:grad).permit(:name, :min, :max, :school_id, course_ids: [], grad_courses_attributes: [:id, :course_id, :grad_id, :semester ])
end
2
  • Why you don't use fields_for . that will be easier to do that. railscasts.com/episodes/196-nested-model-form-part-1 . You want to create @grad.max of grad_course. In controller just build it first then in view everything setting for you Commented Jan 29, 2016 at 3:13
  • "I could pass an array with a hidden field, and manage the form manually, but it would take too much work, so I was wondering if there is an easy way to do" Look at the size of your question! Rails... =/ Commented Jan 29, 2016 at 19:18

1 Answer 1

0

Have you tried to add the :course_ids on the permit list?

Like this:

def grad_params
  params.require(:grad).permit(:name, :min, :max, :school_id, :course_ids)
end
Sign up to request clarification or add additional context in comments.

2 Comments

Yes, actually it was a typo, it was working with :course_ids[] there. Now I'm trying with nested attributes, like Peter suggested above, and it's like these: def grad_params params.require(:grad).permit(:name, :min, :max, :school_id, grad_courses_attributes: [ :id, :course_id, :grad_id, :semester ]) end
can you update the code in the question? it will be easier to debug.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.