如何使named_scope与连接表一起正常工作?

发布于 2024-08-06 03:14:56 字数 980 浏览 6 评论 0原文

这是我的情况。我有两个表:pledges 和 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, ...)
  • 等。

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

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

谢谢!

Here's my situation. I have two tables: pledges and pledge_transactions. When a user makes a pledge, he has only a row in the pledges table.

Later when it comes time to fulfill the pledge, each payment is logged in my pledge_transactions table.

I need to be able to query all open pledges which means that the sum of the amounts in the transactions table is less than the pledged amount.

Here's what I have so far:

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'

You might be asking yourself why I have that superfluous and ridiculous conditions option specified. The answer is that when I don't force ActiveRecord to acknowledge the pledge_transactions table in the conditions, it omits it completely, which means my having clause becomes meaningless.

My belief is that I have run into a shortcoming of ActiveRecord.

Ultimately I need to be able to do the following:

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

Anybody have a more elegant answer to this problem? Please no suggestions of incrementing a pledges amount_given field each time a transaction occurs. That feels like a band-aid approach and I'm much more of a fan of keeping the pledge static after it is created and computing the difference.

If I weren't using Rails here, I'd just create a view and be done with it.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

影子是时光的心 2024-08-13 03:14:56

: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

我认为书籍/文档不会讨论这么多,因为视图的实现和支持在不同平台上存在很大差异。

How is the :transactions association defined? Does it stipulate :class_name = 'PledgeTransaction' (or whatever the class is, if it uses set_table_name)?

Have you looked at the :joins parameter? I think it might be what you were looking for. Certainly that :conditions thing doesn't look right.

If I weren't using Rails here, I'd just create a view and be done with it

Just because it's Rails doesn't mean you can't use a view. OK, depending on the way it's constructed you may not be able to update it, but otherwise go for it. You can create and drop views in migrations, too:

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

I think the books/docs don't go into this much because implementation of, and support for views varies significantly across platforms.

独守阴晴ぅ圆缺 2024-08-13 03:14:56

我认为在您的条件中使用 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_{whatever}。

I think using NOT EXISTS in your conditions will get you what you want. I'm assuming the association is on the pledge_transaction as pledge_id. Here's how I would implement #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
            )
        "
    }
  }

This will allow you to do Pledge.open, Pledge.open.count and Pledge.open.find_by_{what ever}.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文