Skip to content

Instantly share code, notes, and snippets.

@timriley
Created October 19, 2010 00:34
Show Gist options
  • Save timriley/633357 to your computer and use it in GitHub Desktop.
Save timriley/633357 to your computer and use it in GitHub Desktop.
Association Extensions & Named Scopes
# 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
# 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
# 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
# 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
# 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
@modsognir
Copy link

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