在 Rails 服务器开始时在数据库中创建对象
Create objects in database as Rails server begins
我正在使用 Rails 应用程序,该应用程序当前正在创建或保存用户 class 之前和之后创建 classes。我在这条路径上遇到的问题是一个 class 正在从一个非常大的 S3 AWS 存储桶中读取,我需要将超过 7,000 个对象添加到我们的数据库中。整个过程创建对象大约需要 32 毫秒,将这些对象添加到 Batch 数据库需要 2911 毫秒。
我将其添加到我们的数据库而不是简单地读取 AWS 存储桶的原因是
1)给这些对象添加属性
2) 对象可用于 iPhone 应用程序
我很想找出一种方法,以便在 Rails 应用程序完成加载或 运行 后台代码之前读取此存储桶并将其创建到数据库中。
这是我的 Batch.rb 代码:
class Batch < ActiveRecord::Base
serialize :folder, JSON
has_many :tops
has_many :bottoms
def access_bucket
AwsAccess.new('curateanalytics', [], "", {}).sort_through_bucket
end
class AwsAccess
def initialize(bucket_name, array, current, obj)
@bucket_name = bucket_name
@array = array
@current = current
@obj = obj
@newfolder
@newbatch
@newurl
end
def access_bucket
return AWS::S3.new.buckets[@bucket_name]
end
def sort_through_bucket
access_bucket.objects.each do |obj|
if obj_is_swipe_batch?(obj)
create_new_instances(obj)
if !obj_contains_key?
add_newfolder_key
end
if !current_equals_batch?
@current = @newbatch
if array_not_array?
@obj[@newfolder] << @array
end
end
if Properties.new(@newurl).find_properties[:main_category] == "Bottoms"
@bottom = Bottoms.create({:batch_folder => @newfolder, :batch_number => @newbatch , :file_name => @newurl.split("/").last.gsub("%26","&"), :url => @newurl, :properties => Properties.new(@newurl).find_properties})
end
if Properties.new(@newurl).find_properties[:main_category] == "Tops"
@top = Tops.create({:batch_folder => @newfolder, :batch_number => @newbatch, :file_name => @newurl.split("/").last.gsub("%26","&"), :url => @newurl, :properties => Properties.new(@newurl).find_properties})
end
end
end
end
def obj_is_swipe_batch?(obj)
return ((obj.key =~ /swipe batches/) && (obj.key =~ /jpg/))
end
def create_new_instances(obj)
@newfolder = obj.key.split("/")[1]
@newbatch = obj.key.split("/")[obj.key.split("/").length-2]
@newurl = "https://s3.amazonaws.com/curateanalytics/" + obj.key.gsub('&', '%26').gsub('swipe ', 'swipe+')
end
def obj_contains_key?
@obj.key?(@newfolder)
end
def add_newfolder_key
@obj.merge!(@newfolder => [])
end
def current_equals_batch?
@current == @newbatch
end
def array_not_array?
@array != []
end
end
class Properties
def initialize(bucket_url)
@bucket_url = bucket_url
@hash = {}
end
def find_properties
read_json
parse_json
parse_main
parse_sub
return @hash
end
def read_json
@json = JSON.parse(File.read(File.join(Rails.root, 'public', 'DatabaseArray.json')))
end
def parse_json
@json.each do |main|
@main = main
end
end
def parse_main
@main.each do |sub|
@sub = sub
end
end
def parse_sub
@sub.gsub("\"","")[1..-2].split(",").each do |properties|
@property = properties.split(":")
is_everything
end
end
def is_URL?
@property.first == "URL"
end
def is_File_Name?
@property.first == "File_Name"
end
def is_Main?
@property.second == "{Main_Category"
end
def is_everything
if !is_URL? && !is_File_Name? && is_Main?
hash_merge(@property.second.gsub!("{",""),@property.last)
elsif !is_URL? && !is_File_Name?
hash_merge(@property.first,@property.last)
end
end
def hash_merge(name, property)
@hash.merge!(name.parameterize.underscore.to_sym => property)
end
end
end
到目前为止,我已经研究过将此代码作为 initializer。我可以访问 /config/initializer/batch.rb 文件,它看起来与使用 binding.pry 的 batch.rb 文件完全一样,但代码从来没有 运行s.
我通过创建自定义 rake 任务解决了这个问题。我是从这个post's second answer得出这个结论的;在研究了耙子和线程之后,我决定 运行 预先填充数据库的耙子任务最有效,因为除非我允许,否则我正在读取的 S3 存储桶不会更改。对于任何研究这个问题的人,我需要写
task :task_name => :environment do
DB0.connection
DB1.connection
...code...
end
并在没有方法的情况下重写我的代码。
虽然 运行 rake 文件需要很短的时间,但我的用户在网站上登录运行得更快。
我正在使用 Rails 应用程序,该应用程序当前正在创建或保存用户 class 之前和之后创建 classes。我在这条路径上遇到的问题是一个 class 正在从一个非常大的 S3 AWS 存储桶中读取,我需要将超过 7,000 个对象添加到我们的数据库中。整个过程创建对象大约需要 32 毫秒,将这些对象添加到 Batch 数据库需要 2911 毫秒。
我很想找出一种方法,以便在 Rails 应用程序完成加载或 运行 后台代码之前读取此存储桶并将其创建到数据库中。
这是我的 Batch.rb 代码:
class Batch < ActiveRecord::Base
serialize :folder, JSON
has_many :tops
has_many :bottoms
def access_bucket
AwsAccess.new('curateanalytics', [], "", {}).sort_through_bucket
end
class AwsAccess
def initialize(bucket_name, array, current, obj)
@bucket_name = bucket_name
@array = array
@current = current
@obj = obj
@newfolder
@newbatch
@newurl
end
def access_bucket
return AWS::S3.new.buckets[@bucket_name]
end
def sort_through_bucket
access_bucket.objects.each do |obj|
if obj_is_swipe_batch?(obj)
create_new_instances(obj)
if !obj_contains_key?
add_newfolder_key
end
if !current_equals_batch?
@current = @newbatch
if array_not_array?
@obj[@newfolder] << @array
end
end
if Properties.new(@newurl).find_properties[:main_category] == "Bottoms"
@bottom = Bottoms.create({:batch_folder => @newfolder, :batch_number => @newbatch , :file_name => @newurl.split("/").last.gsub("%26","&"), :url => @newurl, :properties => Properties.new(@newurl).find_properties})
end
if Properties.new(@newurl).find_properties[:main_category] == "Tops"
@top = Tops.create({:batch_folder => @newfolder, :batch_number => @newbatch, :file_name => @newurl.split("/").last.gsub("%26","&"), :url => @newurl, :properties => Properties.new(@newurl).find_properties})
end
end
end
end
def obj_is_swipe_batch?(obj)
return ((obj.key =~ /swipe batches/) && (obj.key =~ /jpg/))
end
def create_new_instances(obj)
@newfolder = obj.key.split("/")[1]
@newbatch = obj.key.split("/")[obj.key.split("/").length-2]
@newurl = "https://s3.amazonaws.com/curateanalytics/" + obj.key.gsub('&', '%26').gsub('swipe ', 'swipe+')
end
def obj_contains_key?
@obj.key?(@newfolder)
end
def add_newfolder_key
@obj.merge!(@newfolder => [])
end
def current_equals_batch?
@current == @newbatch
end
def array_not_array?
@array != []
end
end
class Properties
def initialize(bucket_url)
@bucket_url = bucket_url
@hash = {}
end
def find_properties
read_json
parse_json
parse_main
parse_sub
return @hash
end
def read_json
@json = JSON.parse(File.read(File.join(Rails.root, 'public', 'DatabaseArray.json')))
end
def parse_json
@json.each do |main|
@main = main
end
end
def parse_main
@main.each do |sub|
@sub = sub
end
end
def parse_sub
@sub.gsub("\"","")[1..-2].split(",").each do |properties|
@property = properties.split(":")
is_everything
end
end
def is_URL?
@property.first == "URL"
end
def is_File_Name?
@property.first == "File_Name"
end
def is_Main?
@property.second == "{Main_Category"
end
def is_everything
if !is_URL? && !is_File_Name? && is_Main?
hash_merge(@property.second.gsub!("{",""),@property.last)
elsif !is_URL? && !is_File_Name?
hash_merge(@property.first,@property.last)
end
end
def hash_merge(name, property)
@hash.merge!(name.parameterize.underscore.to_sym => property)
end
end
end
到目前为止,我已经研究过将此代码作为 initializer。我可以访问 /config/initializer/batch.rb 文件,它看起来与使用 binding.pry 的 batch.rb 文件完全一样,但代码从来没有 运行s.
我通过创建自定义 rake 任务解决了这个问题。我是从这个post's second answer得出这个结论的;在研究了耙子和线程之后,我决定 运行 预先填充数据库的耙子任务最有效,因为除非我允许,否则我正在读取的 S3 存储桶不会更改。对于任何研究这个问题的人,我需要写
task :task_name => :environment do
DB0.connection
DB1.connection
...code...
end
并在没有方法的情况下重写我的代码。
虽然 运行 rake 文件需要很短的时间,但我的用户在网站上登录运行得更快。