Поскольку у вас нет таблицы 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
Надеюсь, это даст вам некоторые идеи.