1

私は最近、2つの素晴らしいgem、state_machineとcancanをrailsアプリケーションで使用していますが、それらをきれいに統合するための最良の方法に興味があります。現在、コントローラーによって承認されたアクションを実行するボタンに状態遷移を配置しました。これは完全に機能します。そのアクションを実行できるユーザーを制限できます。

編集フォームでもオブジェクトの状態を変更できるようにしたいと思います。state_machineがハッシュ内のstate_eventキーを取得し、実行するアクションの値を取得することに気付きました(したがって、state_machinesのすべてのコールバックを通過します)。これは、update_attributesのparamsハッシュを使用して渡すことができます。素晴らしい。

ただし、特定のユーザーのみがオブジェクトを特定の状態に変更できる必要があります。これをどのように実装しますか?アイデアは

params['state_event']=='move_to_x'

一部のユーザーには保釈する必要がありますが、他のユーザーには許可する必要があります。また、これを実装するまでは、許可されるべきではない場合でも、賢いユーザーが状態イベント内で何かを投稿できる承認部分であるため、私も懸念しています。

4

2 に答える 2

1

これは2つの方法で行うことができます。遷移に条件を設定することによって。このようなもの:

 transition :from => :parked, :to => :idling, :if => :valid_user

そして、モデルにvalid_userメソッドを作成します。

def valid_user
  if User.current_user.has_role?(xyz)
    do baa
  end
end

(User.current_user.has_role?(xyz))は有効なテストではありません-独自のテストが必要になります。

または、カスタムステートマシン検証を使用できます。

 state :first_gear, :second_gear do
   validate :speed_is_legal

これについては、ドキュメントに警告があります。

http://rdoc.info/github/pluginaweek/state_machine/master/StateMachine/Integrations/ActiveModel

ここに別の興味深い投稿があります:

ステートマシン、モデル検証、およびRSpec

このアプリケーションでは、両方の方法を正常に使用しています。

-質量の編集-

モデルでcurrent_userを使用することについてのコメントについて考えます。私たちはそれについて考え、コードを読み直しました。これを使用した1つまたは2つの例では、current_userメソッドを完全に削除できるため、セキュリティリスクを排除できることがわかりました。

User.current_userを呼び出す代わりに、次のように交換しました。

 self.users.first 

これは明らかに、モデルにhas_manyユーザーがいることを前提としています。その後、このユーザーの能力を呼び出すことができます

于 2012-12-19T08:32:05.297 に答える
0

これは実際には思ったほどひどいものではありませんでした。コードをかなり短くし、current_userをモデルから除外する方法で実行しました(非常に大きなプラス)。

秘訣は、コントローラーで再度承認を呼び出すことでした。

基本的に

def update
  authorize! params[:object][:state_event].to_sym, @object unless params[:object][:state_event].empty?
  .... etc
end

このようにして、Ability.rbでエイリアスを作成できます。したがって、アクションを実行できるユーザーは許可され、実行できないユーザーは例外を取得します。これは、ボタンベースのアクションで使用するのと同じ機能なので、これも素晴らしいです。

唯一の注意点は、@ object.state_transistionsを使用して、ユーザーが遷移できる使用可能な状態のリストを取得できないことですが、何らかのヘルパーメソッドを介してこれを実行できるはずです。

更新:レイヤーのようなビューでこれらの状態を取得するのは簡単ですが

私は単純なフォームを使用しているので、次のようなコレクション入力だけです

 ..... collection: @object.status_transistions.select{|t| can? t.event, @object}

これにより、オブジェクトが通過できるすべてのトランジションが選択され、ユーザーにも実行が許可されます:)。

于 2012-12-20T03:57:44.153 に答える