2012-12-18 2 views
2

레일스에서 ​​default_scope을 사용하여 is_deleted = true 값을 갖는 모든 것을 사이펀 아웃합니다 (이 값을 가진 것은 표시되지 않아야하지만 여전히 데이터베이스에 행을 유지하려고합니다) . 하지만 실제로 컨트롤러에서 하나의 컨트롤러 작업을 취소해야합니다 (set is_deleted = false).하지만 default_scope가 적용되기 때문에 실패합니다. default_scope는 레코드를 선택/생성 할 때만 적용되지만 업데이트 할 때는 적용되지 않습니다 (소스 : http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html).레일스 default_scope가 업데이트에 적용됨

default_scope는 레코드 만들기/작성 중에도 적용됩니다. 레코드 갱신 중 적용되지 않습니다.

나는 .unscoped 메서드를 사용할 수 있음을 알고 있지만 반 직관적 인 것으로 보인다. 문서를 오해하고 있습니까?

응용 프로그램/모델/post.rb

class Post < ActiveRecord::Base 
    default_scope where(:is_deleted => false) 

응용 프로그램/컨트롤러/posts_controller.rb

class PostsController < ApplicationController 
def undelete 
    @post = Post.update(params[:id], :is_deleted => false) 
    render :action => :success if @post.save 
end 

오류

찾을 수 없습니다 포스트 id = 1 [W 여기 "게시물". "is_deleted"= 'f']

답변

4

당신이 언급 한 문서에서 선 (The default_scope is also applied while creating/building a record. It is not applied while updating a record.가) default_scope 속성이 건물/제작의 모든 모델에 적용되는 것을 말한다 :

귀하의 경우

모든 새로운 기록 is_deleted 속성이 false로 설정해야합니다

하지만, 업데이트 할 때 db에서 레코드를 얻는 경우 하나의 속성 (예 : title)을 변경하고 save을 호출하십시오. is_deleted 속성은 작성시 발생하는 false으로 강제되지 않습니다.

그러나 update 방법을 사용 (you can check it here)는 단지 항상 default_scope

이 솔루션은 단지

class PostsController < ApplicationController 
def undelete 
    @post = Post.unscoped.update(params[:id], :is_deleted => false) 
    render :action => :success if @post.save 
end 
+1

완벽한 설명을 해주셔서 감사합니다. :) – bswinnerton

1

나는 당신이 의미론에 매달린 것 같아요. Rails는 업데이트하기 전에 레코드를 찾아야합니다. Rails가 레코드를 찾으려면 .unscoped 메소드를 사용해야한다. .unscoped 방법은 마지막 조건을 적용하지 레일을 알려줍니다

SELECT * FROM posts WHERE `id`=123 AND `is_deleted` = true AND `is_deleted` = false 

: 당신은 같은 것을 볼 수

raise Post.find(:id => id, :is_deleted => true).to_sql 

: 레일은 당신이 할 수있는 범위의 값을 적용하는 방법을 참조하십시오. 동일한 필드에 대한 추가 조건을 제공하더라도 Rails는 기본 범위를 건너 뛰지 않습니다. -

+0

아, 내가 볼 unscoped 방법을 사용하는 것입니다 사용하는 내부 find 사용합니다. 그래서 Post.update()는 실제로 Post.find()를 먼저 호출하고 있습니까?이는 완벽하게 이해할 수 있습니다. 그러나 문서는 업데이트시 default_scope을 사용하지 않는다는 것을 매우 혼란스럽게합니다. 그건 update()가 find()를 먼저 호출 한 이후로는 결코 작동하지 않을 것입니다. – bswinnerton

관련 문제