Reputation: 621
I have been reading to understand the best Rails 3 way to do the following. I'd be very grateful for suggested approaches. (scopes?)
I have the following models:
class DonorCategory < ActiveRecord::Base
has_many :donors
end
class Donor < ActiveRecord::Base
has_many :donations
belongs_to :donor_category
end
class Donation < ActiveRecord::Base
belongs_to :donor
end
what I need is this: "All donations associated with a given donor category, for given dates" The date criteria is applied to Donation, but the donor category criterion is applied to Donor So it is as if I need to filter the Donors which are applied to the Donation query.
Upvotes: 1
Views: 800
Reputation: 15772
You could add a helpful query method to Donor. And adding a has_many ... through
on DonationCategory would give you easy access to the Donations from a given category, automatically joining the tables, like this:
class DonationCategory < ActiveRecord::Base
has_many :donors
has_many :donations, through: :donors
end
class Donation < ActiveRecord::Base
def self.within_dates(start_date, end_date)
where "created_at >= ? AND created_at <= ?", start_date, end_date
end
end
# Query looks like this:
some_category.donations.within_dates(start_date, end_date)
# Or this:
DonorCategory.find(123).donations.within_dates(start_date, end_date)
To use the through
option on has_many
, you don't need to modify your database at all. Rails will get the donations
from the donor_category's donors
, by joining your donations, donors, and donor_categories tables.
You mentioned scopes. The within_dates
class method is effectively a scope. scope
is just special rails syntax for creating a class method that queries the database. It's a redundant mechanism, but DHH likes it. And I agree that often a scope is easier on the eyes than the equivalent class method, but when the scope requires arguments, as it would here, I think the class method is actually more straightforward.
UPDATE
RFC1337's answer makes me realize the query method could be simplified:
def self.within_dates(start_date, end_date)
where created_at: start_date..end_date
end
Upvotes: 2
Reputation: 167
I think what you need is something like this:
Donor.where(:donor_category => DonorCategory.find(id)).where(:date => start_date..end_date)
Upvotes: 0