我一直在使用这两个真棒宝石,state_machine和康康舞最近在我的Rails应用程序,但我很好奇,他们干净利落地整合的最佳途径。 目前,我已经放置在参加由控制器授权操作的按钮状态转换。 这完美的作品,我可以限制谁可以执行该操作。
我想给用户更改编辑表单对象的状态以及能力。 我注意到,state_machine将拿起的哈希state_event键,与动作的值,从而进行(所以它会经过所有state_machines回调)。 这可以用在update_attributes方法params哈希表传递英寸 太棒了。
但是只有特定的用户应该能够改变对象的某些状态。 我将如何实现这个? 这个想法是,
params['state_event']=='move_to_x'
要摆脱困境,对于一些用户,但不允许他人。 它还涉及我,直到我实现这个授权部分聪明的用户可以发布状态事件中做任何事,即使他们不应该被允许呢!
你可以通过两种方式做到这一点。 要么是把一个条件上的转变。 事情是这样的:
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注释思考。 我们想了重新阅读我们的代码。 在我们使用这个一个两个例子,我们意识到,我们可以彻底去除CURRENT_USER方法,从而消除任何安全隐患。
与其说User.current_user,我们交换到:
self.users.first
这显然假定模型的has_many用户。 然后,您可以拨打该用户的能力
这实际上并没有那么可怕,因为我以为,我已经在不断的代码,而短期和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获得可用状态,用户可以过渡到一个列表,但它应该有可能通过某种helper方法来做到这一点。
更新:虽然像层视图得到这些国家是很容易
我使用的简单的形式,所以我只是一个集合的输入,使得
..... collection: @object.status_transistions.select{|t| can? t.event, @object}
这让选择与所有transistions对象可以顺利通过,并且用户还有权做:)。