Связанный совокупный вызов через ассоциацию в DataMapper (ruby)

Я работаю над простым бюджетным приложением, используя Sinatra и DataMapper в Ruby.

Я хочу получить сумму всех транзакций по всем счетам доходов за последние 30 дней.

Что-то вроде Account.income_accounts.account_entries.sum(:amount, :transaction_date.gte => Date.today - 30) должно работать. Вместо этого ограничивающее условие для transaction_date игнорируется, возвращая сумму суммы для всех записей для всех счетов доходов.

Учитывая следующее:

class Account
  include DataMapper::Resource

  has n, :account_entries

  property :id,        Serial
  property :name,      String
  property :acct_type, String

  def self.income_accounts
    all(:acct_type => 'Income')
  end
end

class AccountEntry
  include DataMapper::Resource

  belongs_to :account

  property :id,               Serial
  property :account_id,       Integer
  property :description,      String
  property :amount,           BigDecimal
  property :transaction_date, DateTime
end

Я правильно требую dm-aggregates. Я новичок в DataMapper. Если это имеет значение, я использую базу данных sqlite3. Я действительно не хочу прибегать к рубину для суммирования результатов. Также кажется неправильным прибегать к выполнению необработанного SQL для этого типа простого совокупного запроса.

Может кто-нибудь пролить некоторый свет на это? Я хотел бы, чтобы мне указали правильное направление в отношении цепных искателей в DataMapper, особенно с агрегатами. Мое изучение API и сайта DataMapper пока не дало решения.


person kEND    schedule 24.10.2009    source источник


Ответы (4)


Я только что написал небольшой автономный скрипт для проверки вашего примера, и, похоже, он возвращает правильные результаты. Обратите внимание, что я использую Edge extlib, dm-core и dm-more, установленные с git:

#!/usr/bin/env ruby -Ku

# encoding: utf-8

require 'rubygems'
require 'dm-core'
require 'dm-aggregates'

DataMapper::Logger.new($stdout, :debug)
DataMapper.setup(:default, 'sqlite3::memory:')

class Account
  include DataMapper::Resource

  property :id,        Serial
  property :name,      String
  property :acct_type, String

  has n, :account_entries

  def self.income_accounts
    all(:acct_type => 'Income')
  end
end

class AccountEntry
  include DataMapper::Resource

  property :id,               Serial
  property :description,      String
  property :amount,           BigDecimal
  property :transaction_date, Date

  belongs_to :account
end

DataMapper.auto_migrate!

account = Account.create(
  :name      => 'Test Account',
  :acct_type => 'Income'
)

5.times do |n|
  account.account_entries.create(
    :description      => "Account Entry #{n}",
    :amount           => 1.00,
    :transaction_date => Date.today
  )
end

puts Account.income_accounts.account_entries(:transaction_date.gte => Date.today - 30).sum(:amount).to_s('F')  # => 5.0

Можете ли вы запустить указанную выше программу и сообщить мне, что она вам возвращает? Если вы получаете что-то отличное от 5.0, попробуйте обновить до последних пакетов и повторите попытку.

person dkubb    schedule 25.10.2009
comment
У вас есть Date in :transaction_date, а у него DateTime. Может ли это быть? - person Jonas Elfström; 25.10.2009

DateTime использует секунды, так как его базовая единица Date.today - 30 равна 30 секундам назад. Попробуйте Date.today - 30.days

person John F. Miller    schedule 24.10.2009
comment
Date.today - 30 дает мне 2009-09-24, как и ожидалось. - person kEND; 25.10.2009

Вы пробовали DateTime.now-30 или даже Time.now-30*3600*24 вместо Date.today-30?

person Jonas Elfström    schedule 24.10.2009

Ошибка пользователя. Я возился с to_s на DateTime, чтобы использовать форматы времени в strftime. После удаления цепной агрегат работал, как и ожидалось.

person kEND    schedule 24.10.2009