Rails 对象某个字段用了 enumerize 这个 gem,attributes 方法获取的值被改写了,有什么解决办法吗?

xeruzo · 2019年09月25日 · 最后由 xeruzo 回复于 2019年09月26日 · 665 次阅读
class User
 # 有name, type_id 
  TYPE_ID = {admin: 1 , user: 2 }
# 用了 enumerize 这个gem
  extend Enumerize
  enumerize :type_id, :in => TYPE_ID , predicates: { prefix: true }

end

user = User.find(1)
# 引用gem后的变化
user.type_id = 'admin'
user.type_id_value = 1
# 现在的结果
user.attributes = {'id'=>1, 'name'=>'张三', 'type_id'=>'admin'}

# 期望的结果
user.attributes = {'id'=>1, 'name'=>'张三', 'type_id'=>1}

#暂时的办法,在当前类改写方法
# 不改写底层方法是怕影响其他
def attributes
  old_attributes = super
  old_attributes.each do |k, v|
    real_value = self.try([k, '_value'].join.to_sym)
    old_attributes.update(k=>real_value) unless real_value.nil?
  end
  old_attributes
end

我翻过gem相关的文档https://www.rubydoc.info/gems/enumerize/2.3.1 ,暂时没找到这方面的设置,源码有些看的不懂,希望大家给下解决建议。。。

出现此问题主要是原本项目是rails4 相应的gem的版本比较旧,所以当时是没有问题的,不会改写attributes 升级rails5和gem后就出问题了。。。

共收到 7 条回复

这个就是 gem 的 feature 吧

获取原始值可以试试 user.type_id_before_type_cast

coderliu 回复

单独的原始值是 字段+ _value就可以获取了 主要的问题点是 通过原方法attributes获取的值也被改写了,不是原始值

其实你这方法挺好的..抽成concerns给其他也需要的公用一下就好..

重构,用 Rails Enum

huacnlee 回复

测了一下 AR 自带的也是把 attributes 改成 string。

最好当作 feature,看看用了 enum 以后业务代码需要处理原始值是否合理。

如果期望的结果是拿着 1,2值去使用,那么你用枚举还费这么大劲造一堆hash对照值为的是什么呢?

我常用的组合是 ActiveRecord::Enum 搭配 这个 gem https://github.com/zmbacker/enum_help ,你可以试一下。

sandy_xu 回复
  • 平时直接获取的到的枚举结果是符合我目的的。况且在rails4时和旧版的gem是这样实现是没问题的。
  • 获取原始值,我只期望在attributes这个方法中实现,这里需要把数据序列化到redis以给其他项目以共享数据,很早之前就约定好都是给原始值的,只是升级新版后,不知道是rails5的问题还是gem更新的问题有变动了。
  • 经过大家的提醒,我这个featrue应该给那个gem提一下
  • 最后感谢你的建议,我去翻一下文档,看看是否适合当前项目
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册