2011-11-20 61 views
10

我在我的一个Rails 3.1应用程序中使用了带有ActiveRecord的state_machine。我发现访问具有不同状态的记录的语法非常麻烦。是否有可能在不编写范围定义的情况下同时将每个状态定义为范围?state_machine中状态的命名范围

考虑下面的例子:

class User < ActiveRecord:Base 
    state_machine :status, :initial => :foo do 
    state :foo 
    state :bar 

    # ... 
    end 
end 

# state_machine syntax: 
User.with_status :foo 
User.with_status :bar 

# desired syntax: 
User.foo 
User.bar 

回答

2

我也需要此功能,但state_machine没有什么相似的。虽然我发现这个gist,但aasm在这种情况下似乎是更好的状态机替代方案。

+0

谢谢,这确实很有用。我发现'state_machine' gem在我的情况下更好,除了范围问题。 – Andrew

16

我加入以下我的模型:

state_machine.states.map do |state| 
    scope state.name, :conditions => { :state => state.name.to_s } 
end 

如果算上这是不知道“手写范围定义?”

+0

请注意,这个Lars代码需要在state_machine块之后添加。 – tomaszbak

8

以防万一,如果有人还在寻找这一点,有以下方法,同时限定state_machine补充说:

class Vehicle < ActiveRecord::Base 
    named_scope :with_states, lambda {|*states| {:conditions => {:state => states}}} 
    # with_states also aliased to with_state 

    named_scope :without_states, lambda {|*states| {:conditions => ['state NOT IN (?)', states]}} 
    # without_states also aliased to without_state 
end 

# to use this: 
Vehicle.with_state(:parked) 

我喜欢用这个,因为永远不会有与国家名称冲突。你可以在state_machine's ActiveRecord integration page找到更多的信息。

好处是,它允许通过阵列,所以我经常做这样的事情:

scope :cancelled, lambda { with_state([:cancelled_by_user, :cancelled_by_staff]) } 
+0

OP已经知道这一点。他问他是否可以创建不同的命名范围:'Vehicle.parked'而不是'Vehicle.with_state(:parked)'。 –

+0

thnx奖金)))这就是它! – cubbiu

+0

请注意,在Rails 3中,named_scope已被重命名为scope。 – cubbiu

0

我会告诉你,可如果模型有多个state_machines也可以使用的方式。

即使在你的状态是整数的情况下它也可以工作。

def Yourmodel.generate_scopes_for_state_machines state_machines.each_pair do |machine_name, that_machine| 
    that_machine.states.map do |state| 
     # puts "will create these scopes: #{machine_name}_#{state.name} state: #{state.value} " 
     # puts "will create these scopes: #{machine_name}_#{state.name} state: #{state.name.to_s} " 
     # Price.scope "#{machine_name}_#{state.name}", :conditions => { machine_name => state.name.to_s } 
     Price.scope "#{machine_name}_#{state.name}", :conditions => { machine_name => state.value } 
    end end end 

Yourmodel.generate_scopes_for_state_machines