ruby-on-rails Rails将word或enum数组Map为整数或浮点值

dm7nw8vv  于 2023-03-20  发布在  Ruby
关注(0)|答案(2)|浏览(94)

我不知道这个问题叫什么,但是有没有可能通过以下方式在模型中创建一个列表:
array of word

equipment %w[foo bar kimi etc...]
equipcost %i[10 35 85 etc...]

enum

enum equipment: { foo: 10,
                  bar: 35,
                 kimi: 83,
                 etc...
               }

然后将多个保存在数组中,即

t.string "equipment_list", default: [], array: true

{ equipment_list => ["foo", "bar"] } or { equipment_list => [10, 35] }

然后,当通过@object.equipment_list调用该对象时,它将引用array of wordsenum
在视图中,我输入<%= @object.equipment_list %>,并显示foo和bar,或者,如果我在模型中,我可以使用一个方法,将这些值相加,得到总成本:

def cost
   e = self.equipment_list
   e.value
   e.inject(:+)
end

有没有ruby或rails的方法来实现这个目标?array of words的方法似乎是错误的,emun的方法只针对单个值。
我找到了this,但就像他们说的,它是一个索引,而不是实际值。

dauxcl2d

dauxcl2d1#

将列序列化为数组很少是一种好方法。
您需要的是一个equipments表,其中包含列namecost
这个表与另一个模型相关联,我将其命名为Store,仅作为示例:

# equipments.rb
class Equipment < ApplicationRecord
  has_and_belongs_to_many :stores
end

# stores.rb
class Store < ApplicationRecord
  has_and_belongs_to_many :equipments

  def equipment_cost
    equipments.pluck(:cost).sum
  end
end
mfuanj7w

mfuanj7w2#

将数据硬编码到应用程序中并不是一个好主意,除非您想在每次业务逻辑需要进行细微更改时更改代码,或者您喜欢在凌晨3点被调用。使用数组/JSON/HSTORE/Serialized text列实际上也不是一个好方法:

  • 无数据规范化
  • 错误的类型支持(无Decimal类型)
  • 无关联
  • 违反第一范式(1 NF)
  • 查询数据既困难又不那么高效。

而是创建一个联接表,在该表中可以存储商店和设备之间的关系以及描述这两个企业实体之间关系的任何附加数据:

class Equipment < ApplicationRecord
  has_many :store_equipments
  has_many :stores, through: :store_equipments
end

class Store
  has_many :store_equipments
  has_many :equipments, through: :store_equipments
end

# rails g model store_equipment store:belongs_to equipment:belongs_to cost:decimal
class StoreEquipment < ApplicationRecord
  belongs_to :store
  belongs_to :equipment
end

根据表/模型所连接的两个事物来命名表/模型只是一个非常懒惰的约定--尽可能使用一个更合适的名称,以符合该事物实际表示的业务逻辑。
这里的具体实现取决于你的业务逻辑,你必须考虑如何处理数量。如果你想得到设备的总成本,最简单的实现是:

# for a single record
store = Store.find(1)
equipment_cost = @store.store_equipments.sum(:cost)

# fetch it for a group of records in a single query
stores = Store.left_joins(:store_equipments)
               .select(
                 Store.arel_table[Arel.star],
                 StoreEquipment.arel_table[:cost].sum.as('equipment_cost')
               )
               .group(:id)

相关问题