Reputation: 3299
I have the following Rails Code, in which it technically do two queries max, but for some reason, the console shows three different queries as shown in the screenshot below. My question is why does it run the SELECT "pages".* FROM "pages"
query for when it's not necessary?
Query
page = Page.includes(:page_roles)
page.where(is_deleted: false).index_by(&:name)
page_results = {}
page.each do |entry|
result_entry = entry.as_json;
result_entry['page_roles'] = entry.page_roles
page_results[entry.name] = result_entry
end
Console Output
Page Load (0.0ms) SELECT "pages".* FROM "pages" WHERE "pages"."is_deleted" = $1 [["is_deleted", false]]
PageRole Load (0.5ms) SELECT "page_roles".* FROM "page_roles" WHERE "page_roles"."page_id" IN (1, 2, 3, 4)
Page Load (0.5ms) SELECT "pages".* FROM "pages"
CACHE (0.0ms) SELECT "page_roles".* FROM "page_roles" WHERE "page_roles"."page_id" IN (1, 2, 3, 4)
Completed 200 OK in 117ms (Views: 16.9ms | ActiveRecord: 17.0ms)
Upvotes: 0
Views: 115
Reputation: 230531
Here's why:
page = Page.includes(:page_roles)
page.where(is_deleted: false).index_by(&:name) # your first two queries (pages + page_roles).
# query is triggered by index_by (method of enumerable, not activerecord) and result is ignored
# as it's not saved anywhere.
page_results = {}
page.each do |entry| # your second two queries. Note that this one doesn't use `is_deleted: false` filter.
# page_roles query is served from cache as it didn't change.
result_entry = entry.as_json;
result_entry['page_roles'] = entry.page_roles
page_results[entry.name] = result_entry
end
Upvotes: 1
Reputation: 1176
that's because the first assignment. You can short all of that by doing:
page_results =
Page
.includes(:page_roles)
.where(is_deleted: false)
.group_by(&:name)
Upvotes: 1
Reputation: 833
I believe this is because you've got the page.where
query which will still use the ActiveRecord query interface on the Page table and not use the ActiveRecord collection stored as page
.
Upvotes: 0