2012-12-19 3 views
1

나는 두 개의 멋진 보석 인 state_machine과 cancan을 최근에 내 레일 어플리케이션에 사용하고 있지만 깨끗하게 통합하는 가장 좋은 방법은 궁금합니다. 현재 컨트롤러에서 승인 한 작업을 수행하는 버튼에 상태 전환을 배치했습니다. 이것은 완벽하게 작동합니다. 누가 해당 작업을 수행 할 수 있는지 제한 할 수 있습니다.레일즈 cancan 및 상태 머신 - 인증 상태

사용자에게 편집 양식의 개체 상태를 변경할 수있는 권한을 부여하고 싶습니다. state_machine은 해시에서 state_event 키를 수행 할 작업 값으로 선택합니다 (state_machines 콜백을 모두 통과하게 됨). 이것은 update_attributes의 params 해시와 함께 전달 될 수 있습니다. 환상적.

그러나 특정 사용자 만 개체를 ​​특정 상태로 변경할 수 있어야합니다. 어떻게 구현할 수 있습니까? 아이디어는

params['state_event']=='move_to_x' 

일부 사용자에 대한 구제해야하지만, 다른 사람을 위해 허용 될 것입니다. 그것은 또한 내가 이것을 구현할 때까지 영리한 사용자가 허가를 받아서는 안되는 경우에도 상태 이벤트 내부에 어떤 것을 게시 할 수있는 권한 부분입니다.

답변

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를 사용하여 사용자가 전환 할 수있는 상태 목록을 가져올 수는 없지만 일종의 도우미 메서드를 통해이를 수행 할 수 있어야한다는 것입니다.

UPDATE : 레이어와 같은 관점에서 그 상태를 얻는 것은 내가 간단한 양식을 사용하고

충분히 간단하지만 그래서 난 그냥 수집 입력이되도록 모두 함께 선택 잎

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

객체가 통과 할 수있는 변환, 사용자가 권한을 부여 받았음을 나타냅니다.

1

두 가지 방법으로이 작업을 수행 할 수 있습니다. 전환에 조건을 추가하십시오. 다음과 같이 입력하십시오 :

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))은 유효한 테스트하지 않습니다 - 당신이 당신의 자신의 필요합니다.

또는 사용자 정의 상태 머신 유효성 검사를 사용할 수는 :

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

또 다른 흥미로운 게시물은 여기에 있습니다 : :

state :first_gear, :second_gear do 
    validate :speed_is_legal 

워드 프로세서에서 이것에 대해 발견주의있다 State Machine, Model Validations and RSpec

우리는 우리의 응용 프로그램에서 두 가지 방법을 성공적으로 사용합니다.

- 대중을위한 편집 -

모델에 CURRENT_USER 사용에 대한 주석에 대해 생각. 우리는 코드에 대한 재검토를 생각했습니다. 우리가 이것을 사용했던 한 두 가지 예에서 우리는 current_user 메소드를 완전히 제거 할 수 있음을 깨달았습니다. 따라서 보안상의 위험을 제거 할 수 있습니다. 이것은 분명히 모델 has_many 사용자를 가정

self.users.first 

: 대신 User.current_user를 호출

, 우리는 교환. 그런 다음이 사용자의 능력을 호출 할 수 있습니다.

+0

나는 당신이하려는 것을 얻는다. 그러나 나는 모델 레벨의 메소드처럼 나쁜 Current_user를 사용하여 인상을 받고있었습니다. –

+0

나쁘지 않은데, 제 의견으로는 일반적인 것이 아닙니다. 우리는 상태 기계와 같은 것들을 위해해야하기 때문에 그렇게합니다. '현재 사용자 모델'을 검색하면 나쁜 이유와 왜 그렇지 않은지에 대한 게시물 모음을 찾을 수 있습니다. – simonmorley

+0

나는 모델 레이어에서 현재 사용자를 사용하는 것을 싫어하는 부분이 있음을 짐작할 수 있습니다. 내가 가지고있는 가장 큰 걱정거리는 내가 레일에서 벗어난 것이다. 또는 레일 c에서 모델을 사용하려고합니다. 나는 현재 사용자 메소드를 거기에서 사용할 수있게 만들 필요가 있고 유닛 테스트에서도 접근 할 수 있도록해야한다. 어색해 보입니다. 아직도 말했듯이 인증 코드가 내 모델을 만지는 것을 막아 준 내 솔루션에 만족합니다. 그것은 cancan이 어떻게 작동하는지에 대한 느낌과 비슷한 컨트롤러에 머물러 있습니다. –