Rails 4 has_many through association nested form using ajax

548 views Asked by At

I have three models:

class Course < ActiveRecord::Base
    validates :title, presence: true

    has_many :enrollments
    has_many :users, through: :enrollments

    accepts_nested_attributes_for :enrollments
end

class Enrollment < ActiveRecord::Base
    belongs_to :user
    belongs_to :course

    enum type: { instructor: 0, student: 1 }
end

class User < ActiveRecord::Base
    has_many :enrollments
    has_many :courses, through: :enrollments
end

Currently when a user creates a course, the association is created as expected (the enrollment object is created as well). However, I'm trying to figure out the most conventional way to immediately assign the enrollment object's type to be 0.

Because I'm using React as my front-end framework, I attempt this through an ajax request.

var NewCourseForm = React.createClass({

  submit: function() {
    var params = {
      course: {
        title: this.refs.title.getDOMNode().value,
        enrollments_attributes: {
          type: 0
        }
      }
    };

    $.ajax({
      type: 'POST',
      url: '/courses',
      data: params,
      success: this.handleData
    });
  },

  handleData: function(response) {
    console.log(response);
  },

  render: function() {
    return (
      <div>
        <h1>New Course</h1>

        <input type='text' placeholder='Title' ref='title' />

        <br />

        <button onClick={this.submit}>Submit</button>
      </div>
    );
  }

});

This is my courses_controller.rb

class CoursesController < ApplicationController
  def index
    @courses = Course.all
  end

  def show
    @course = Course.find(params[:id])
  end

  def new
  end

  def create
    @course = current_user.courses.create(course_params)

    respond_to do |format|
      format.html { redirect_to action: :index }
      format.json { render json: @course }
    end
  end

  private

  def course_params
    params.require(:course).permit(:title, enrollments_attributes: [:type])
  end
end

Right now I get an error that says:

Completed 500 Internal Server Error in 23ms (ActiveRecord: 2.8ms)

TypeError (no implicit conversion of Symbol into Integer):

Any help would be appreciated. Thanks!

1

There are 1 answers

0
James B. On

This may be a bit late. But why don't you set it in your controller create action after it is passed through via ajax? Something like

def create
    @course = current_user.courses.create(course_params)
    @course.type = 0

    respond_to do |format|
      format.html { redirect_to action: :index }
      format.json { render json: @course }
end

You can also change your enrollment class with enums to be like this:

Class Enrollment
    enum type: [:teacher, :student]

The code above automatically assigns 0 and 1 to each role. Subsequently you can change your schema so it auto assigns a student role upon enrollment. That way the only thing that is assigned is the teacher role upon hitting the create action in your enrollments controller.

t.integer  "type",                default: 0