Массовая вставка данных во вложенные модели - PullRequest
0 голосов
/ 13 декабря 2011

Я следовал этому фантастическому учебнику о массовой вставке данных. Все хорошо, время транзакций сократилось с 30 секунд до 1:)

Я просто не знаю, как заполнить поля в дочерней модели:

has_many :check, :dependent => :destroy
accepts_nested_attributes_for :check, :reject_if => lambda { |a| a[:value].blank? },   :allow_destroy => true   

Ранее я использовал это:

...
User.create!(:username => username, :check_attributes => [ {:attribute_name => "User-Password", :value => password, :op => ":="}])   
...

С тех пор как я перешел на другой метод, я теперь получил это в моей пользовательской модели:

  def self.activerecord_extensions_mass_insert(validate = true)
        columns = [:username]
        values = []
         10000.times do
           username = ""
           5.times { username << (i = Kernel.rand(62); i += ((i < 10) ? 48 : ((i < 36) ? 55 : 61 ))).chr }
           values.push [username]
         end
        User.import columns, values, {:validate => validate}
  end

Я пытался использовать этот и несколько других вариантов без успеха ...

  columns = [:username, :check_attributes => [ :attribute_name, :value, :op]]

Есть предложения?

1 Ответ

0 голосов
/ 14 декабря 2011

import не принимает вложенность, поэтому я думаю, что вам не повезло с этим методом.Почему бы не иметь две строки, user_sql и check_sql, а затем при циклическом ручном построении каждого оператора sql для расширенной вставки.тогда вы можете запустить запустить два запроса вместо группы.с другой стороны, вы сэкономите еще немного времени от штрафа за индексирование нескольких запросов.

отредактировано для добавления кода: вы создаете два оператора SQL одновременно, чтобы их можно было передавать друг другу через user_id,затем в конце вы можете выполнить.Если этот материал когда-нибудь попадет в производство, оберните вызовы sql в транзакцию, чтобы не было несчастных случаев.

user_sql = "INSERT into users (id,username,password) VALUES\n"
check_sql = "INSERT into check_attributes (user_id,foo,bar) VALUES\n"
random_data_pool = [('0'..'9'),('A'..'Z'),('a'..'z')].collect(&:to_a).flatten
max_loop = 10

1.upto(max_loop) do |i|
 seperator = (i == max_loop) ? ';' : ",\n"
 username = (1..5).map{ random_data_pool[Kernel.rand(random_data_pool.size)] }.join
 password = (1..5).map{ random_data_pool[Kernel.rand(random_data_pool.size)] }.join
 user_sql += "(#{i},'#{username}','#{password}')" + seperator
 check_sql +="(#{i},true,'potato')" + seperator
end


ActiveRecord::Base.connection.execute(user_sql)
ActiveRecord::Base.connection.execute(check_sql)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...