I met a N+1 issue in this situation:
Library has many Programs. Now I want to get all the programs located a certain country, so I have a code:
country = "US"
programs = #libraries.includes(:programs).map do |library|
library.programs.where(country: country)
end
But now there is N+1 problem:
Program Load (0.8ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 15], ["country", "US"]]
Program Load (0.4ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 73], ["country", "US"]]
Program Load (0.5ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 27], ["country", "US"]]
Program Load (0.3ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 177], ["country", "US"]]
Program Load (0.3ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 38], ["country", "US"]]
Program Load (0.4ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 51], ["country", "US"]]
Program Load (0.6ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 18], ["country", "US"]]
Program Load (0.3ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 20], ["country", "US"]]
Program Load (0.5ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 42], ["country", "US"]]
Program Load (0.5ms) SELECT "programs".* FROM "programs" WHERE "programs"."library_id" = $1 AND "programs"."country" = $2 [["library_id", 39], ["country", "US"]]
Update:
My purpose is not to just filter the programs, but to use it. For example:
programs = #libraries.includes(:programs).each do |library|
if library.programs.where(country: country).size < 5
puts "US programs are less than 5 so you can still add"
end
end
Does anyone know how to solve the N+1 problem?
You can chain the where query to the includes like below
programs = #libraries.includes(:programs).where(programs: {country: country})
which should solve the N+1 problem.
See specifying-conditions-on-eager-loaded-associations
Update #1:
You can simply do it like this
programs = #libraries.includes(:programs).where(programs: {country: country}).size < 5 #returns true or false
if programs #true
puts "US programs are less than 5 so you can still add"
else #false
#your code
end
Update #2:
This should do
programs_size = #libraries.includes(:programs).where(programs: {country: country}).map { |library| library.programs.size }
Which would perform only one query and returns the size of each library.programs matching that condition as array something like below
=> [5, 4, 7, 4, 6, 2, 1]
Now you can iterate over the programs_size array and perform the logic
programs_size.each do |ps|
if ps < 5 #true
puts "US programs are less than 5 so you can still add"
else #false
#your code
end
end
Related
I have been eager loading ActiveStorage attachments as follows:
Journey.includes(created_by_user: [profile_picture_attachment: :blob])
We have been using variants and every since we upgraded to Rails 6.1 and enabled tracking Active Storage variants in database, we notice n+1 queries in the logs because of a loop as follows:
Journey.includes(created_by_user: [profile_picture_attachment: :blob]).each do |j|
j.created_by_user.profile_picture.variant(resize_to_fill: [32, 32]).processed
end
Journey Load (0.8ms) SELECT "journeys".* FROM "journeys"
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 [["id", 607]]
ActiveStorage::Attachment Load (0.6ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_type" = $1 AND "active_storage_attachments"."name" = $2 AND "active_storage_attachments"."record_id" = $3 [["record_type", "User"], ["name", "profile_picture"], ["record_id", 607]]
ActiveStorage::Blob Load (0.6ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 [["id", 144]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
I tried to eager load with the following but it doesn't seem to work:
Journey.includes(created_by_user: [profile_picture_attachment: { blob: :variant_records }])
Has anyone tried eager loading the tracked variant records to share your ideas?
Turns out there is a pull request addressing exactly this. For anyone looking for a solution, please follow the merge request.
https://github.com/rails/rails/pull/37901
It eventually winds its way to a secondary PR, which allows eager loading the stored variants. It's now merged into future versions of Rails, here was the code they used to eager load variants:
https://github.com/rails/rails/pull/40842/files
I found many questions with similar title but none of them could solve my question.
I have a model Program which has many Videos:
class Program < ActiveRecord::Base
has_many :videos
...
end
Then I have scope in Video:
class Video < ActiveRecord::Base
belongs_to :program
scope :trailer, -> { where(video_type: 0) }
...
end
Firstly, when I have a list of programs and want to access videos, I have no N+1 program with include method:
> #programs.includes(:videos).map { |p| p.videos.size }
Program Load (0.6ms) SELECT "programs".* FROM "programs" ORDER BY "programs"."id" ASC LIMIT 10
Video Load (0.5ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" IN (8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
However, when I try to get the scope, it will touch Database again:
> #programs.includes(:videos).map { |p| p.videos.trailer }
Program Load (0.6ms) SELECT "programs".* FROM "programs" ORDER BY "programs"."id" ASC LIMIT 10
Video Load (0.5ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" IN (8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
Video Load (0.4ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 8], ["video_type", 0]]
Video Load (0.4ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 9], ["video_type", 0]]
Video Load (12.4ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 10], ["video_type", 0]]
Video Load (0.3ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 11], ["video_type", 0]]
Video Load (0.3ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 12], ["video_type", 0]]
Video Load (0.3ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 13], ["video_type", 0]]
Video Load (0.3ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 14], ["video_type", 0]]
Video Load (0.3ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 15], ["video_type", 0]]
Video Load (0.4ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 16], ["video_type", 0]]
Video Load (0.4ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" = $1 AND "videos"."video_type" = $2 ORDER BY "videos"."id" ASC LIMIT 1 [["program_id", 17], ["video_type", 0]]
You can see it will load DB many times which lead to a bad performance.
#<Benchmark::Tms:0x007f95faa8fab0 #label="", #real=0.02663199999369681, #cstime=0.0, #cutime=0.0, #stime=0.0, #utime=0.019999999999999574, #total=0.019999999999999574>
One solution I can think of is to convert videos to array and search the array:
> #programs.includes(:videos).map { |program| program.videos.to_ary.select { |v| v.video_type == 0 } }
Program Load (0.5ms) SELECT "programs".* FROM "programs" WHERE "programs"."id" IN (8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
Video Load (0.4ms) SELECT "videos".* FROM "videos" WHERE "videos"."program_id" IN (17, 16, 13, 12, 11, 9, 8, 15, 14, 10)
The performance is better but the code is complex.
#<Benchmark::Tms:0x007f95faac8720 #label="", #real=0.006901999993715435, #cstime=0.0, #cutime=0.0, #stime=0.0, #utime=0.010000000000000675, #total=0.010000000000000675>
Another solution I can think of, is to add a new has_many in Program for scope:
class Program < ActiveRecord::Base
has_many :videos
has_many :trailer_videos, -> { where(video_type: 0) }, class: 'Video'
...
end
Then if I includes and call the new relation directly, it will eager load as well.
> #programs.includes(:trailer_videos).map { |program| program.trailer_videos }
Program Load (0.5ms) SELECT "programs".* FROM "programs" WHERE "programs"."id" IN (8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
Video Load (0.3ms) SELECT "videos".* FROM "videos" WHERE "videos"."video_type" = $1 AND "videos"."program_id" IN (17, 16, 13, 12, 11, 9, 8, 15, 14, 10) [["video_type", 0]]
The benchmark is below, which is super fast:
#<Benchmark::Tms:0x007f95fdea96c0 #label="", #real=0.004801000002771616, #cstime=0.0, #cutime=0.0, #stime=0.0, #utime=0.009999999999999787, #total=0.009999999999999787>
However, in this way, it will make the Program model so heavy. Because for each scope in Video, I need to added a related association in Program.
Therefore, I am looking for a better solution, which will keep the scope logic inside of Video, but without N+1 problem.
Cheers
As I said, IMO your approach of adding the has_many :trailer_videos, -> { where(video_type: 0) }, class: 'Video' is the simple and best way to counter your problem. I don't see any drawback in adding more such associations to the model.
In Rails Associations have an optional scope parameter that accepts a lambda that is applied to the Relation (see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Scopes)
So you could write your models as:
# app/models/video.rb
class Video < ActiveRecord::Base
belongs_to :program
scope :trailer, -> { where(video_type: 0) }
...
end
# app/models/program.rb
class Program < ActiveRecord::Base
has_many :videos
has_many :trailer_videos, -> { trailer }, class: 'Video'
...
end
This way you could keep the definition of the scope in Video and reuse it from Program.
A solution is to use merge with eager_load:
#programs.eager_load(:videos).merge(Video.trailer).map { |p| p.videos.size }
It produces only one query.
If the video types are known to the programmer you can use an ActiveRecord::Enum and some simple metaprogrammng to create assocations programatically for each possible value in the enum.
class Video < ActiveRecord::Base
enum video_type: [:trailer, :promo, :foo, :bar]
end
class Program < ActiveRecord::Base
# this creates trailer_videos etc assocations
Video.video_types.each do |key, int|
# eval is needed since we need to dynamically create
# the lamba for each type
has_many "#{key}_videos".to_sym, eval "->{ Video.send(#{key}) }"
end
end
I have the following code in my controller :
#unanswered_questions = Question.unanswered_with_tag(params[:tag_id]).paginate(per_page: 10, page: params[:page])
Which calls this method in my Question model:
def self.unanswered_with_tag id
joins(:taggings).where(taggings: { tag_id: id }).where(questions: { num_answers: 0})
end
I expect one sql query that fetches the first 10 unanswered questions on that page, but my logs are showing 2 queries:
Question Load (0.4ms) SELECT "questions".* FROM "questions"
INNER JOIN "taggings" ON "taggings"."question_id" = "questions"."id"
WHERE "taggings"."tag_id" = $1 AND "questions"."num_answers" = $2
ORDER BY "questions"."id" ASC LIMIT $3 OFFSET $4
[["tag_id", 3], ["num_answers", 0], ["LIMIT", 1], ["OFFSET", 0]]
^^Note the LIMIT 1 part.
And the second query :
SELECT "questions".* FROM "questions" INNER JOIN "taggings"
ON "taggings"."question_id" = "questions"."id"
WHERE "taggings"."tag_id" = $1 AND "questions"."num_answers" = $2
LIMIT $3 OFFSET $4
[["tag_id", 3], ["num_answers", 0], ["LIMIT", 10], ["OFFSET", 0]]
Which has LIMIT 10.
Why is this behaviour?
Are you running code in your view that checks whether #unanswered_questions has any rows at all (#exists? for example) to either display the values or not?
I have double everything in my logs. Not sure how to get rid of it. Any suggestions?
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 7]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 7]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 7]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 7]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 8]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 8]]
Size Load (0.3ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 8]]
Size Load (0.3ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 8]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 9]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 9]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 9]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 9]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 10]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 10]]
CACHE (0.0ms) SELECT "printers".* FROM "printers" WHERE "printers"."id" = $1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT "printers".* FROM "printers" WHERE "printers"."id" = $1 LIMIT 1 [["id", 1]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 10]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 10]]
Rails Version Rails 4.2.5
Ruby Version 2.3.0
you can add the following to application.rb
if Rails.env.development?
# Don't log to STDOUT, by default rails s will handle it
config.logger = Logger.new('/dev/null')
else
# Don't log to file, sending everything to unicorn file.
config.logger = Logger.new(STDOUT)
end
Basically rails server and rails logger both send their messages to stdout which results in duplication in the logs.
I'm having an issue with the spree_I18n gem and the Spree admin panel.
i'm trying to get the admin product filter to work on spree 3.0 stable.
I found this thread : https://github.com/spree-contrib/spree_i18n/pull/602
I changed my gemfile accordingly
This is my gemfile :
gem 'spree', github: 'spree/spree', branch: '3-0-stable'
gem 'spree_gateway', github: 'spree/spree_gateway', branch: '3-0-stable'
gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '3-0-stable'
gem 'spree_i18n', git: 'https://github.com/mvz/spree_i18n.git', branch: '3-0-ransack-translations'
I ran bundle install and bundle update spree_i18n but The admin product filter is still returning all of the products. Is there a step that I missed ?
here are the logs :
Started GET "/admin/products?utf8=%E2%9C%93&q%5Bname_cont%5D=Mug&q%5Bvariants_including_master_sku_cont%5D=&q%5Bdeleted_at_null%5D=1" for 127.0.0.1 at 2015-08-26 13:56:39 +0200
Processing by Spree::Admin::ProductsController#index as HTML
Parameters: {"utf8"=>"✓", "q"=>{"name_cont"=>"Mug", "variants_including_master_sku_cont"=>"", "deleted_at_null"=>"1"}}
Spree::User Load (0.2ms) SELECT "spree_users".* FROM "spree_users" WHERE "spree_users"."deleted_at" IS NULL AND "spree_users"."id" = $1 ORDER BY "spree_users"."id" ASC LIMIT 1 [["id", 1]]
(0.3ms) SELECT COUNT(*) FROM "spree_roles" INNER JOIN "spree_roles_users" ON "spree_roles"."id" = "spree_roles_users"."role_id" WHERE "spree_roles_users"."user_id" = $1 AND "spree_roles"."name" = $2 [["user_id", 1], ["name", "admin"]]
(0.4ms) SELECT DISTINCT COUNT(DISTINCT "spree_products"."id") FROM "spree_products" WHERE "spree_products"."deleted_at" IS NULL
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_index_table_options.html.erb (118.4ms)
(0.4ms) SELECT COUNT(DISTINCT count_column) FROM (SELECT DISTINCT "spree_products"."id" AS count_column FROM "spree_products" WHERE "spree_products"."deleted_at" IS NULL LIMIT 10 OFFSET 0) subquery_for_count
Spree::Product Load (0.5ms) SELECT DISTINCT "spree_products".* FROM "spree_products" WHERE "spree_products"."deleted_at" IS NULL ORDER BY "spree_products"."name" ASC LIMIT 10 OFFSET 0
Spree::Variant Load (0.2ms) SELECT "spree_variants".* FROM "spree_variants" WHERE "spree_variants"."deleted_at" IS NULL AND "spree_variants"."is_master" = $1 AND "spree_variants"."product_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) ORDER BY "spree_variants".position ASC [["is_master", "f"]]
Spree::Image Load (0.6ms) SELECT "spree_assets".* FROM "spree_assets" WHERE "spree_assets"."type" IN ('Spree::Image') AND "spree_assets"."viewable_type" = 'Spree::Variant' AND "spree_assets"."viewable_id" IN (17, 18, 19, 20, 21, 22, 23, 24, 25, 26) ORDER BY "spree_assets"."position" ASC
Spree::Variant Load (0.2ms) SELECT "spree_variants".* FROM "spree_variants" WHERE "spree_variants"."deleted_at" IS NULL AND "spree_variants"."is_master" = $1 AND "spree_variants"."product_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) [["is_master", "t"]]
Spree::Image Load (0.4ms) SELECT "spree_assets".* FROM "spree_assets" WHERE "spree_assets"."type" IN ('Spree::Image') AND "spree_assets"."viewable_type" = 'Spree::Variant' AND "spree_assets"."viewable_id" IN (1, 2, 3, 4, 5, 7, 6, 10, 9, 8) ORDER BY "spree_assets"."position" ASC
Spree::Price Load (0.1ms) SELECT "spree_prices".* FROM "spree_prices" WHERE "spree_prices"."deleted_at" IS NULL AND "spree_prices"."currency" = $1 AND "spree_prices"."variant_id" IN (1, 2, 3, 4, 5, 7, 6, 10, 9, 8) [["currency", "USD"]]
Spree::Product::Translation Load (0.1ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 1]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 2]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 3]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 4]]
Spree::Product::Translation Load (0.3ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 5]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 6]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 7]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 8]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 9]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 10]]
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_index_table_options.html.erb (122.8ms)
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/products/index.html.erb within spree/layouts/admin (370.4ms)
Deface: 1 overrides found for 'spree/admin/shared/_head'
Deface: 'override' matched 1 times with 'title'
Deface: [WARNING] No :original defined for 'override', you should change its definition to include:
:original => 'b94dd9df96e085d9a869128fa811ee3aaf55fab1'
Deface: 1 overrides found for 'spree/admin/shared/_translations'
Deface: 'translation' matched 1 times with 'script'
Deface: [WARNING] No :original defined for 'translation', you should change its definition to include:
:original => '6d879f5c231ff848b4e1023dc0f8b271f922269b'
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_translations.html.erb (27.2ms)
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_head.html.erb (985.0ms)
Deface: 1 overrides found for 'spree/admin/shared/_header'
Deface: 'auth_admin_login_navigation_bar' matched 1 times with '[data-hook='admin_login_navigation_bar'], #admin_login_navigation_bar[data-hook]'
Deface: [ERROR] The original source for 'auth_admin_login_navigation_bar' has changed, this override should be reviewed to ensure it's still valid.
CACHE (0.0ms) SELECT COUNT(*) FROM "spree_roles" INNER JOIN "spree_roles_users" ON "spree_roles"."id" = "spree_roles_users"."role_id" WHERE "spree_roles_users"."user_id" = $1 AND "spree_roles"."name" = $2 [["user_id", 1], ["name", "admin"]]
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree_auth_devise-2e8e08759c4d/lib/views/backend/spree/layouts/admin/_login_nav.html.erb (1.2ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_header.html.erb (15.4ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/sub_menu/_product.html.erb (3.3ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/sub_menu/_promotion.html.erb (1.2ms)
Spree::Store Load (0.4ms) SELECT "spree_stores".* FROM "spree_stores" WHERE (url like '%localhost%') ORDER BY "spree_stores"."id" ASC LIMIT 1
Spree::Store Load (0.1ms) SELECT "spree_stores".* FROM "spree_stores" WHERE "spree_stores"."default" = $1 ORDER BY "spree_stores"."id" ASC LIMIT 1 [["default", "t"]]
Spree::Country Load (0.3ms) SELECT "spree_countries".* FROM "spree_countries" WHERE "spree_countries"."id" = $1 LIMIT 1 [["id", 232]]
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/sub_menu/_configuration.html.erb (7.8ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_main_menu.html.erb (106.2ms)
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_content_header.html.erb (0.2ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_alert.html.erb (0.0ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_table_filter.html.erb (0.8ms)
Completed 200 OK in 1711ms (Views: 1697.4ms | ActiveRecord: 6.1ms)