在DataMapper(ruby)中跨关联的链式聚合调用

时间:2009-10-24 18:04:52

标签: ruby datamapper

我正在使用Ruby中的Sinatra和DataMapper开发一个简单的预算应用程序。

我希望获得过去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 个答案:

答案 0 :(得分:2)

我刚刚写了一个小的独立脚本来测试你的例子,它似乎返回了正确的结果。请注意我使用的是边缘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以外的其他内容,请尝试更新到最新的软件包并重试。

答案 1 :(得分:0)

DateTime使用秒,因为它的基本单位Date.today - 30是30 以前。试试Date.today - 30.days

答案 2 :(得分:0)

您是否尝试过DateTime.now-30或者甚至是Time.now-30 * 3600 * 24而不是Date.today-30?

答案 3 :(得分:0)

用户错误。我在to_s上使用DateTime进行了调整,以使用strftime中的时间格式。删除后,链式聚合按预期工作。