How to update the has_and_belongs_to_many collection RESTfully?

I have two models created with help, student and class . They have many-to-many relationships implemented with has_and_belongs_to_many.
I would like to be able to change which class es student as well as student accepts each class. That is, I want to change the student class variable (adding and removing elements from it) and vice versa.
How to do it? If I remove a class from the student’s class list , it seems that I want to call an update on my student_controller. If so, what should I pass as a parameter to change the class variable? Another es class collection (with remote class )?
My other thought is to call some action on student_controller (say remove_class) and pass in the identifier of the class to be removed. It seems sensual, but not RESTful.

What is the best way to do this?

+5
source share
4 answers

The key to solving this is to correctly identify the resource you are modifying. In this case, the resource you are modifying is the relationship between the class and the student, which I will name Enrollment.

In Rails, it has become customary to use has_many :throughpreferably has_and_belongs_to_many. You might want to change your domain logic to match custom, but you can also win the trend if you are really sure that metadata should not be stored in relation to relationships.

One of the key ideas for REST is that RESTful resources do not need to map models. You should create EnrollmentsControllerand add a line in config / routes.rb:

map.resources :enrollments

Then you can create and delete your relations like this:

class EnrollmentsController < ApplicationController
    def create
       @student = Student.find(params[:student_id])
       @course = Course.find(params[:course_id])
       @student.courses << @course
       if @student.save
         #do happy path stuff
       else
         #show errors
       end
    end

    def destroy
       @student = Student.find(params[:student_id])
       @course = @student.courses.find(params[:course_id])
       @student.courses.delete( @course )
    end
end

:

<%= button_to "Enroll", enrollments_path(:student_id => current_student.id, :course_id => @course.id ), :method => :post %>
<%= button_to "Withdraw", enrollment_path(1, :student_id => current_student.id, :course_id => @course.id ), :method => :delete %>

1 , :enrollment_id , , Rails.

+8

REST, , , . , , . , .

:

REST , , , .

, , . , , , , _ .

, , .

0

, RESTfully. , , .

SO Cascade Deleting on Rails.

0

can you have two nested resources?

depending on whether you have params[:class_id](please don’t say that you named your model class!), or you have one params[:student_id], which you could determine who the object is for which the operation is performed (see the attached sample creation with one side):

class SchoolClassController < ApplicationController

before_filter :get_school_class, :except => [:new, :create, :index]
before_filter :get_student

def create
  get_school_class(false)
  get_student(false)
  if @school_class
    if @student
      (@school_class.students << @student)
    else
      redirect_to "/" and return
    end
  else
    @school_class = SchoolClass.new(params[:school_class])
  end
  if @school_class.save
    redirect_loc = @student ? student_school_class_path(@student, @school_class) : school_class_path(@student)
    redirect_to redirect_loc and return
  else
    redirect_to "/"
  end

end

private

def get_school_class(will_redirect=true)
  begin
    @school_class = SchoolClass.find(params[:id])
  rescue AR::RNF
    (redirect_to "/" and return false) if will_redirect
  end
end

def get_student(will_redirect=true)
  if params[:student_id]
    begin
      @student = Student.find(params[:student_id])
    rescue AR:RNF
      (redirect_to "/" and return false) if will_redirect
    end
  end
end

end

I'm sorry for the mistakes! Indeed, it should be used as a theoretical example.

0
source

All Articles