我正在实施pluginaweek's state_machine gem。我将代码缩小到这一点,这样我就可以更容易地理解这个问题了。我们假设我现在只有一个状态:
class Event < ActiveRecord::Base
state_machine :status, :initial => :active_offer do
end
def status
'Active Offer'
end
end
通过播种或浏览器创建新的Event对象时遇到的错误是{: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。我最初没有这样做,因为我已经有了省份等的州attr,所以我将其迁移到:address_state。
答案 0 :(得分: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.expire
或if @event.expired
等内容进行转换。如果您想要自动化,则需要whenever。