0

我正在实施pluginaweek 的 state_machine gem。我将代码缩小到这个范围,以便我可以更轻松地理解问题。假设我现在只有一个状态:

class Event < ActiveRecord::Base
  state_machine :status, :initial => :active_offer do
  end

  def status
    'Active Offer'
  end
end

通过播种或浏览器创建新事件对象时出现的错误是{:status=>["is invalid"]}.

计划是包含所有不同状态的条件并将自定义字符串返回到视图。整个项目的视图当前都使用该.status语法,所以我正在尝试顺利安装它。我基于阅读 api 文档开始了这个解决方案:

http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Overwriting+default+accessors

这是我的主要目标:

def status
  if read_attribute(:status) == 'active_offer' && self.start_date > Time.now
    'Active Offer'
  elsif read_attribute(:status) == 'active_offer' && self.start_date < Time.now
    'Expired'
  else read_attribute(:status) == 'cancelled'
    'Cancelled'
  end
end

我该怎么做才能使 state_machine 块使用普通访问器以便它获取数据库值?

银弹解决方案:

我的主要问题是访问器覆盖status。当 state_machine 代码运行时,它正在通过我的访问器覆盖读取当前状态,因此返回了一个自定义字符串,这是一个无效状态。我不得不让 state_machine 使用 :state。我最初没有这样做,因为我已经有一个省等的:state attr,所以我将它迁移到:address_state。

4

1 回答 1

1

很确定您只需要更改定义的名称:

class Event < ActiveRecord::Base
  state_machine :status, :initial => :active_offer do
  end

  def active_offer
    'Active Offer'
  end
end

编辑:

如果我理解正确,我不确定我是否正确,这将起作用:

state_machine :status, initial: :active_offer do
  event :expire do
    transition all => :expired
  end
  event :cancel do
    transition all => :cancelled
  end
end

然后你可以if...在控制器或其他东西中做你的陈述等,并用类似的东西来转换它们@event.expireor if @event.expired。如果您希望它自动化,您将需要像任何时候这样的东西。

于 2013-02-13T22:46:53.067 回答