轨道在控制器中使用实例变量还是在帮助程序中生成?



所以我试图在发票页面上构建past_due_amount,我试图只找到当前帐户的发票,这些发票没有还清,应该是过去的。

所以粗略地说,我有:

past_due_amount = Invoice.where(account: invoice.account, status: :unpaid).where('date < ? ', invoice.date).map(&:due).sum

有关其他上下文,以下是涉及的模型:

发票:

class Invoice < ApplicationRecord
belongs_to :account
has_many :line_items, dependent: :destroy
has_many :payment_destinations, dependent: :destroy
has_many :prorated_fees, dependent: :nullify
enum status: [:unpaid, :paid]
validates :date, presence: true
validates :period_start, :period_end,
uniqueness: { scope: :account, allow_blank: true }, on: :create
validate :start_is_before_end
DAYS_DUE_AFTER_DATE = 14.days
scope :descending, -> { order(date: :desc) }
scope :ascending, -> { order(date: :asc) }
scope :due, -> { unpaid.where(arel_table[:date].lteq(Time.zone.today - DAYS_DUE_AFTER_DATE)) }
def total
if persisted?
line_items.sum(:amount)
else
line_items.map(&:amount).sum
end

结束 结束

帐户:

class Account < ApplicationRecord
belongs_to :customer
belongs_to :property_address,
class_name: Address.to_s,
dependent: :destroy,
required: false
[:products, :account_changes, :equipments,
:payments, :invoices].each do |assoc|
has_many assoc, dependent: :destroy
end
accepts_nested_attributes_for :property_address
delegate :street, :city, :state, :zip,
to: :property_address, allow_nil: true
delegate :email, :full_name, to: :customer
enum status: [:staged, :active, :inactive]
scope :active_or_staged, -> { where(status: [:staged, :active]) }
scope :past_due, lambda {
joins(:invoices)
.where(
Invoice.arel_table[:status].eq(:unpaid)
.and(Invoice.arel_table[:date].lt(Time.zone.today - 14.days))
).distinct
}
scope :search, lambda { |term|
joins(:customer)
.where(
arel_table[:account_num].matches("%#{term}%")
.or(Customer.arel_search(term))
)
}
end

有了粗略的代码,我决定在 show 方法中的发票控制器上构建一个实例变量,如下所示:

def show
@invoice = Invoice.find_by!(id: params[:id], account: current_customer.account_ids)
@account = @invoice.account
@past_due_amount = Invoice.where(account: @account, status: :unpaid).where('date < ?', @invoice.date).map(&:due).sum
end

没有出现任何错误,但这并不能说明什么,因为我拥有的例子充其量是很差的。但我的问题是...我实际上应该将其放在帮助程序中,而不是在发票控制器甚至模型中的 show 方法中吗?

编辑:

我还尝试输入我的发票模型:

def self.past_due_amount
Invoice.where(account: @account, status: :unpaid).where('date < ?', @invoice.date).map(&:due).sum
end

然后在我的发票控制器中:

def show
@invoice = Invoice.find_by!(id: params[:id], account: current_customer.account_ids)
@account = @invoice.account
@past_due_amount = Invoice.past_due_amount
end 

最终得到 @invoice.date 的未定义方法"date"。

最好的方法是创建一个past_due_amountInvoicesHelper

module InvoicesHelper
def past_due_amount
Invoice.where(account: @account, status: :unpaid).where('date  <?', @invoice.date).map(&:due).sum
end
end

在控制器中只需初始化所有实例变量

def show
@invoice = Invoice.find_by!(id: params[:id], account: current_customer.account_ids)
@account = @invoice.account
end 

在视图中,应使用:<%= past_due_amount >来显示数据

在模型中创建实例方法Account

def past_due_amount
invoices.map(&:due).sum
end

然后从视图中您可以@account.past_due_amount所有内容。 无需在控制器操作中创建额外的实例变量

所以我有点使用了帕特里克的答案,但它实际上失败了,所以我改用将发票作为参数传递。

助手

module InvoicesHelper
def past_due_amount(invoice)
Invoice.where(account: invoice.account, status: :unpaid).where('date < ?', invoice.date).map(&:due).sum
end
end

那么在我看来:

<% if past_due_amount(invoice).positive? %>
<p><%= number_to_currency past_due_amount(invoice) %></p>
<% end %>

最新更新