Rails создает модель для контроллера, использующего метод .group - PullRequest
0 голосов
/ 14 июля 2020

Мне нужно собрать моих клиентов с помощью Spree::Order.group(:email) (поскольку у нас есть опция гостевой проверки).

Контроллер такой:

class CustomersController < ApplicationController
  def index
    @customers = Spree::Order.where(state: "complete").group(:email).select(
      :email, 
      'count(id) AS total_orders_count',
      'sum(payment_total) AS amount', 
      'array_agg(number) AS order_numbers', 
      'array_agg(completed_at) AS completion_dates'
      )    
  end

Могу ли я создать customer.rb модель для этих @customers, поэтому я могу переместить туда лог c. Мне нужно .joins(:line_items) и фильтровать по дате, поэтому я считаю, что это будет чище.

PS В качестве помощника ... 'sum(payment_total' AS amount всегда возвращает 0.0, потому что payment_total является BigDecimal объект. Какой правильный синтаксис для этого запроса, который будет действовать как 'sum(payment_total.to_f)'....

1 Ответ

0 голосов
/ 14 июля 2020

Поскольку у вас нет таблицы customers, и вы пытаетесь абстрагировать понятие гостя из таблицы заказов, создание модели является разумным подходом.

Рассмотрите следующее:

class Customer < ActiveRecord::Base

  # Use the `orders` table for this "virtual" model
  self.table_name = Spree::Order.table_name

  # ensure no writes ever occur from this model as a precaution
  def readonly?; true; end

  scope :with_completed_orders, ->  {
    where(state: "complete")
      .select(
        :email,
        'count(id) AS total_orders_count',
        'sum(payment_total) AS amount',
        'array_agg(number) AS order_numbers',
        'array_agg(completed_at) AS completion_dates'
      )
      .group(:email)
      .order(:email) # prevents errors - remove it and try Customer.first in the console.
  }

  scope :by_email, -> (email) { where(email: email) }

  # Default scopes are generally a no-no, but a convenience here
  def self.default_scope
    # this could be any scope that groups by :email
    self.with_completed_orders
  end

  # example of a potentially useful instance method
  def orders
    # returns a scope, which you can chain
    Spree::Order.where(email: email)
  end

end

Выборки в области заполняют атрибуты экземпляра клиента с тем же именем, как вы, вероятно, знаете.

Это позволит вам делать такие вещи, как:

customers = Customer.all
c = Customer.by_email('test@example.com')
c.amount # returns BigDecimal
c.order_numbers # returns Array 
c.orders.first # example of chaining scope for #orders instance method

В контроллере:

class CustomersController < ApplicationController
  def index
    @customers = Customer.all
  end
end

Надеюсь, это даст вам некоторые идеи.

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