Created
October 19, 2010 00:34
-
-
Save timriley/633357 to your computer and use it in GitHub Desktop.
Association Extensions & Named Scopes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is how I would like the models | |
# | |
# Order has an extension on its order_transactions association to return the total amount of all the transactions | |
# | |
# I want to call this extension method while modifying the association via a named scope, but it doesn't work (see below). | |
class OrderTransaction < ActiveRecord::Base | |
scope :purchases, where(:action => 'purchase') | |
scope :refunds, where(:action => 'credit') | |
end | |
class Order < ActiveRecord::Base | |
has_many :order_transactions, :autosave => true do | |
def total_amount | |
sum(:amount) / 100.0 | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# But it doesn't work | |
ree-1.8.7-2010.02 > o = Order.first | |
ree-1.8.7-2010.02 > o.order_transactions.total_amount | |
=> 18200 | |
ree-1.8.7-2010.02 > o.order_transactions.purchases.total_amount | |
NoMethodError: undefined method `total_amount' for #<ActiveRecord::Relation:0x1036ff230> | |
from /Users/tim/.rvm/gems/ree-1.8.7-2010.02@corner/ruby/1.8/gems/activerecord-3.0.0.rc/lib/active_record/relation.rb:366:in `method_missing' | |
from (irb):3 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# To have it work, I need to create an identical extension on both the association and named scopes. Not DRY! | |
class OrderTransaction < ActiveRecord::Base | |
scope :purchases, where(:action => 'purchase') do | |
def total_amount | |
sum(:amount) / 100.0 | |
end | |
end | |
scope :refunds, where(:action => 'credit') do | |
def total_amount | |
sum(:amount) / 100.0 | |
end | |
end | |
end | |
class Order < ActiveRecord::Base | |
has_many :order_transactions, :autosave => true do | |
def total_amount | |
sum(:amount) / 100.0 | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# And now I can do what I want | |
ree-1.8.7-2010.02 > o = Order.first | |
ree-1.8.7-2010.02 > o.order_transactions.total_amount | |
=> 18200 | |
ree-1.8.7-2010.02 > o.order_transactions.purchases.total_amount | |
=> 18200 | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Here's one solution: | |
module SummingExtension | |
def total_amount | |
sum(:amount) / 100.0 | |
end | |
end | |
class OrderTransaction < ActiveRecord::Base | |
scope :purchases, where(:action => 'purchase') do | |
include SummingExtension | |
end | |
scope :refunds, where(:action => 'credit') do | |
include SummingExtension | |
end | |
end | |
class Order < ActiveRecord::Base | |
has_many :order_transactions, :autosave => true, :extend => SummingExtension | |
end |
Yeah, you're right, that doesn't work at all. my bad.
Hmm.. not sure if theres a dry-er way to alias it without going to craziness such as
class ActiveRecord::Relation
def total_amount
self.sum(:amount)
end
end
@modsognir, Check out the last file in the gist. Seems like the DRYest way to do it right now. Works for me.
hah, of course. yeah that works well. I might go through ARel later and see if theres an easy way to do something like I originally mentioned.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The first two lines work as expected, but I can't seem to have it as a scope: