[英]Incrementing enums in Ruby?
假設我在模型中有enum stage [:one, :two, :three, :four]
。
當調用控制器動作next_stage
(用戶單擊按鈕以將其發送到下一個階段)時,我想從X階段逐步轉到Y階段。最簡單的方法是什么? 我目前使用的是重大案件,但我覺得我可以做得更好。 我將提供用例:
Class MyController
def next_stage
# @my_controller.stage => "two"
@my_controller.stage.value++ unless @my_controller.stage.four?
# @my_controller.stage => "three"
end
end
老實說,如果您要存儲以特定順序移動的狀態,則應使用狀態機。 https://github.com/aasm/aasm支持使用枚舉存儲狀態。 你可以做這樣的事情;
aasm :column => :stage, :enum => true do
state :stage1, :initial => true
state :stage2
state :stage3
state :stage4
event :increment_stage do
transitions from: :stage1, to: :stage2
transitions from: :stage2, to: :stage3
transitions from: :stage3, to: :stage4
end
end
它不僅可以清理您的邏輯,而且測試會更簡單,並且您可以對不同事件進行各種回調。 這對於任何類型的工作流程也都非常好(例如,將帖子從審核轉移到批准等)
編輯:我還可以建議,如果您不想使用狀態機,那么至少要將此狀態轉移邏輯移入模型中? 控制器與訪問控制有關,模型與狀態有關。
model.read_attribute('foo')
,但是從我發現的枚舉中獲取整數的唯一方法是執行model.read_attribute('foo')
因此,您可以嘗試執行
def next_stage
@my_controller.update_column(:stage, @my_controller.read_attribute('stage')+1) unless @my_controller.four?
end
您的代碼似乎有點奇怪, @my_controller
是@my_controller
? 什么是stage
?
除此之外,如果我理解正確,那么您想要的是:
@my_controller[:stage] += 1 unless @my_controller.four?
枚舉以整數形式存儲在數據庫中,它們從0開始,以1為增量。因此,只需訪問原始屬性數據並將其遞增即可。
有一個gem simple_enum ,可以使用更強大的枚舉。
枚舉將允許您同時使用整數和/或符號,然后您可以執行以下操作
@my_controller.stage.value_cd += 1 unless @my_controller.stage.last_stage?
您可以將其與ActiveRecord / Mongoid一起使用,也可以與其他任何對象一起使用。
對於像Mongoid這樣的ORM,您的模型可能如下所示
class Project
as_enum :status, {
idea: 0,
need_estimate: 1,
in_progress: 2,
finished: 3,
paid: 4,
field: { type: Integer, default: 0 }
def next_step!
self.status_cd += 1 unless self.paid?
end
end
project = Project.new
project.status # => :idea
project.need_estimate? #=> false
project.next_step!
project.need_estimate? #=> true
我不知道我是否正確。 也許您可以嘗試以下方法:
Class MyController
def next_stage
@my_controller.stage.increment! :value rescue nil
end
end
新答案
好的,我想我會更好地了解您的需求。 這個怎么樣:
在模型中,使用哈希而不是數組設置Enum:
class MyClass < ActiveRecord::Base
enum stage: {one: 1, two: 2, three: 3, four: 4} #just makes more sense when talking about stages
end
然后,您可以使用當前狀態的索引:
Class MyController
def next_stage
# @my_controller.stage => "two"
current_stage = MyClass.stages[@my_controller.stage] # returns => 1
current_stage += 1 unless current_stage == 4 # returns => 2
@my_controller.update! stage: current_stage
# @my_controller.stage => "three"
end
end
如果我正確理解了文檔,這也可能會起作用:
Class MyController
def next_stage
# @my_controller.stage => "two"
@my_controller.update! stage: MyClass.stages[@my_controller.stage] + 1 unless @my_controller.stage == :four
# @my_controller.stage => "three"
end
end
這是袖手旁觀,可能可以通過某些方式進行清理。 我不能做太多實驗,因為我沒有在Rails應用程序中進行任何設置,而帶有枚舉。
舊的答案留給存檔。
def next_stage
self.next
end
編輯我看到枚舉,並認為您正在將可枚舉縮短為枚舉(如x.to_enum
)。 不太確定這在某種程度上對您不起作用。 您要求的不是丑陋的陳述。 您可以使用從該列獲取當前枚舉數的枚舉數來設置起點,終點為4(或:4,具體取決於編寫方式),並在枚舉數末尾進行救援以返回最大值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.