Preload has_many associations with dynamic conditions
This seems to be the only solution that works:
# 1st query: load places
places = Place.all.to_a
# 2nd query: load events for given places, matching the date condition
events = Event.where(place: places.map(&:id)).where("start_date > '#{time_in_the_future}'")
events_by_place_id = events.group_by(&:place_id)
# 3: manually set the association
places.each do |place|
events = events_by_place_id[place.id] || []
association = place.association(:events)
association.loaded!
association.target.concat(events)
events.each { |event| association.set_inverse_instance(event) }
end
It's a bit hacky but it's quite easy to adapt to any situation where you might want to load an association using a separate query and then attach it to an existing object.
All credit goes to https://mrbrdo.wordpress.com/2013/09/25/manually-preloading-associations-in-rails-using-custom-scopessql/
Rails has_many with dynamic conditions
Rails 4+ way (Thanks to Thomas who answered this below):
has_many :faixas_aliquotas, -> (object) {
where("regra_fiscal = ?", object.regra_fiscal)
},
:class_name => 'Fiscal::FaixaAliquota'
Rails 3.1+ way:
has_many :faixas_aliquotas, :class_name => 'Fiscal::FaixaAliquota',
:conditions => proc { "regra_fiscal = #{self.regra_fiscal}" }
Rails 3 and below:
has_many :faixas_aliquotas, :class_name => 'Fiscal::FaixaAliquota',
:conditions => ['regra_fiscal = #{self.regra_fiscal}']
No. This is not a mistake. The conditions are specified in single quotes and still contains the code #{self.regra_fiscal}
. When the conditions clause is evaulated, the regra_fiscal method will be called on the object of self
(whatever the class is). Putting double quotes will not work.
I hope this is what you are looking for.
Preload associations of an already loaded model
using model_instance.associated_model
will only load the association for the first time.
If we open rails console and try it there, we'll see that it has queried the database only first time and after that all the calls to associated model didn't load it from database.
how can i specify dynamic conditions in has_many associations
You cannot use dynamic conditions in has_many
. However, in your particular case it seems you need primary_key
and foreign_key
instead:
class Message
has_many :threads, :class_name=>"Message", :primary_key => 'conversation_id', :foreign_key => 'conversation_id'
end
You may also be interested by one of the gems that adds tree structure to ActiveRecord.
How to preload child conditionally based on parent column?
You can use Custom Preloading SQL in Gorm
Example: Preload guests order by name desc.
db.Where("code = ?", orderCode).Preload("Guests", func(db *gorm.DB) *gorm.DB {
return db.Order("guests.name DESC")
}).Find(&orders)
//// SELECT * FROM orders WHERE orders.code = "ABC";
//// SELECT * FROM guests WHERE order_id IN (1,2,3,4) order by guests.name DESC;
For working with parent-child condition you can use JOIN
db.Joins("JOIN orders ON orders.id = guests.order_id ").Find(&guests)
Combining both may work. Like
db.Where("code = ?", orderCode).Preload("Guests", func(db *gorm.DB) *gorm.DB {
return db.Joins("JOIN orders ON orders.some_column_in_order_tbl = guests.some_column_in_guest_tbl")
}).Find(&orders)
Active Record: Eager load association with parameter
Step 1
Make the current_user
accessible in the model layer (one technique is outlined here: https://stackoverflow.com/a/2513456/163203)
Step 2
Add an association with a condition that gets evaluated during run time.
Rails 2
class Item < ActiveRecord::Base
has_many :ratings
has_many :current_user_ratings,
:class_name => "Rating",
:conditions => 'ratings.user_id = #{User.current_user.try(:id)}'
end
Rails 3.1 and above
class Item < ActiveRecord::Base
has_many :ratings
has_many :current_user_ratings,
:class_name => "Rating",
:conditions => proc { ["ratings.user_id = ?", User.current_user.try(:id)] }
end
Step 3
Item.includes(:current_user_ratings)
Related Topics
Homebrew Install: Failed During: Git Fetch Origin Master:Refs/Remotes/Origin/Master -N --Depth=1
Transforming Datetime into Month, Day and Year
How to Chop a String into Chunks of a Given Length in Ruby
What's the Difference Between Process.Fork and Process.Spawn in Ruby 1.9.2
How to Find an Actively Developed Lint Tool for Ruby
Find() with Nil When There Are No Records
Get Last Day of the Month in Ruby
How to Save Values into a Yaml File
How to Include Variables in My Vagrantfile
How to Call an Older Version of a Gem from the Commandline
How to Overwrite a Getter Method in an Activerecord Model
How to Get Rspec-2 to Give the Full Trace Associated with a Test Failure
Scope of Constants in Ruby Modules
How to See the Dependency Tree Just from Gemfile
Ruby/Rails: Convert Int to Time or Get Time from Integer
How to Make Carrierwave Delete the File When Destroying a Record
How Would I Save Multiple Records at Once in Rails
How to or Should I Find an Object by the Object_Id Attribute in Ruby