Именованные области для состояний в state_machine

Я использую state_machine с помощью ActiveRecord в одном из приложений Rails 3.1. Я нашел, что синтаксис для доступа к записям с разными состояниями является громоздким. Можно ли определить каждое состояние как область видимости одновременно, не указав вручную определения области?

Рассмотрим следующий пример:

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

Ответ 1

Мне также нужна эта функциональность, но state_machine не имеет ничего подобного. Хотя я нашел это gist, но aasm кажется лучшим вариантом альтернативы в данном случае.

Ответ 2

Я добавляю следующее к своим моделям:

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

Не уверен, считаете ли вы это как "определение определений области видимости вручную?"

Ответ 3

На всякий случай, если кто-то все еще ищет это, добавляются следующие методы при определении 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 ActiveRecord.

Бонус в том, что он позволяет передавать массив, поэтому я часто делаю что-то вроде:

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

Ответ 4

Я покажу вам способ, который можно использовать, если модель также имеет несколько 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