【问题标题】:How to add extra attribute in model to move calculation out of view?如何在模型中添加额外属性以将计算移出视图?
【发布时间】:2012-02-25 00:40:32
【问题描述】:

对于以下 RubyOnRails 代码,有没有办法将“利润”计算从视图移到模型中。所以可能有一个名为 total_incometotal_expense?

模型 - transaction.rb

class Transaction < ActiveRecord::Base
  attr_accessible :name, :amount, :category
  scope :incomes,  :conditions => { :category => 'Income'  }
  scope :expenses, :conditions => { :category => 'Expense' }
end

控制器 - transactions_controller.rb

class TransactionsController < ApplicationController

  def index
    @incomes  = Transaction.incomes
    @expenses = Transaction.expenses
    @transaction = Transaction.new
  end

查看 - index.html.erb

<pre>
<strong>Income</strong>
  <% @incomes.each do |income| %>
  <%= income.name %>  -  <%= number_to_currency((income.amount.nil? ? 0 : income.amount)) %>
  <% end %>
  <strong>Subtotal:</strong> <%= number_to_currency(@income_total = @incomes.sum(:amount)) %>

<strong>Expenses</strong>
  <% @expenses.each do |expense| %>
  <%= expense.name %>  -  <%= number_to_currency((expense.amount.nil? ? 0 : expense.amount)) %>
  <% end %>
  <strong>Subtotal:</strong> <%= number_to_currency(@expenses_total = @expenses.sum(:amount)) %>

<strong>Profit: <%= number_to_currency(@income_total - @expenses_total) %></strong>
</pre>

【问题讨论】:

  • 与您的问题无关:注意,Transaction 是许多编程环境中的保留字,可能会导致问题。我养成了总是稍微调整名称以避免问题的习惯。
  • @DGM 感谢您指出这一点。 RoR old wiki 上列出了一些 RoR 保留字(我发现确实包括“交易”)。

标签: ruby-on-rails refactoring rails-activerecord


【解决方案1】:

对于最基本的更改,您只需将类方法添加到 Transaction

class Transaction < ActiveRecord::Base
  attr_accessible :name, :amount, :category
  scope :incomes,  :conditions => { :category => 'Income'  }
  scope :expenses, :conditions => { :category => 'Expense' }

  def self.income_total
    incomes.sum :amount
  end

  def self.expenses_total
    expenses.sum :amount
  end

end

class TransactionsController < ApplicationController

  def index
    @incomes  = Transaction.incomes
    @expenses = Transaction.expenses
    @income_total = Transaction.income_total
    @expenses_total = Transaction.expenses_total
    @transaction = Transaction.new
  end

【讨论】:

  • 正是我正在寻找的东西。谢谢。
【解决方案2】:

这些天来,我更喜欢将这些多个相互依赖的实例变量包装到一个新的演示者类中,就像这样 (未经测试)

class TransactionPresenter

  attr_reader :income_total, :expenses_total

  def initialize
    @incomes = Transaction.incomes
    @expenses = Transaction.expenses
  end

  def each_income(&block)
    @incomes.each(&block)
  end

  def each_expense(&block)
    @incomes.each(&block)
  end

  def income_total
    @income_total ||= number_to_currency(@incomes.sum(&:amount))
  end

  def expenses_total
    @expenses_total ||= number_to_currency(@expenses.sum(&:amount))
  end

  def name_and_amount(income_or_expense)
    "#{income_or_expense.name} - #{number_to_currency((income.amount.nil? ? 0 : income.amount))}"
  end

  def profit
    number_to_currency(income_total - expenses_total)
  end

end

# controller

def index
  @presenter = TransactionPresenter.new
end

# view

<pre>
<strong>Income</strong>
  <% @presenter.each_income do |income| %>
    <%= @presenter.name_and_amount %>
  <% end %>
  <strong>Subtotal:</strong> <%= @presenter.income_total %>

<strong>Expenses</strong>
  <% @presenter.each_expense do |expense| %>
    <%= @presenter.name_and_amount %>
  <% end %>
  <strong>Subtotal:</strong> <%= @presenter.expenses_total %>

<strong>Profit: <%= @presenter.profit %></strong>
</pre>

【讨论】:

  • 我将不得不阅读演示者类的使用。我以前从未见过这种类型的东西。
猜你喜欢
  • 1970-01-01
  • 2016-06-19
  • 2014-08-10
  • 1970-01-01
  • 2018-08-25
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 2020-10-24
相关资源
最近更新 更多