我似乎无法让state_machine
gem(http://github.com/pluginaweek/state_machine/)处理现有记录(它在新记录上正常工作)。
这是我的模特:
class Comment < ActiveRecord::Base
state_machine :state, :initial => :pending do
event :publish do
transition all => :published
end
end
end
这是一个IRB会话,它演示了这个问题(我做了ActiveRecord::Base.logger = Logger.new(STDOUT)
以便于阅读):
>> c = Comment.new
=> #<Comment id: nil, song_id: nil, author: nil, body: nil, created_at: nil, updated_at: nil, state: "pending">
>> c.state
=> "pending"
>> c.publish
Comment Create (0.6ms) INSERT INTO "comments" ("updated_at", "body", "author", "song_id", "created_at", "state") VALUES('2009-11-02 02:44:37', NULL, NULL, NULL, '2009-11-02 02:44:37', 'published')
=> true
>> Comment.last.state
Comment Load (0.4ms) SELECT * FROM "comments" ORDER BY comments.id DESC LIMIT 1
=> "published"
>> c = Comment.create
Comment Create (0.5ms) INSERT INTO "comments" ("updated_at", "body", "author", "song_id", "created_at", "state") VALUES('2009-11-02 02:44:47', NULL, NULL, NULL, '2009-11-02 02:44:47', 'pending')
=> #<Comment id: 4, song_id: nil, author: nil, body: nil, created_at: "2009-11-02 02:44:47", updated_at: "2009-11-02 02:44:47", state: "pending">
>> c.publish
=> true
>> c.save
=> true
>> Comment.last.state
Comment Load (0.4ms) SELECT * FROM "comments" ORDER BY comments.id DESC LIMIT 1
=> "pending"
即,当我publish
未保存的评论时,一切正常,但当我尝试发布已保存的评论时,没有任何反应。
=> true
>> a = Comment.last
Comment Load (1.3ms) SELECT * FROM "comments" ORDER BY comments.id DESC LIMIT 1
=> #<Comment id: 3, song_id: nil, author: nil, body: nil, created_at: "2009-11-03 03:03:54", updated_at: "2009-11-03 03:03:54", state: "pending">
>> a.state
=> "pending"
>> a.publish
=> true
>> a.state
=> "published"
>> a.state_changed?
=> false
即使状态实际发生了变化,state_changed?
返回false,因此当我调用save
时,Rails不会更新相应的数据库行。
当我关闭部分更新时,它会有效,但在我尝试state_will_change!
时则不行:
>> Comment.partial_updates = false
=> false
>> c = Comment.create
Comment Create (0.5ms) INSERT INTO "comments" ("updated_at", "body", "author", "song_id", "created_at", "state") VALUES('2009-11-07 05:06:49', NULL, NULL, NULL, '2009-11-07 05:06:49', 'pending')
=> #<Comment id: 7, song_id: nil, author: nil, body: nil, created_at: "2009-11-07 05:06:49", updated_at: "2009-11-07 05:06:49", state: "pending">
>> c.publish
Comment Update (0.9ms) UPDATE "comments" SET "created_at" = '2009-11-07 05:06:49', "author" = NULL, "state" = 'published', "body" = NULL, "song_id" = NULL, "updated_at" = '2009-11-07 05:06:53' WHERE "id" = 7
=> true
>> Comment.last.state
Comment Load (0.5ms) SELECT * FROM "comments" ORDER BY comments.id DESC LIMIT 1
=> "published"
>> Comment.partial_updates = true
=> true
>> c = Comment.create
Comment Create (0.8ms) INSERT INTO "comments" ("updated_at", "body", "author", "song_id", "created_at", "state") VALUES('2009-11-07 05:07:21', NULL, NULL, NULL, '2009-11-07 05:07:21', 'pending')
=> #<Comment id: 8, song_id: nil, author: nil, body: nil, created_at: "2009-11-07 05:07:21", updated_at: "2009-11-07 05:07:21", state: "pending">
>> c.state_will_change!
=> "pending"
>> c.publish
=> true
>> c.save
=> true
>> Comment.last.state
Comment Load (0.5ms) SELECT * FROM "comments" ORDER BY comments.id DESC LIMIT 1
=> "pending"
修改
更奇怪:
>> a = Comment.last
Comment Load (1.2ms) SELECT * FROM "comments" ORDER BY comments.id DESC LIMIT 1
=> #<Comment id: 5, song_id: nil, author: nil, body: nil, created_at: "2009-11-02 06:33:19", updated_at: "2009-11-02 06:33:19", state: "pending">
>> a.state
=> "pending"
>> a.publish
=> true
>> a.state
=> "published"
>> a.save
=> true
>> a.id
=> 5
>> Comment.find(5).state
Comment Load (0.3ms) SELECT * FROM "comments" WHERE ("comments"."id" = 5)
=> "pending"
比较:
>> a = Comment.last
Comment Load (0.3ms) SELECT * FROM "comments" ORDER BY comments.id DESC LIMIT 1
=> #<Comment id: 5, song_id: nil, author: nil, body: nil, created_at: "2009-11-02 06:33:19", updated_at: "2009-11-02 06:33:19", state: "pending">
>> a.state = "published"
=> "published"
>> a.save
Comment Update (0.6ms) UPDATE "comments" SET "state" = 'published', "updated_at" = '2009-11-02 08:29:34' WHERE "id" = 5
=> true
>> a.id
=> 5
>> Comment.find(5).state
Comment Load (0.4ms) SELECT * FROM "comments" WHERE ("comments"."id" = 5)
=> "published"
答案 0 :(得分:2)
我在3年后遇到了同样的问题所以值得回答这里以节省其他人的时间。
您需要在表中使用名为“state”的列,因此state_machine将能够使状态持久。
只需将其添加到您的迁移 - t.string:state
即可答案 1 :(得分:1)
是否可以使用发布**!**而非发布
重试状态转换答案 2 :(得分:1)
没有贡献任何有用的东西,但我只想说我在整个应用程序中的多个state_machines中也在努力解决这个错误。我无法切换到AASM,因为我需要在同一个模型中拥有多个state_machine ......太令人沮丧了!
无论如何,你并不孤单,它肯定还需要一个解决方案。
答案 3 :(得分:1)
关闭部分更新后是否还会发生这种情况? Comment.partial_updates = false
如果是这样,那么我们知道问题在于识别脏对象。在拨打c.state_will_change!
c.publish
答案 4 :(得分:1)
模型在初始化时是否调用超级?
state_machine文档说状态需要初始化
def initialize
@seatbelt_on = false
super() # NOTE: This *must* be called, otherwise states won't get initialized
end
答案 5 :(得分:0)
同样,不是你问题的真实答案,但在这里我试图模拟你的会话:
>> c = Comment.new
=> #<Comment id: nil, body: nil, created_at: nil, updated_at: nil, state: "pending">
>> c.state
=> "pending"
>> c.publish
=> true
>> Comment.last.state
=> "published"
>> c = Comment.create
=> #<Comment id: 4, body: nil, created_at: "2009-11-05 07:12:53", updated_at: "2009-11-05 07:12:53", state: "pending">
>> c.publish
=> true
>> c.save
=> true
>> Comment.last.state
=> "published"
正如您所看到的,它对我来说是预期的。检查了两次。 (我创建了一个带有body和state属性的模型,并将代码放入其中。)
答案 6 :(得分:0)
尝试从定义中删除:状态:
FROM: state_machine:state,:initial =&gt; :待定
要 state_machine:initial =&gt; :待定