如何使用连接表使named_scope正常工作?

时间:2009-09-24 06:57:43

标签: ruby-on-rails ruby activerecord named-scope

这是我的情况。我有两个表:承诺和pledge_transactions。当用户做出承诺时,他在承诺表中只有一行。

稍后到达承诺时,每笔付款都会记录在我的pledge_transactions表中。

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

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

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在条件中确认pledge_transactions表时,它完全省略了它,这意味着我的having子句变得毫无意义。

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

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

  • Pledge.open
  • Pledge.open.count
  • Pledge.open.find(:all,...)

有人对这个问题有更优雅的答案吗?请勿在每次交易发生时增加认捐额度_given字段。这感觉就像一个创可贴的方法,而且我更倾向于在创建和保持差异之后保持承诺的静态。

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

谢谢!

2 个答案:

答案 0 :(得分: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

我认为书籍/文档不会涉及这么多,因为不同平台的视图实施和支持差别很大。

答案 1 :(得分:1)

我认为在你的条件下使用NOT EXISTS可以得到你想要的东西。我假设该关联位于pledge_transaction 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_ {what ever}。