4

これが私の状況です。pledges と pledge_transactions の 2 つのテーブルがあります。ユーザーが誓約を行うと、誓約テーブルには行しかありません。

後で誓約を履行するときが来たら、各支払いは私の 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 を使用していなければ、ビューを作成するだけで済みます。

ありがとう!

4

2 に答える 2

1

関連付けはどのように:transactions定義されますか?それは規定していますか:class_name = 'PledgeTransaction'(または、使用する場合はクラスが何であれset_table_name)?

:joinsパラメータを見ましたか?それはあなたが探していたものかもしれないと思います。確かにその:conditionsことは正しく見えません。

ここでRailsを使用していなかった場合は、ビューを作成してそれで完了します。

Railsだからといって、ビューを使用できないわけではありません。OK、構築方法によっては更新できない場合がありますが、それ以外の場合は更新してください。移行でビューを作成および削除することもできます。

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_transactionアソシエーションがasにあると仮定してい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} を実行できるようになります。

于 2009-10-08T19:26:36.777 に答える