Reputation: 297
I'm trying to reduce the number of queries in my application and need some help with the following setup:
I have 5 models:
They are associated with the following:
My goal is to find the Spotprices that matches a Specific Bet. To do that I uses the following queries, but I'm sure it can be done in a better way, so when I run through 100 bets and want to see if they are above or below the corrosponding Spotprice I don't overload the DB with queries.
a = Bet.find(5)
b = Choice.find(a.choice_id)
c = Spotprice.where(:spotarea_id => b.spotarea_id, :product_id => b.product_id,
:deliverydate => b.deliverydate).first
Thanks!
Upvotes: 0
Views: 149
Reputation: 297
After a few hours and a lot of Google search I found a solution that works.. After adding the join bridges I wanted to do:
Bet.find(5).spotprice
But that didn't work because to do that I needed something like this in my Choice model:
has_one :spotprice, :through => [:spotarea, :product] :source => :spotprices
I that is not possible.. apperently..
So I found this link has_one :through => multiple and I could use that answer in my situation.
class Choice < ActiveRecord::Base
belongs_to :user
belongs_to :spotarea
belongs_to :product
has_many :bets
def spotprice
Spotprice.where(:product_id => self.product_id, :spotarea_id => self.spotarea_id, :deliverydate => self.deliverydate).first
end
class Bet < ActiveRecord::Base
belongs_to :user
belongs_to :choice
has_one :spotprice, :through => :choice
With the above I can now do:
Bet.find(5).choice.spotprice
If anybody got a better solution please let me know :)
Upvotes: 0
Reputation: 20857
Before trying to decrease the number of queries, you should run a performance test on your app, and monitor the database load. Sometimes it's better to run a few small queries rather than one huge query with a few joins. Certain versions of Oracle seem especially bad at joins.
An alternative to joins, if you're trying to avoid the n+1 query problem, is to use preload
and pass the association (preload
takes the same arguments as includes
). This makes ActiveRecord run one query per table.
Basically:
Upvotes: 1
Reputation: 16435
first of all, set up join bridges:
class Choice
has_many :spotprices, :through => :spotarea
end
class Bet
has_many :spotprices, :through => :choice
end
then you can query things like
Bet.joins(:spotprices).where("spotprices.price > bets.value")
Upvotes: 1
Reputation: 3376
Well here's one pretty easy change:
b = Bet.includes(:choice).find(5).choice
Upvotes: 0