如何在 rails 中循环时在对象数组中插入对象

How to insert an object in an array of object while looping in rails

提问人:user12763413 提问时间:5/19/2023 更新时间:5/19/2023 访问量:66

问:

控制器.rb

def index
 @expenses = Expense.all.order(:expense_type_id)
end

@expenses如下所示

[#<Expense:0x00007faeb044c6e8
  id: 1,
  amount: 120
  expense_type_id: 1>,
 #<Expense:0x00007faeb044c2b0
  id: 2,
  amount: 1200
  expense_type_id: 1>,
 #<Expense:0x00007faeb044c2b0
  id: 3,
  amount: 11200
  expense_type_id: 3>,
 #<Expense:0x00007faeb044c2b0
  id: 4,
  amount: 1120
  expense_type_id: 4>,
#<Expense:0x00007faeb044c2b0
  id: 5,
  amount: 1120
  expense_type_id: 4>]

index.json.jbuilder

json.records do
  json.array! @expenses do |expense|
    json.amount expense.billed
    json.id expense.id
    json.expense_type_id expense.expense_type_id

  end
end

现在,从 index.json.jbuilder 文件返回的输出是

records = [{amount: 120, id: 1, expense_type_id: 1}, {amount: 1200, id: 2, expense_type_id: 1}, {amount: 11200, id: 3, expense_type_id: 3}, {amount: 1120, id: 4, expense_type_id: 4}, {amount: 1120, id: 5, expense_type_id: 4}]

但我想要的输出是怎样的

records = [{amount: 120, id: 1, expense_type_id: 1}, {amount: 1200, id: 2, expense_type_id: 1}, {amount: sum of amount with expense_type_id 1, id: 'Subtotal', expense_type_id: nil}, {amount: 11200, id: 3, expense_type_id: 3}, {amount: sum of amount with expense_type_id 3, id: 'Subtotal', expense_type_id: nil}, {amount: 1120, id: 4, expense_type_id: 4}, {amount: 1120, id: 5, expense_type_id: 4}, {amount: sum of amount with expense_type_id 4, id: 'Subtotal', expense_type_id: nil}]

我想要插入一个小计对象,以获取每个expense_type_id的所有费用。任何帮助都是值得赞赏的。

数组 Ruby-on-Rails Ruby 对象

评论

0赞 tgf 5/19/2023
建议的输出格式似乎更难使用,因为值的类型不太确定。粗略地说,它将 id 的类型从 ID 更改为“ID ||string“和expense_type_id从 ID 到 ”ID ||null”。有没有理由你不能把格式改成这样的格式:。如果需要,您仍然可以包含一个通用的未分组版本:(或留给客户端)expenses_by_type: [{expense_type_id: 1, sub_total: 2000, expenses: [{each expense that is part of this}]} ]expenses: [{id: 1, amount: 120, expense_type_id: 3}, {...}, ]
0赞 Prateek Choudhary 5/24/2023
您是否愿意考虑为聚合值使用单独的数组?此结构看起来像数组包含两种不同类型的数据,它们不属于单个数据结构中。

答:

0赞 Biki Maharjan 5/19/2023 #1

我没有使用过json生成器。我已经用普通的红宝石完成了,希望你能翻译成构建器格式。

# Grouping all records by expense_type_id, so that we can sum
records = @expenses.group_by{ |expense| expense[:expense_type_id] }
records.map do |expense_type_id, items|
  # Initializing total as zero, so that we can sum inside loop. We can sum later in separate loop, but better to avoid many loops
  total = 0
  attributes = items.map do |item|
    bill = expense.billed.to_f
    total += bill
    {
      amount: bill, 
      id: expense.id,
      expense_type_id: expense_type_id
    }
  end
  # attributes will contain all formatted records, and lastly we insert our total
 attributes << {amount: total, id: 'Subtotal', expense_type_id: nil }
end.flatten.compact # Since we are using double map, we get array of arrays, so need to flatten
0赞 Les Nightingill 5/19/2023 #2

我会采用面向对象的方法,通过定义一个名为的类(也许你的应用程序中已经有这个,因为我看到了一个变量)......ExpenseTypeexpense_type_id

Expense.all.group_by(&:expense_type_id).map do |type_id, expenses|
  ExpenseType.from_list(type_id,expenses).to_json
end

现在,实例数组可以负责聚合和格式化其 json 表示形式,如下所示......ExpenseType

# expense_type.rb
class ExpenseType
  attr_accessors :type_id, :list

  def self.from_list(type_id, list)
    new(type_id, list)
  end

  def initialize(type_id, list)
    @type_id = type_id
    @list = list
  end

  def to_json
    # skipping the detail here
    # make a json representation of the list of expenses with this expense_type_id by calling .to_json on each
    # followed by a json representation of the sum for this expense_type_id
  end
end

最后,每个对象都知道如何将自己表示为 json:Expense

# expense.rb
class Expense < ApplicationRecord # I assume it's a model in a Rails app
  def to_json
    # return json representation of a single expense
  end
end