2009-07-06 5 views
5

두 개의 스캐 폴드 생성 모델, 학생클래스이 있습니다. 그것들은 has_and_belongs_to_many로 구현 된 many-to-many 관계를 가진다.
나는이 학생의 각 클래스이 소요되는으로뿐만 아니라에있는 학생 말이지하는 클래스를 변경할 수 있도록하고 싶습니다. 즉, 학생클래스 변수를 수정 (항목을 추가 및 제거)하거나 그 반대로 수정하고 싶습니다.
어떻게하면 되나요? 내 students_controller에 갱신를 호출 할 같은
내가 클래스 목록
학생에서 클래스을 제거하고있어 경우, 그것은 보인다. 이 경우 클래스를 수정하기위한 매개 변수로 전달해야하는 변수는입니다. 클래스 (클래스이 적절히 제거 된 컬렉션)?
다른 생각은 students_controller (예 : remove_class)에서 어떤 조치를 호출하고 클래스의 ID를 제거하여 제거하는 것입니다. 이것은 현명하지만 RESTful은 아닙니다.
has_and_belongs_to_many 컬렉션을 어떻게 RESTful하게 업데이트합니까?

이 작업을 수행하는 가장 좋은 방법은 무엇입니까?

답변

8

수정해야 할 리소스를 올바르게 식별해야합니다. 이 경우 수정하려는 리소스는 클래스와 학생 간의 관계입니다.이를 Enrollment이라고합니다.

has_many :through을 우선적으로 사용하는 것은 레일에서 통상적으로 has_and_belongs_to_many이되었습니다. 사용자 정의에 맞게 도메인 논리를 변경하려고 할 수 있지만 관계에 대해 메타 데이터를 저장할 필요가 없다는 것이 확실한 경우 추세를 활용할 수도 있습니다.

REST의 핵심 아이디어 중 하나는 RESTful 리소스를 모델에 매핑 할 필요가 없다는 것입니다. 당신은 EnrollmentsController을 만들고 줄을 추가 config (설정) 할 수/routes.rb해야합니다

map.resources :enrollments 

그런 다음 생성 등처럼 관계를 삭제할 수 있습니다

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 %> 
:enrollment_id 가야와 구문 vineg의 작은 비트가 자리 표시 자 역할을 위 라인에

1 ar은 Rails 프레임웍의 의지를 좌지우지하고 있음을 상기시켜줍니다.

+0

덕분에, 그것은 두 가지 사소한 변경으로 매우 잘 작동했습니다 : 1. @ student.courses.destroy (params [: course_id])를 호출하면 당연히 찾고 있었기 때문에 ActiveRecord :: AssociationTypeMismatch를 받았습니다. 우선 올바른 코스 (@ student.courses.find (params [: course_id]))를 찾은 다음이를 제거하여이 문제를 해결했습니다. 2. 코스를 파괴하고 싶지 않고 연관성을 삭제하기 때문에 파괴 대신 삭제 호출을 사용했습니다. –

+0

효과가 좋았습니다. 변경 사항을 반영하기 위해 예제를 업데이트했습니다. – austinfromboston

0

정말 휴식 인 경우 클래스와 학생을 동시에 변경하거나 둘 다에 관계를 추가하거나 둘 다 삭제하는 것입니다. 업로드 된 모델이 자체 일관성이 있는지 확인한 후 이전 모델과 비교하여 필요한 모든 변경을 수행합니다. 이러한 변화가 계급 주도형인지 학생 주도형인지는 구현 세부 사항이됩니다.

두 더 많은 옵션은 :

당신은 클래스 또는 학생 중 하나가 관계를 소유 할 수 있도록함으로써, 나머지 상태 정보를 덜 중복 만들 수 있지만, 사용자의 요구에 맞지 않을 수 있습니다.

또한 관계 정보를 양측에 보관할 수 있지만 정식이라고 판단 할 수 있습니다. 예를 들어, 학생이 아닌 클래스가 학생을 소유 한 경우, 학생의 belongs_to에 대한 변경 사항은 무시됩니다.

나는 첫 번째 옵션을 선호하지만, 적어도 이것들을 고려해야한다고 생각합니다.

0

나는 둘 다 RESTful하게하고 싶지 않습니다. 둘 사이에 계단식 삭제 관계를 생성하면 더 많은 마일리지를 얻을 수 있습니다.

여기 Cascade Deleting on Rails에 대한 토론이 있습니다.

0

두 개의 중첩 된 리소스가있을 수 있습니까?

params[:class_id]이 있는지 여부에 따라 다릅니다 (모델 클래스라고하지 마십시오.) 또는 당신이 params[:student_id]하면되는 작업이 호출되고 같은 객체가되는 말할 수 있었다는 것을() 한면에 부착 작성 샘플을 참조하십시오

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 

변명 오류를! 이론적 인 예제로 사용되어야합니다.

관련 문제