4

这是我的情况。我有两个表:承诺和承诺交易。当用户进行质押时,他在质押表中只有一行。

稍后当需要履行承诺时,每笔付款都会记录在我的承诺交易表中。

我需要能够查询所有未完成的质押,这意味着交易表中的金额总和小于质押金额。

这是我到目前为止所拥有的:

named_scope :open,
   :group => 'pledges.id', 
   :include => :transactions, 
   :select => 'pledge_transactions.*', 
   :conditions => 'pledge_transactions.id is not null or pledge_transactions.id is null',
   :having => 'sum(pledge_transactions.amount) < pledges.amount or sum(pledge_transactions.amount) is null'

您可能会问自己,为什么我指定了那个多余和荒谬的条件选项。答案是,当我不强制 ActiveRecord 确认条件中的质押交易表时,它会完全省略它,这意味着我的 having 子句变得毫无意义。

我的信念是我遇到了 ActiveRecord 的缺点。

最终我需要能够做到以下几点:

  • 质押公开
  • Pledge.open.count
  • Pledge.open.find(:all, ...)
  • 等等

有人对这个问题有更优雅的答案吗?请不要建议每次交易发生时增加一个承诺 amount_given 字段。这感觉像是一种创可贴的方法,我更喜欢在创建承诺后保持静止并计算差异。

如果我在这里不使用 Rails,我只需创建一个视图并完成它。

谢谢!

4

2 回答 2

1

协会是如何:transactions定义的?它是否规定:class_name = 'PledgeTransaction'(或任何类别,如果它使用set_table_name)?

你看过:joins参数吗?我想这可能是你要找的。当然,那:conditions件事看起来不太对劲。

如果我在这里不使用 Rails,我只需创建一个视图并完成它

仅仅因为它是 Rails 并不意味着您不能使用视图。好的,根据它的构造方式,您可能无法更新它,但还是去吧。您也可以在迁移中创建和删除视图:

class CreateReallyUsefulView < ActiveRecord::Migration
def self.up
    # this is Oracle, I don't know if CREATE OR REPLACE is widely-supported
    sql = %{
      CREATE OR REPLACE VIEW really_usefuls AS
      SELECT
      ... blah blah SQL blah
    }
    execute sql
  end

  def self.down
    execute 'drop view really_usefuls'
  end
end

class ReallyUseful < ActiveRecord::Base
    # all the usual stuff here, considering overriding the C, U and D parts 
    # of CRUD if it's supposed to be read-only and you're paranoid
end

我认为书籍/文档并没有过多介绍,因为不同平台的视图实现和支持差异很大。

于 2009-09-24T07:54:43.440 回答
1

我认为NOT EXISTS在你的条件下使用会让你得到你想要的。我假设该协会在pledge_transactionas pledge_id. 这是我将如何实施#open

named_scope :open,
      :conditions =>
        "
          NOT EXISTS (
            select 1
            from pledge_transactions
            where
              pledge.id = pledge_transactions.pledge_id AND
              pledge_transactions.amount < pledge.amount
            )
        "
    }
  }

这将允许您执行 Pledge.open、Pledge.open.count 和 Pledge.open.find_by_{whatever}。

于 2009-10-08T19:26:36.777 回答