【问题标题】:Create objects in database as Rails server begins在 Rails 服务器启动时在数据库中创建对象
【发布时间】:2015-04-19 13:43:00
【问题描述】:

我正在使用 Rails 应用程序,该应用程序当前正在创建或保存 User 类之前和之后创建类。我在这条路径上遇到的问题是一个类正在从一个非常大的 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 文件完全相同,但代码永远不会运行。

【问题讨论】:

    标签: ruby-on-rails amazon-s3 initializer


    【解决方案1】:

    我通过创建自定义 rake 任务解决了这个问题。我从这个post's second answer得出这个结论;在研究了 rake 和线程之后,我决定事先运行一个 rake 任务来填充我的数据库,因为除非我允许,否则我正在读取的 S3 存储桶不会改变。对于任何研究这个问题的人,我需要写

    task :task_name => :environment do
      DB0.connection
      DB1.connection
      ...code...
    end
    

    并在没有方法的情况下重写我的代码。

    虽然运行 rake 文件需要很短的时间,但我在网站上的用户登录运行速度要快得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-28
      • 2021-06-27
      • 1970-01-01
      • 2023-04-05
      相关资源
      最近更新 更多