Цепной агрегированный вызов по ассоциации в DataMapper (ruby) - PullRequest
1 голос
/ 24 октября 2009

Я работаю над простым бюджетным приложением, использующим 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. Я действительно не хочу прибегать к помощи ruby ​​для подведения итогов. Также кажется неправильным прибегать к выполнению необработанного SQL для этого типа простого агрегированного запроса.

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

Ответы [ 4 ]

2 голосов
/ 25 октября 2009

Я только что написал небольшой автономный скрипт для проверки вашего примера, и он, похоже, возвращает правильные результаты. Обратите внимание, что я использую 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, попробуйте обновить до последних пакетов и повторите попытку.

0 голосов
/ 25 октября 2009

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

0 голосов
/ 25 октября 2009

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

0 голосов
/ 24 октября 2009

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

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