在 rails model 里不免有些数据字段仅能取若干个离散的非数字值,这种情况的通用解决方案是在 model 里定义 tinyint 字段然后在 model 里添加这个属性的注释。比如一个商品 Deal 的状态可能有如下几种: ['审核中', '销售中', '未开始', '已结束', '已卖光', '已下架'] 那么可以定义:
t.integer :status, limit: 1, null: false, default: 0
然后在 model 里为这个字段注释:
STATUS = ['审核中', '销售中', '未开始', '已结束', '已卖光', '已下架']
取值则为
deal = Deal.new
Deal::STATUS[deal.status]
现在我的问题是,能不能在 concern 里定义一个可复用的方法,在实现之后 deal 有 enum_status 方法,使 class Deal extend Concern 后,deal.enum_status 能直接输出“审核中”而不是 0? 以下是初步想法:
def show_enum_columns
self.column_names.each do |x|
begin
column = self.const_get x.upcase! if self.send(x).is_a? Integer
self.define_method "enum_#{x}" do # 1
self.class.const_get(x.upcase!)[self.send(attr)] # 2
end if column.present?
rescue NameError
next
end
end
end
这里有两个问题:1. define_method 是私有方法;2. 这里的 self 需要指代 Deal.new,事实上这里是 Deal.new 还是 Deal?3. 这个方法需要在 extend 之后手动执行 Deal.show_enum_columns 生成方法,有没有办法使其自动在 extend 时就生成实例方法 enum_status?