2009-09-24 11 views
4

Voici ma situation. J'ai deux tables: les promesses et les promesses de dons. Quand un utilisateur fait une promesse, il n'a qu'une rangée dans la table des promesses.Comment faire pour que named_scope fonctionne correctement avec une table jointe?

Plus tard au moment de remplir le formulaire, chaque paiement est enregistré dans ma table pledge_transactions.

Je dois pouvoir interroger tous les engagements ouverts, ce qui signifie que la somme des montants dans la table des transactions est inférieure au montant promis.

Voici ce que j'ai jusqu'à présent:

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' 

Vous pourriez vous demander pourquoi je superflues et que les conditions ridicules option spécifiée. La réponse est que lorsque je ne force pas ActiveRecord à reconnaître la table pledge_transactions dans les conditions, elle l'omet complètement, ce qui signifie que ma clause having devient sans signification. Je crois que j'ai rencontré un défaut d'ActiveRecord.

En fin de compte je dois être en mesure de faire ce qui suit:

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

Quelqu'un at-il une réponse plus élégante à ce problème? S'il vous plaît pas de suggestions d'incrémentation d'un champ amount_given pledges chaque fois qu'une transaction se produit. Cela ressemble à une approche de pansement et je suis beaucoup plus fan de garder l'engagement statique après sa création et de calculer la différence.

Si je n'utilisais pas Rails ici, je créerais simplement une vue et j'en aurais fini avec.

Merci!

Répondre

1

Comment l'association :transactions est-elle définie? Est-ce qu'il stipule :class_name = 'PledgeTransaction' (ou quelle que soit la classe, s'il utilise set_table_name)?

Avez-vous regardé le paramètre :joins? Je pense que c'est peut-être ce que tu cherchais. Certes, cette chose ne semble pas correcte.

Si je n'utilise Rails ici, je venais de créer une vue et faire avec elle

Juste parce qu'il est Rails ne signifie pas que vous ne pouvez pas utiliser une vue. OK, selon la façon dont il est construit, vous ne pourrez peut-être pas le mettre à jour, mais sinon allez-y. Vous pouvez créer et supprimer les vues des migrations, aussi:

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 

Je pense que les livres/docs ne vont pas dans ce bien parce que la mise en œuvre et le soutien des points de vue varient considérablement selon les plates-formes.

1

Je pense qu'en utilisant NOT EXISTS dans vos conditions vous obtiendrez ce que vous voulez. Je suppose que l'association est sur le pledge_transaction comme pledge_id.Voici comment je mettre en œuvre #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 
      ) 
     " 
    } 
    } 

Cela vous permettra de faire Pledge.open, Pledge.open.count et Pledge.open.find_by_ {} que jamais.

+0

James, Idée très intéressante. Cependant, une chose à considérer est qu'une personne dans ce système peut faire un paiement partiel vers leur gage et leur engagement est toujours considéré ouvert. C'est pourquoi j'ai approché le problème avec une somme(). Si la somme des engagements n'est pas égale ou supérieure à la mise en gage, le gage est toujours considéré comme ouvert (non rempli). – rwl4

+0

Hey rwl4, Vous pouvez toujours utiliser la clause NOT EXISTS, j'ai ajouté le montant jpoz