在 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 文件需要很短的时间,但我的用户在网站上登录运行得更快。