ruby-on-railsruby-on-rails-4rails-activerecordhas-and-belongs-to-many

Create a form that adds new rows to a join table


In Rails 4, how can I make a form that creates new rows in a join table, in a has_many, through association? Specifically, what do I pass into my check_box() input?

Example: Students enroll in many Courses. This is a has_many to has_many association. My join table is "student_course_assignments".

Models:

Student
has_many :student_course_assignments
has_many :courses, through: :student_course_assignments
accepts_nested_attributes_for :student_course_assignments

Course
has_many :student_course_assignments
has_many :students, through: :student_course_assignments

StudentCourseAssignment
belongs_to :student
belongs_to :course

Controller Students

def show
  @student.student_course_assignments.build
end

View at myapp.com/student/1

# This form lets you add new rows to student_course_assignments, for the given student.
<%= form_for @student do |f| %>
  <%= f.fields_for :student_course_assignments do |join_fields| %>
    <% Courses.all.each do |course| %>
      <%= join_fields.checkbox(course.id) %>  # What should be passed in here??
      <span><%= course.name %></span>
    <% end %>
  <% end %>
<% end %>

Any advice on how to structure the form that shows checkboxes for every course, and lets me check a course that should be added to the student_course_assignemnts db would be greatly appreciated.


Solution

  • ActiveRecord

    You'll probably be looking for the << ActiveRecord feature:

    #config/routes.rb
    resources :students do
        #could be a member route
        match :add, via: [:get, :post]
    end
    
    #app/controller/students_controller.rb
    def add
        @student = Student.find(params[:student_id])
        if request.post?
            @course = Course.find(params[:course_id])
            @student.student_course_assignments << @course
        end
    end
    
    #app/views/students/add.html.erb
    <%= form_for @student, method: :post do |f| %>
        <%= f.text_field :course_id %>
    <% end %>
    

    Yours

    For your code, I'd do this:

    <%= form_for @student do |f| %>
        <% Courses.all.each do |course| %>
          <%= f.checkbox :student_course_assignment_ids, course.id %>
          <span><%= course.name %></span>
      <% end %>
    <% end %>
    

    This will populate the collection of :student_course_assignments for you I think. You shouldn't have to use accepts_nested_attributes_for if you're not creating new course objects