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

xeruzo · 2019年09月25日 · 最后由 xeruzo 回复于 2019年09月26日 · 3509 次阅读
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 提一下
  • 最后感谢你的建议,我去翻一下文档,看看是否适合当前项目
需要 登录 后方可回复, 如果你还没有账号请 注册新账号