I have a task like this:
namespace :company do
task :update, [:code] => :environment do |t, args|
company = Company.find_or_create_by(code: args[:code])
company.update_from_local_data
end
end
And this is the Company
class.
class Company < ActiveRecord::Base
has_many :items
def update_from_local_data
data = YAML.load(File.read(ENV['COMPANY_DATA_FILE']))
update_items(data)
end
def update_items(item_array)
item_array.each do |value|
item = items.find_or_initialize_by(name: value[:name])
item.update_attributes(value)
end
end
end
I confirmed that there is a lot of SELECT
SQL query for this code.
In controller I can handle with it, but how can I use eager loading from rake task?
Edit
Thanks for Uri's comments I see how to improve performance for save several data to Database, but I still have problem how to call find_or_initialize_by
for several items.
I found :on_duplicate_key_update
option for ActiveRecord.import
, but it can be used only with MySQL
while I'm using PostgreSQL
.
Edit 2
To explain what is the problem I created a example project.
This is a result of Company#update_from_local_data
.
I don't want SELECT
query for every Item
s.
How can I write it more efficiently?
c = Company.first
c.update_from_local_data
Item Load (0.2ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item0' LIMIT 1 [["company_id", 1]]
(0.1ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item1' LIMIT 1 [["company_id", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item2' LIMIT 1 [["company_id", 1]]
(0.1ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item3' LIMIT 1 [["company_id", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item4' LIMIT 1 [["company_id", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item5' LIMIT 1 [["company_id", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item6' LIMIT 1 [["company_id", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item7' LIMIT 1 [["company_id", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item8' LIMIT 1 [["company_id", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."company_id" = ? AND "items"."name" = 'item9' LIMIT 1 [["company_id", 1]]
(0.0ms) begin transaction
(0.0ms) commit transaction
=> [{:name=>"item0"}, {:name=>"item1"}, {:name=>"item2"}, {:name=>"item3"}, {:name=>"item4"}, {:name=>"item5"}, {:name=>"item6"}, {:name=>"item7"}, {:name=>"item8"}, {:name=>"item9"}]