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

Resources