Rails использует переменную экземпляра в контроллере или генерирует внутри помощника? - PullRequest
0 голосов
/ 03 мая 2018

Итак, я пытаюсь создать на странице «Счет-фактура» значение 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

Имея грубый код, я решил создать переменную экземпляра на InvoicesController в методе 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 в InvoicesController или даже в модели?

EDIT:

Я также пытался вставить свою модель счета-фактуры:

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

Тогда в моем InvoicesController:

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 

В конечном итоге получим неопределенный метод date для @ invoice.date.

Ответы [ 3 ]

0 голосов
/ 04 мая 2018

Создание метода экземпляра в Account модель

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

и тогда из вида вы можете все это @account.past_due_amount. нет необходимости создавать дополнительную переменную экземпляра в действии контроллера

0 голосов
/ 04 мая 2018

Итак, я использовал ответ Патрика, но на самом деле он не удался, поэтому я переключился на передачу счета в качестве параметров.

Helper

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 %>
0 голосов
/ 04 мая 2018

Лучший способ - создать метод past_due_amount в InvoicesHelper

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 > для отображения ваших данных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...