3

Devise を使用してユーザーを認証しています。すべてのテーブルで global_location_id 列に基づいてデータを表示/非表示にする必要があります。現在の global_location_id の値は current_user.global_location_id から取得されます。モデルの 1 つに次のデフォルト スコープを追加しようとしました。

class Artifact < ActiveRecord::Base
default_scope where(:global_location_id => current_user.global_location_id)

しかし、次のエラーが発生します。

undefined local variable or method `current_user' for #<Class:0x8721840>

モデルで current_user が使用できないことを回避するために、アプリケーションコントローラーに以下を追加しました

class ApplicationController < ActionController::Base
   def set_global_location_id
    @global_location_id = current_user.global_location_id
   end

そして、コントローラーからメソッドを呼び出しました

class ArtifactsController < ApplicationController
   #Check to see if the user is logged in first
   before_filter :authenticate_user!
   before_filter :set_global_location_id

@global_location_id を追加するようにモデルのデフォルト スコープを変更しました

class Artifact < ActiveRecord::Base
  default_scope where(:global_location_id => @global_location_id)

しかし、これもうまくいきません。@global_location_id は、アプリケーション コントローラーで適切に設定されています。しかし、モデルでは空です。それを機能させる方法。

4

1 に答える 1

3

残念ながら、コントローラーで設定されたインスタンス変数をモデルのインスタンスと共有することはできません (スレッド ハッカーがなければ)。これは実際には良いことですが、そうしないとグローバル変数のように振る舞い、良いことよりも悪いことになります。

現在ログインしているユーザーの状態とモデルの間に厄介な結合が追加されるため、実際になぜこのようにしたいのか理解するのに苦労しています。コンソールで Artifact を見つけようとすると、 current_user が存在せず、そのインスタンス変数が使用できないため、深刻な問題が発生します。

これは、一歩下がって、自分が本当にやろうとしていることを自問するポイントです. 現在のユーザーの global_location_id に基づいて暗黙的に default_scope を作成する必要がある理由はありますか? 通常のスコープを作成して、代わりにコントローラーで使用できますか?

class Artifact < ActiveRecord::Base
  scope :by_global_location_id, lambda {|id| where(:global_location_id => id) }
end

class ArtifactsController < ApplicationController
  def index
    @artifacts = Artifact.by_global_location_id(current_user.global_location_id)
  end
end

このアプローチの利点の 1 つは、コードを読む人が default_scope の動作を追跡するのに多くの時間を費やす必要がないことです。

于 2012-12-20T02:03:07.850 に答える