Preload, Eagerload, Includes and Joins
Rails provides four different ways to load association data. In this blog we are going to look at each of those.
Preload loads the association data in a separate query.
User.preload(:posts).to_a # => SELECT "users".* FROM "users" SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1)
This is how
includes loads data in the default case.
preload always generates two sql we can't use
posts table in
where condition. Following query will result in an error.
User.preload(:posts).where("posts.desc='ruby is awesome'") # => SQLite3::SQLException: no such column: posts.desc: SELECT "users".* FROM "users" WHERE (posts.desc='ruby is awesome')
With preload where clauses can be applied.
User.preload(:posts).where("users.name='Neeraj'") # => SELECT "users".* FROM "users" WHERE (users.name='Neeraj') SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (3)
Includes loads the association data in a separate query just like
However it is smarter than
preload. Above we saw that
preload failed for query
User.preload(:posts).where("posts.desc='ruby is awesome'"). Let's try same with includes.
User.includes(:posts).where('posts.desc = "ruby is awesome"').to_a # => SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0, "posts"."title" AS t1_r1, "posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3 FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id" WHERE (posts.desc = "ruby is awesome")
As you can see
includes switches from using two separate queries to creating a single
LEFT OUTER JOIN to get the data. And it also applied the supplied condition.
includes changes from two queries to a single query in some cases. By default for a simple case it will use two queries. Let's say that for some reason you want to force a simple
includes case to use a single query instead of two. Use
references to achieve that.
User.includes(:posts).references(:posts).to_a # => SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0, "posts"."title" AS t1_r1, "posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3 FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
In the above case a single query was done.
eager loading loads all association in a single query using
LEFT OUTER JOIN.
User.eager_load(:posts).to_a # => SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0, "posts"."title" AS t1_r1, "posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3 FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
This is exactly what
includes does when it is forced to make a single query when
order clause is using an attribute from
Joins brings association data using
User.joins(:posts) # => SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
In the above case no posts data is selected. Above query can also produce duplicate result. To see it let's create some sample data.
With the above sample data if we execute
User.joins(:posts) then this is the result we get
#<User id: 9, name: "Neeraj"> #<User id: 9, name: "Neeraj"> #<User id: 9, name: "Neeraj"> #<User id: 10, name: "Neil">
We can avoid the duplication by using
Also if we want to make use of attributes from
posts table then we need to select them.
records = User.joins(:posts).select('distinct users.*, posts.title as posts_title').to_a records.each do |user| puts user.name puts user.posts_title end
Note that using
joins means if you use
user.posts then another query will be performed.
- Configuring Log Formatting in Rails
- Learn RubyMotion Episode 19 - Using lock code functionality when user leaves the app idle in the foreground
- How to record videos on mac using screenflow
- How to record videos on mac using QuickTime
- Git- Squashing multiple commits into single one.
- Learn RubyMotion Episode 18 - Using lock code functionality when app comes to foreground
- Learn RubyMotion Episode 17 - Change lock code
- Learn RubyMotion Episode 16 - Confirmation of lock code
- Learn RubyMotion Episode 15 - Building backspace and auto forward feature
- Learn RubyMotion Episode 14 - Building lock code functionality
- Learn RubyMotion Episode 13 - Grouped UITableView in RubyMotion
- Learn RubyMotion Episode 12 - UITabBar in RubyMotion
- Learn RubyMotion Episode 11 - MotionModel and UITableViewCellStyleValue
- Learn RubyMotion Episode 10 - Show spinner
- Learn RubyMotion Episode 9 - Send email from help screen
- Learn RubyMotion Episode 8 - Reset Password by invoking API
- Learn RubyMotion Episode 7 - Help and view for reset password
- Learn RubyMotion Episode 6 - Authentication with server
- Learn RubyMotion Episode 5 - making form interact with user
- Learn RubyMotion Episode 4 - Building login screen using RMQ part II
- Learn RubyMotion Episode 3 - Building login screen using RMQ part I
- Learn RubyMotion Episode 2 - Caching of table cells
- Learn RubyMotion Episode 1 - Table basics
- Displaying non repeating random records
- Active Record is still magical
- Getting arguments passed to command
- What is ppid
- Do not allow force push to master
- How to keep your fork up-to-date
- How to setup Pinch to Zoom for an image in RubyMotion
- Fix image orientation issue in RubyMotion
- Visitor pattern and double dispatch in ruby
- Preload, Eagerload, Includes and Joins
- Set background and header for a form created using Formotion in RubyMotion
- Cookies on Rails
- Understanding instance exec in ruby
- Rex, Rexical and Rails routing
- Journey into Rails Routing -- an under the hood look at how routing works
- Life of save in ActiveRecord
- Handling money in ruby
- Executing commands in ruby
- Redirect to www for heroku with SSL
- Solr, Sunspot, Websolr and Delayed job
- Test factories first
- CRUD application in emberjs
- Validations in emberjs application
- emberjs mixin
- Getting started with emberjs
- pjax on rails
- extend self in ruby
- to_str in ruby
- jquery-ujs and jquery trigger
- XSS and Rails
- CSRF and Rails
- tsort in ruby and rails initializers
- alias vs alias_method
- jquery deferred
- jquery delegate
- Understanding bind and bindAll in Backbone.js
- jquery live
- enhancing forms with jQuery
- jquery events
- DOM manipulation using jQuery
- Ruby pack unpack
- jQuery selectors
- jQuery domready
- jQuery introduction
- How callbacks work in Rails
- How rails boots
- How arel works
- How autoloading works in Rails
- Infinite hash and default_proc
- Mime type resolution in Rails
- Variable declaration at the top is not just pretty thing
- An inline confirmation utility powered by jQuery
- Return false has changed in jquery 1.4.3
- instance_exec , changing self and params
- $LOADED_FEATURES and require, load, require_dependency
- I am not seeing hoptoad messages. Now I know why.
- List of only the elements that contains
- Get started with nodejs in steps
- Two ways of declaring functions and impact on variable hoisting
- Practical example of need for prototypal inheritance
- return false considered harmful in live
- Simplest jQuery slideshow code explanation
- How jQuery selects elements using Sizzle
- Understanding jQuery effects queue
- jQuery edge delegate method has arrived
- jQuery show method edge case
- jQuery fadeTo method fades even the hidden elements
- Order of format matters in respond_to block
- How animate really works in jQuery
- Handling JSON parsing natively in jQuery 1.4 and what changed from jQuery 1.3
- How jQuery 1.4 fixed rest of live methods
- Hidden feature of jQuery - calling a method on a jQuery collection
- Use end more often in jQuery while building DOM elements
- How live method works in jQuery. Why it does not work in some cases. When to use livequery.
- Wrap your function with self invoking jQuery instead of performing find/replace
- jQuery custom events
- jQuery base code to create a jQuery plugin
- jQuery.Data for inspecting jQuery internals and for storing information
- Event propagation and peventDefault
- What is JSONP?
- $stdout.sync = true to flush output immediately
- How to find if my commits are executed in a transaction or not
- Restful architecture does not mean one to one mapping with model
- rescue_action_in_public, local_request? and how to configure local_request
- Override automatic updated_at in ActiveRecord/Rails
- Under the hood how named_scope works
- Why the id of nil is 4 in Ruby