ruby-on-rails 如何在Rails中循环时在Object数组中插入对象

wgmfuz8q  于 2023-05-19  发布在  Ruby
关注(0)|答案(2)|浏览(75)

controller.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}]

我希望插入一个Subtotal对象,以获取每个expense_type_id的所有费用。任何帮助都很感激。

lx0bsm1f

lx0bsm1f1#

我没有使用过json builder。我用ruby做的,希望你能翻译成builder格式。

# 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
polhcujo

polhcujo2#

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

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

现在,ExpenseType示例数组可以负责聚合和格式化它们的json表示,类似于...

# 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

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

# 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

相关问题