Ruby on Rails Enum存储值映射与UI显示问题求助
解决方案
先梳理你当前代码里的几个核心问题:
- 赋值方法里常量名写错:
M_CODE应该是J_CODE - 取值方法存在递归调用(
if status == 0会重复触发自身方法调用),会直接导致栈溢出 - 存取逻辑完全错位:数据库实际存储23/24,但取值时判断的是0/1,赋值时仅处理了0/1输入,没覆盖枚举符号/字符串的常见输入场景
最优方案:让Enum直接映射存储值
既然数据库要存23和24,直接把枚举的数值改成对应值,Rails会自动处理所有转换逻辑,不需要自己写存取器:
enum status: { draft: 23, published: 24 } I_CODE = 23 # 可保留,但与enum的draft值重复,也可以直接用Status[:draft]代替 J_CODE = 24 # 同理
这样实现后:
model.draft?/model.published?这类枚举自带方法会直接生效,判断数据库值是否为23/24- 赋值时
model.status = :draft/model.status = "draft"/model.status = 23都会自动将数据库值设为23 - 取值时
model.status直接返回"draft"或"published",UI可直接使用该值
若必须保留原Enum的0/1映射(不推荐)
如果因历史原因无法修改枚举数值,需要重写存取器,同时避免递归并覆盖所有输入场景:
enum status: { draft: 0, published: 1 } I_CODE = 23 J_CODE = 24 # 重写赋值方法 def status=(value) if value.blank? self[:status] = nil return end # 覆盖枚举符号、字符串、数值的输入场景 case value when :draft, "draft", 0 self[:status] = I_CODE when :published, "published", 1 self[:status] = J_CODE else self[:status] = nil # 未知值可设为nil或抛出错误,按需调整 end end # 重写取值方法,用read_attribute避免递归调用 def status stored_value = read_attribute(:status) case stored_value when I_CODE "draft" when J_CODE "published" else "----" end end
额外说明:原枚举生成的draft?/published?方法会失效(基于0/1判断),如果需要这类方法,需手动实现:
def draft? read_attribute(:status) == I_CODE end def published? read_attribute(:status) == J_CODE end
内容的提问来源于stack exchange,提问作者Kumar Nikhil
相关产品推荐
相关产品推荐

