1

I have this association in the Project model of a Rails 3.2 application:

has_many :pledges, conditions: { paid: true }

At one place, I need all unpaid pledges. Besides the two obvious solutions (defining another association with paid: false condition or finding the pledges with Pledge.where...), is it possible to drop the conditions on the fly?

Something similar to:

project.pledges.unscoped.where(paid: false)   # does not work since the link to project is also lost
project.pledges.where(paid: false)            # no good since it does "paid=t AND paid=f"
svoop
  • 3,318
  • 1
  • 23
  • 41

1 Answers1

0

Why not add scopes to the Pledge model?

class Pledge < ActiveRecord::Base
  scope :paid, -> {
    where(paid: true)
  }
  scope :unpaid, -> {
    where(paid: false)
  }
end

Then you could do:

project.pledges.paid
project.pledges.unpaid

You also need to remove the conditions from the association in the Project model.

[EDIT] alternative solution:

Add a second association in products for unpaid pledges:

class Product
  has_many :unpaid_pledges, class_name: Pledge, conditions: { paid: false }
end

Then you can do

project.pledges #these are all paid
project.unpaid_pledges #all unpaid pledges belonging to product
Slicedpan
  • 4,995
  • 2
  • 18
  • 33
  • Not quite what I'm looking for. The condition is in the model to make sure pledges to work on are always paid. Kinda safety measure to enforce it there. – svoop Dec 18 '13 at 14:16
  • Added an alternative, not sure how else to do this without resorting to `Pledge.where(...)`. Dropping the scope of the association without dropping the association itself is not possible in rails – Slicedpan Dec 18 '13 at 14:27
  • 1
    Woops, you suggested that alternative in your question! Anyway, [here's](http://stackoverflow.com/questions/3963124/default-scope-and-associations) a similar question, there's another way, `Pledge.unscoped { product.pledges }` I think would be the equivalent – Slicedpan Dec 18 '13 at 14:33
  • Unfortunately, the above does not work: `Pledge.unscoped { project.pledges }` queries `SELECT "pledges".* FROM "pledges" WHERE "pledges"."project_id" = 1652 AND "pledges"."paid" = 't'` so the condition is still there. However, from the linked question, the following answer does the trick: `Pledge.unscoped.where(project_id: project.id, paid: false)`. – svoop Dec 18 '13 at 18:28
  • You don't need the unscoped in that case, unless the Pledge model has a default scope. – Slicedpan Dec 19 '13 at 15:41