2

Railsでdefault_scopeを使用して、is_deleted = trueの値を持つものをすべて吸い上げています(この値を持つものは表示されないはずですが、データベースに行を保持したいです)。ただし、実際に何かを元に戻す必要があるコントローラーアクションが1つあります(is_deleted = falseを設定します)が、default_scopeが適用されているため、失敗します。default_scopeは、レコードの選択/作成時にのみ適用され、更新時には適用されないことを理解しています(ソース:http ://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html )。

default_scopeは、レコードの作成/作成中にも適用されます。レコードの更新中は適用されません。

.unscopedメソッドを使用できることは知っていますが、これは直感に反しているようです。ドキュメントを誤解していますか?

app / models / post.rb

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

app / controllers / 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の投稿が見つかりませんでした[WHERE"posts"。"is_deleted"='f']

4

2 に答える 2

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に設定されます

ただし、更新時に、データベースからレコードを取得する場合は、1つの属性(たとえばtitle)を変更して呼び出します。作成時に発生したようにsaveis_deleted属性は強制されません。false

ただし、update使用するメソッド(ここで確認できます)は内部を使用するだけfindで、常に内部を使用します。default_scope

unscoped解決策は、メソッドを使用することです

class PostsController < ApplicationController
def undelete
  @post = Post.unscoped.update(params[:id], :is_deleted => false)
  render :action => :success if @post.save
end
于 2012-12-18T17:13:10.720 に答える
1

あなたはセマンティクスに夢中になっていると思います。Railsは、レコードを更新する前に、レコードを見つける必要があります。Railsがレコードを見つけるには、.unscopedメソッドを使用する必要があります。Railsがスコープ値をどのように適用するかを確認するには、次のようにします。

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

次のように表示されます。

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

.unscopedメソッドは、最後の条件を適用しないようにRailsに指示します。同じフィールドに追加の条件を指定した場合でも、Railsはデフォルトのスコープをスキップしません。

于 2012-12-18T17:06:08.007 に答える