Rails too many queries? - ruby
Just doing some Rails and noticed that when displaying 30 products on a single page using #products.each do it appears as though there are a lot of queries going on in the background, see below for my console output. Is this right or am I reading this entirely wrong?
Category Load (0.1ms) SELECT "categories".* FROM "categories" WHERE ("categories"."name" = 'bras') LIMIT 1
Product Load (28.0ms) SELECT "products".* FROM "products" WHERE ("products".category_id = 48)
Brand Load (0.2ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
Category Load (0.1ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
Merchant Load (0.1ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (16.9ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.8ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.7ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.4ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.4ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.6ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.6ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.4ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (2.0ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.4ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.6ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Rendered products/_product.html.erb (1.5ms)
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Update: Sorry I am specifically talking about the CACHE lines, do these mean these queries are not run everytime?
CACHE (0.0ms) SELECT "brands".* FROM "brands" WHERE ("brands"."id" = 408) LIMIT 1
CACHE (0.0ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" = 48) LIMIT 1
CACHE (0.0ms) SELECT "merchants".* FROM "merchants" WHERE ("merchants"."id" = 2) LIMIT 1
Here is the code from the product partial:
<h3><%= product.product_name %></h3>
<img src="<%= product.image %>" align="right" alt="<%= product.product_name %>" height="200" />
<p><%= truncate(product.product_description, :length => 300, :omission => "...") %></p>
<p><%= product.price %></p>
<p>Brand: <%= product.brand.brand_name %></p>
<p>Category: <%= product.category.category_name %></p>
<p>Merchant: <%= product.merchant.merchant_name %></p>
<p>More information</p>
<hr />
You might want to eager load your products/merchants/etc
#product = Product.find(conditions, :include => {:category, :brand, :merchant})
(I don't know your relations so use as needed)
EDIT in regards to your cache question, no those queries aren't run against the server, but you should definitely look into eager loading so you don't have unnecessary querying going on
For more details see the following
http://rails-bestpractices.com/posts/29-fix-n-1-queries
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html <- See Eager loading
Those CACHEd queries are only run once but you still want to join them in initially. In your controller, you will want to do #products = Product.all(:include => [:brand, :category, :merchant])
Also, it is a little bit expensive to repeatedly render a small partial. I have had better luck making the partials themselves loop over the collection:
products/_products.html.erb
<% products.each do |product| %>
<h3><%= product.product_name %></h3>
<img src="<%= product.image %>" align="right" alt="<%= product.product_name %>" height="200" />
<p><%= truncate(product.product_description, :length => 300, :omission => "...") %></p>
<p><%= product.price %></p>
<p>Brand: <%= product.brand.brand_name %></p>
<p>Category: <%= product.category.category_name %></p>
<p>Merchant: <%= product.merchant.merchant_name %></p>
<p>More information</p>
<hr />
<% end %>
Related
Select statement with a dynamic group by clause
How possible to group records conditionally? For example I have records with FLOW_NUMBER column, values 1, 2, 3. When FLOW_NUMBER value is 1, I want to group this records, but when FLOW_NUMBER is 2 or 3, I don't want to group. SELECT LISTAGG(DISTINCT PRODORD, ',') PRODORD, SUM(QTY) AS QTY FROM ( SELECT 1 AS FLOW_NUMBER, 'A' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 1 AS FLOW_NUMBER, 'B' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 1 AS FLOW_NUMBER, 'C' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 2 AS FLOW_NUMBER, 'A' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 2 AS FLOW_NUMBER, 'B' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 2 AS FLOW_NUMBER, 'C' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 3 AS FLOW_NUMBER, 'A' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 3 AS FLOW_NUMBER, 'B' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 3 AS FLOW_NUMBER, 'C' AS PRODORD, 1 AS QTY FROM DUAL ) GROUP BY FLOW_NUMBER -- bad group by clause There is example photo of group by which I need.
SELECT SUBSTR(flow,1,INSTR(flow,'/')-1) AS flow, LISTAGG(prodorder,',') WITHIN GROUP(ORDER BY prodorder) AS prodorders, SUM(qty) AS qty FROM ( SELECT CASE WHEN flow=1 THEN '1/' ELSE to_CHAR(flow)||'/'||ROWNUM END AS flow, prodorder, qty FROM DATA ) GROUP BY flow;
I don't think there is anyway to achieve it except using 2 query combined with UNION ALL clause - SELECT FLOW_NUMBER, LISTAGG(DISTINCT PRODORD, ',') PRODORD, SUM(QTY) AS QTY FROM temp WHERE FLOW_NUMBER = 1 GROUP BY FLOW_NUMBER UNION ALL SELECT FLOW_NUMBER, PRODORD, QTY FROM temp WHERE FLOW_NUMBER <> 1; Demo.
You can try this: select substr(fn,1,decode(instr(fn,','),0,1000,instr(fn,','))-1) flow_number, prodord, qty from (SELECT case when FLOW_NUMBER=1 then to_char(flow_number) else to_char(flow_number)||','||rownum end fn, LISTAGG(DISTINCT PRODORD, ',') PRODORD, SUM(QTY) AS QTY FROM ( SELECT 1 AS FLOW_NUMBER, 'A' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 1 AS FLOW_NUMBER, 'B' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 1 AS FLOW_NUMBER, 'C' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 2 AS FLOW_NUMBER, 'A' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 2 AS FLOW_NUMBER, 'B' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 2 AS FLOW_NUMBER, 'C' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 3 AS FLOW_NUMBER, 'A' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 3 AS FLOW_NUMBER, 'B' AS PRODORD, 1 AS QTY FROM DUAL UNION ALL SELECT 3 AS FLOW_NUMBER, 'C' AS PRODORD, 1 AS QTY FROM DUAL ) GROUP BY case when FLOW_NUMBER=1 then to_char(flow_number) else to_char(flow_number)||','||rownum end); I used rownum here, but you can probably replace it by other things (e.g. rowid, if the data is from a table, just be sure to have a unique value)
How to find the schema name of a table in oracle
What should I add in this given query to get the schema name of the tables? SELECT DS.TABLESPACE_NAME AS schema_name, SEGMENT_NAME AS table_name, a.num_rows AS row_count, ROUND(SUM(DS.BYTES) * 8 * 1024) AS total_space_bytes, ROUND(SUM(DS.BYTES) * 8) AS total_space_kilobytes, ROUND(SUM(DS.BYTES) / (1024/1000)) AS total_space_megabytes, CASE WHEN a.partitioned='NO' THEN 0 WHEN a.partitioned='YES'THEN 1 ELSE 0 END AS is_table_partitioned FROM DBA_SEGMENTS DS JOIN (SELECT table_name,tablespace_name,owner,num_rows,partitioned FROM all_tables)a ON a.table_name=DS.SEGMENT_NAME AND DS.TABLESPACE_NAME = a.tablespace_name WHERE segment_type='TABLE' AND SEGMENT_NAME IN (SELECT TABLE_NAME FROM DBA_TABLES) GROUP BY DS.TABLESPACE_NAME, SEGMENT_NAME,a.num_rows,a.partitioned ORDER BY SEGMENT_NAME
Add dba_segments.owner column to it (don't forget to include it into the group by clause as well): SELECT ds.tablespace_name AS schema_name, ds.owner, --> this segment_name AS table_name, a.num_rows AS row_count, ROUND (SUM (ds.bytes) * 8 * 1024) AS total_space_bytes, ROUND (SUM (ds.bytes) * 8) AS total_space_kilobytes, ROUND (SUM (ds.bytes) / (1024 / 1000)) AS total_space_megabytes, CASE WHEN a.partitioned = 'NO' THEN 0 WHEN a.partitioned = 'YES' THEN 1 ELSE 0 END AS is_table_partitioned FROM dba_segments ds JOIN (SELECT table_name, tablespace_name, owner, num_rows, partitioned FROM all_tables) a ON a.table_name = ds.segment_name AND ds.tablespace_name = a.tablespace_name WHERE segment_type = 'TABLE' AND segment_name IN (SELECT table_name FROM dba_tables) GROUP BY ds.owner, ds.tablespace_name, segment_name, a.num_rows, a.partitioned ORDER BY segment_name
Select Group on Department
I have data like below. I want to select those Emp_id where only HR is the only DEPT present. From the below, only 100994 and 100998 should be selected. **EMP_ID DEPT** 100017 FIN 100017 HR 100017 ADMIN 100994 HR 100997 ADMIN 100997 FIN 100998 HR 100999 FIN
Here's one option: SQL> with test (emp_id, dept) as 2 (select 100017, 'FIN' from dual union all 3 select 100017, 'HR' from dual union all 4 select 100017, 'ADMIN' from dual union all 5 select 100994, 'HR' from dual union all 6 select 100997, 'ADMIN' from dual union all 7 select 100997, 'FIN' from dual union all 8 select 100998, 'HR' from dual union all 9 select 100999, 'FIN' from dual 10 ) 11 select emp_id 12 from test 13 group by emp_id 14 having min(dept) = max(dept) 15 and min(dept) = 'HR'; EMP_ID ---------- 100998 100994 SQL>
I would recomment to use a subquery to count the records. If records count for specific id is more than 1 then skip the id. SELECT `emp_id`, `dept` FROM ( SELECT SUM(1) AS `count`, `emp_id`, `dept` FROM `table1` GROUP BY `emp_id` ) AS `derived` WHERE `count` = 1 AND `dept` = 'HR'
What is the conceptual difference between User.first.followers.count and User.first.followers.to_a.count?
The two Active Record queries: User.first.followers.count and User.first.followers.to_a.count evaluate to the following SQL queries respectively: [4] pry(main)> User.first.followers.count User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] (0.3ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]] => 4 [5] pry(main)> User.first.followers.to_a.count User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] User Load (0.1ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]] => 4 How are they conceptually different? This question came up in an exercise question at the end of section 14.1 in The Rails Tutorial He gives the following hint: Hint: Suppose that the user had a million followers.
Rails include with multiple tables
Please anyone help me: Using Rails I developed an application. My models look like this: class Score < ActiveRecord::Base belongs_to :song belongs_to :user end class Song < ActiveRecord::Base has_one :gsong has_many :scores end class Gsong < ActiveRecord::Base belongs_to :song end class user < ActiveRecord::Base has_many :scores end And my ScoresController: class scoresController < ApplicationController def index id = current_user.id #scores = score.where(:user_id => id) render :json => { :scores => #scores.as_json(:include => {:gsong => { :include => { :song => { :only => [:title, :album]}}, :only => [:artwork]}}, :only => [:song_id, :score]), } end It's working fine functionally, But it's making too many queries in the database like below: score Load (0.1ms) SELECT `scores`.* FROM `scores` WHERE `scores`.`user_id` = 3 Gsong Load (0.1ms) SELECT `gsongs`.* FROM `gsongs` WHERE `gsongs`.`id` = 8 LIMIT 1 Song Load (0.1ms) SELECT `songs`.* FROM `songs` WHERE `songs`.`id` = 8 LIMIT 1 Gsong Load (0.1ms) SELECT `gsongs`.* FROM `gsongs` WHERE `gsongs`.`id` = 2 LIMIT 1 Song Load (0.1ms) SELECT `songs`.* FROM `songs` WHERE `songs`.`id` = 2 LIMIT 1 Gsong Load (0.1ms) SELECT `gsongs`.* FROM `gsongs` WHERE `gsongs`.`id` = 1 LIMIT 1 Song Load (0.1ms) SELECT `songs`.* FROM `songs` WHERE `songs`.`id` = 1 LIMIT 1 Gsong Load (0.1ms) SELECT `gsongs`.* FROM `gsongs` WHERE `gsongs`.`id` = 11 LIMIT 1 Song Load (0.1ms) SELECT `songs`.* FROM `songs` WHERE `songs`.`id` = 11 LIMIT 1 Gsong Load (0.1ms) SELECT `gsongs`.* FROM `gsongs` WHERE `gsongs`.`id` = 12 LIMIT 1 Song Load (0.1ms) SELECT `songs`.* FROM `songs` WHERE `songs`.`id` = 12 LIMIT 1 Gsong Load (0.1ms) SELECT `gsongs`.* FROM `gsongs` WHERE `gsongs`.`id` = 23 LIMIT 1 Song Load (0.1ms) SELECT `songs`.* FROM `songs` WHERE `songs`.`id` = 23 LIMIT 1 How can I fetch all this data with single or two queries like: Gsong Load (0.1ms) SELECT `gsongs`.* FROM `gsongs` Song Load (0.3ms) SELECT `songs`.* FROM `songs` WHERE `songs`.`id` IN (8,2,1,11,12,23)
I would look into using ActiveModel serializers. I think you'll find it will make complex JSON like this a breeze There's a great Screencast on it at http://railscasts.com/episodes/409-active-model-serializers