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

xeruzo · 2019年09月25日 · 最后由 xeruzo 回复于 2019年09月26日 · 3411 次阅读
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 后就出问题了。。。

这个就是 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 提一下
  • 最后感谢你的建议,我去翻一下文档,看看是否适合当前项目
需要 登录 后方可回复, 如果你还没有账号请 注册新账号