inst_data_shipper 0.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +35 -0
- data/Rakefile +21 -0
- data/app/models/hosted_data_dumper/dump_batch.rb +10 -0
- data/db/migrate/20240301090836_create_canvas_sync_sync_batches.rb +17 -0
- data/lib/inst_data_shipper/basic_dumper.rb +27 -0
- data/lib/inst_data_shipper/concerns/hooks.rb +32 -0
- data/lib/inst_data_shipper/data_sources/base.rb +7 -0
- data/lib/inst_data_shipper/data_sources/canvas_reports.rb +113 -0
- data/lib/inst_data_shipper/data_sources/local_tables.rb +33 -0
- data/lib/inst_data_shipper/destinations/base.rb +104 -0
- data/lib/inst_data_shipper/destinations/concerns/chunking.rb +34 -0
- data/lib/inst_data_shipper/destinations/hosted_data.rb +133 -0
- data/lib/inst_data_shipper/destinations/s3.rb +72 -0
- data/lib/inst_data_shipper/dumper.rb +159 -0
- data/lib/inst_data_shipper/engine.rb +8 -0
- data/lib/inst_data_shipper/jobs/async_caller.rb +19 -0
- data/lib/inst_data_shipper/jobs/base.rb +27 -0
- data/lib/inst_data_shipper/jobs/basic_dump_job.rb +11 -0
- data/lib/inst_data_shipper/record.rb +6 -0
- data/lib/inst_data_shipper/schema_builder.rb +93 -0
- data/lib/inst_data_shipper/version.rb +3 -0
- data/lib/inst_data_shipper.rb +71 -0
- data/spec/dummy/README.rdoc +1 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/config/application.rb +37 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/test.rb +44 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/routes.rb +2 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/schema.rb +45 -0
- data/spec/spec_helper.rb +70 -0
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv +3 -0
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv +4 -0
- metadata +452 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
module InstDataShipper
|
2
|
+
class Dumper
|
3
|
+
include Hooks
|
4
|
+
|
5
|
+
define_hook :initialize_dump_batch
|
6
|
+
define_hook :finalize_dump_batch
|
7
|
+
|
8
|
+
def self.perform_dump(destinations:)
|
9
|
+
raise "Must subclass Dumper to use perform_dump" if self == Dumper
|
10
|
+
|
11
|
+
dumper = new(destinations)
|
12
|
+
dumper.begin_dump
|
13
|
+
|
14
|
+
dumper.tracker
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
attr_reader :executor
|
20
|
+
|
21
|
+
def initialize(destinations = nil, executor: nil)
|
22
|
+
@raw_destinations = destinations
|
23
|
+
@executor = executor
|
24
|
+
end
|
25
|
+
|
26
|
+
def enqueue_tasks
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
|
30
|
+
def begin_dump
|
31
|
+
raise "Dump already begun" unless @raw_destinations.present?
|
32
|
+
|
33
|
+
@tracker = tracker = DumpBatch.create(job_class: self.class.to_s, status: 'in_progress')
|
34
|
+
|
35
|
+
destinations.each do |dest|
|
36
|
+
dest.initialize_dump()
|
37
|
+
end
|
38
|
+
|
39
|
+
context = {}
|
40
|
+
run_hook(:initialize_dump_batch, context)
|
41
|
+
|
42
|
+
Sidekiq::Batch.new.tap do |batch|
|
43
|
+
batch.description = "HD #{export_genre} Export #{tracker.id} Root"
|
44
|
+
batch.context = {
|
45
|
+
**context,
|
46
|
+
root_bid: batch.bid,
|
47
|
+
tracker_id: tracker.id,
|
48
|
+
origin_class: batch_context[:origin_class] || self.class.to_s,
|
49
|
+
destinations: @raw_destinations,
|
50
|
+
}
|
51
|
+
batch.on(:success, "#{self.class}#finalize_dump")
|
52
|
+
batch.on(:death, "#{self.class}#cleanup_fatal_error!")
|
53
|
+
batch.jobs do
|
54
|
+
enqueue_tasks
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO Catch errors in here and cleanup as needed
|
59
|
+
end
|
60
|
+
|
61
|
+
def upload_data(table_def, extra: nil, &datagen)
|
62
|
+
# Allow muxing, allowing a hook to prevent some files going to certain destinations
|
63
|
+
dests = destinations_for_table(table_def)
|
64
|
+
|
65
|
+
dest_groups = dests.group_by do |dest|
|
66
|
+
catch(:not_groupable) do
|
67
|
+
next dest.group_key
|
68
|
+
end
|
69
|
+
:not_groupable
|
70
|
+
end
|
71
|
+
|
72
|
+
not_groupable = dest_groups.delete(:not_groupable)
|
73
|
+
|
74
|
+
# If multiple destinations will produce the same data, only generate the chunk once...
|
75
|
+
dest_groups.each do |group_key, dests|
|
76
|
+
dests[0].chunk_data(datagen, table: table_def, extra: extra) do |chunk|
|
77
|
+
# ...and upload it to each
|
78
|
+
dests.each do |dest|
|
79
|
+
dest.upload_data_chunk(table_def, chunk)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
not_groupable&.each do |dest|
|
85
|
+
dest.chunk_data(datagen, table: table_def, extra: extra) do |chunk|
|
86
|
+
dest.upload_data_chunk(table_def, chunk)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# TODO Consider how to handle errors in this method.
|
91
|
+
# Retriable errors must not be allowed to bubble - if dest 1 succeeds and dest 2 fails, dest 1 must not be retried
|
92
|
+
# Each destination should handle its own retries
|
93
|
+
# If a destination errors-out, we should continue with the other destinations
|
94
|
+
end
|
95
|
+
|
96
|
+
def finalize_dump(_status, _opts)
|
97
|
+
run_hook(:finalize_dump_batch)
|
98
|
+
|
99
|
+
destination.each do |dest|
|
100
|
+
dest.finalize_dump
|
101
|
+
end
|
102
|
+
|
103
|
+
DumpBatch.find(batch_context[:tracker_id]).update(status: 'completed')
|
104
|
+
end
|
105
|
+
|
106
|
+
def cleanup_fatal_error!(*_args)
|
107
|
+
return unless batch.present?
|
108
|
+
|
109
|
+
run_hook(:finalize_dump_batch)
|
110
|
+
|
111
|
+
destination.each do |dest|
|
112
|
+
dest.cleanup_fatal_error
|
113
|
+
rescue StandardError # rubocop:disable Lint/SuppressedException
|
114
|
+
end
|
115
|
+
|
116
|
+
DumpBatch.find(batch_context[:tracker_id]).update(status: 'failed')
|
117
|
+
|
118
|
+
CanvasSync::JobBatches::Batch.delete_prematurely!(batch_context[:root_bid])
|
119
|
+
end
|
120
|
+
|
121
|
+
# Helper Methods
|
122
|
+
|
123
|
+
def table_schemas
|
124
|
+
return origin_class::TABLE_SCHEMAS if defined?(origin_class::TABLE_SCHEMAS)
|
125
|
+
raise NotImplementedError
|
126
|
+
end
|
127
|
+
|
128
|
+
def delayed(mthd, *args, **kwargs)
|
129
|
+
AsyncCaller.perform_later(self.class.to_s, mthd.to_s, *args, **kwargs)
|
130
|
+
end
|
131
|
+
|
132
|
+
def tracker
|
133
|
+
@tracker ||= batch_context[:tracker_id].present? ? DumpBatch.find(batch_context[:tracker_id]) : nil
|
134
|
+
end
|
135
|
+
|
136
|
+
def export_genre
|
137
|
+
self.class.to_s.gsub(/HD|ExportJob/, '')
|
138
|
+
end
|
139
|
+
|
140
|
+
def origin_class
|
141
|
+
batch_context[:origin_class]&.constantize || self.class
|
142
|
+
end
|
143
|
+
|
144
|
+
def working_dir
|
145
|
+
executor.working_dir
|
146
|
+
end
|
147
|
+
|
148
|
+
def destinations_for_table(table_def)
|
149
|
+
destinations
|
150
|
+
end
|
151
|
+
|
152
|
+
def destinations
|
153
|
+
@destinations ||= (@raw_destinations || batch_context[:destinations]).map.with_index do |dest, i|
|
154
|
+
dcls = InstDataShipper.resolve_destination(dest)
|
155
|
+
dcls.new("#{InstDataShipper.redis_prefix}:dump#{tracker.id}:dest#{i}", dest, self)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module InstDataShipper
|
2
|
+
module Jobs
|
3
|
+
class AsyncCaller < InstDataShipper::Jobs::Base
|
4
|
+
sidekiq_options retry: 6 if defined?(sidekiq_options)
|
5
|
+
|
6
|
+
def self.call_from_pool(pool, clazz, method, *args, **kwargs)
|
7
|
+
pool.add_job(
|
8
|
+
job: self,
|
9
|
+
args: [clazz.to_s, method.to_s, *args],
|
10
|
+
kwargs: kwargs,
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def perform(clazz, method, *args, **kwargs)
|
15
|
+
clazz.constantize.new(executor: self).send(method.to_sym, *args, **kwargs)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "active_job"
|
2
|
+
|
3
|
+
module InstDataShipper
|
4
|
+
module Jobs
|
5
|
+
class Base < ActiveJob::Base
|
6
|
+
attr_reader :start_time
|
7
|
+
|
8
|
+
before_perform do
|
9
|
+
@start_time = DateTime.now
|
10
|
+
end
|
11
|
+
|
12
|
+
around_perform :cleanup_working_dir
|
13
|
+
|
14
|
+
def working_dir
|
15
|
+
@working_dir ||= Dir.mktmpdir
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def cleanup_working_dir
|
21
|
+
yield if block_given?
|
22
|
+
ensure
|
23
|
+
FileUtils.remove_entry @working_dir if @working_dir
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module InstDataShipper
|
2
|
+
class SchemaBuilder
|
3
|
+
attr_reader :tables
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@tables = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.build(&block)
|
10
|
+
builder = new
|
11
|
+
builder.instance_exec(&block)
|
12
|
+
builder.tables
|
13
|
+
end
|
14
|
+
|
15
|
+
def table(model_or_name, description = nil, as: nil, includes: nil, incremental: false, &block)
|
16
|
+
as ||= model_or_name
|
17
|
+
as = as.table_name if as.respond_to?(:table_name)
|
18
|
+
|
19
|
+
tdef = {
|
20
|
+
description: description,
|
21
|
+
model: model_or_name.is_a?(String) ? nil : model_or_name,
|
22
|
+
warehouse_name: as.to_s,
|
23
|
+
incremental: incremental,
|
24
|
+
columns: [],
|
25
|
+
includes: includes,
|
26
|
+
}
|
27
|
+
|
28
|
+
TableSchemaBuilder.build(tdef, &block)
|
29
|
+
|
30
|
+
@tables << tdef
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
class TableSchemaBuilder
|
36
|
+
attr_reader :options, :columns
|
37
|
+
|
38
|
+
def initialize(table)
|
39
|
+
@options = table
|
40
|
+
@columns = table[:columns]
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.build(tdef, &block)
|
44
|
+
builder = new(tdef)
|
45
|
+
builder.instance_exec(&block)
|
46
|
+
builder.columns
|
47
|
+
end
|
48
|
+
|
49
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
50
|
+
def column(name, *args, **kwargs, &block)
|
51
|
+
name = { name => name } unless name.is_a?(Hash)
|
52
|
+
raise ArgumentError, 'Exactly one name must be provided' unless name.count == 1
|
53
|
+
|
54
|
+
cdef = {
|
55
|
+
local_name: name.keys[0].to_s,
|
56
|
+
warehouse_name: name.values[0].to_s,
|
57
|
+
transformer: block,
|
58
|
+
}
|
59
|
+
|
60
|
+
[:description, :type, :refs => :references].each do |k|
|
61
|
+
if k.is_a? Hash
|
62
|
+
k.each do |hk, hv|
|
63
|
+
cdef[hv] = kwargs.delete(hk) if kwargs.key?(hk)
|
64
|
+
end
|
65
|
+
elsif kwargs.key?(k)
|
66
|
+
cdef[k] = kwargs.delete(k)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
cdef[:references] = Array(cdef[:references])
|
71
|
+
|
72
|
+
args[0..1].each do |a|
|
73
|
+
k = (a.is_a?(String) && :description) || (a.is_a?(Symbol) && :type) || nil
|
74
|
+
raise ArgumentError, 'Unsupported Argument' if k.nil?
|
75
|
+
raise ArgumentError, "Duplicate Argument for #{k}" if cdef.key?(k)
|
76
|
+
|
77
|
+
cdef[k] = a
|
78
|
+
end
|
79
|
+
|
80
|
+
if options[:model].is_a?(Class) && cdef[:local_name].to_s.ends_with?('_id')
|
81
|
+
rel_name = cdef[:local_name].to_s[0...-3]
|
82
|
+
refl = options[:model].reflections[rel_name]
|
83
|
+
cdef[:references] << "#{refl.klass}##{refl.options[:primary_key] || 'id'}" if refl.present? && !refl.polymorphic?
|
84
|
+
end
|
85
|
+
|
86
|
+
@columns << cdef
|
87
|
+
|
88
|
+
self
|
89
|
+
end
|
90
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "canvas_sync"
|
2
|
+
|
3
|
+
require "inst_data_shipper/version"
|
4
|
+
require "inst_data_shipper/engine"
|
5
|
+
require "inst_data_shipper/record"
|
6
|
+
|
7
|
+
module InstDataShipper
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def alias_destination(from, to)
|
11
|
+
@destination_aliases ||= {}
|
12
|
+
@destination_aliases[from.to_s] = to.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def resolve_destination(destination)
|
16
|
+
return destination if destination.is_a?(Class)
|
17
|
+
|
18
|
+
if destination.is_a?(String) && destination.include?("://")
|
19
|
+
type, rest = destination.split("://", 2)
|
20
|
+
destination = @destination_aliases[type]
|
21
|
+
elsif destination.is_a?(Hash)
|
22
|
+
type = destination[:type] || destination["type"]
|
23
|
+
destination = @destination_aliases[type]
|
24
|
+
end
|
25
|
+
|
26
|
+
safe_constantize(destination)
|
27
|
+
end
|
28
|
+
|
29
|
+
def start_basic_dump(*args, **kwargs, &block)
|
30
|
+
BasicDumper.perform_dump(*args, **kwargs, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def logger
|
34
|
+
return @logger if defined? @logger
|
35
|
+
@logger = Logger.new(STDOUT)
|
36
|
+
@logger.level = Logger::DEBUG
|
37
|
+
@logger
|
38
|
+
end
|
39
|
+
|
40
|
+
def redis(*args, &blk)
|
41
|
+
CanvasSync::JobBatches::Batch.redis(*args, &blk)
|
42
|
+
end
|
43
|
+
|
44
|
+
def redis_prefix
|
45
|
+
pfx = "hdd"
|
46
|
+
pfx = "#{Apartment::Tenant.current}:#{pfx}" if defined?(Apartment)
|
47
|
+
pfx
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
Dir[File.dirname(__FILE__) + "/inst_data_shipper/concerns/**/*.rb"].each { |file| require file }
|
53
|
+
|
54
|
+
require "inst_data_shipper/schema_builder"
|
55
|
+
|
56
|
+
require "inst_data_shipper/jobs/base"
|
57
|
+
Dir[File.dirname(__FILE__) + "/inst_data_shipper/jobs/**/*.rb"].each { |file| require file }
|
58
|
+
|
59
|
+
require "inst_data_shipper/data_sources/base"
|
60
|
+
Dir[File.dirname(__FILE__) + "/inst_data_shipper/data_sources/**/*.rb"].each { |file| require file }
|
61
|
+
|
62
|
+
require "inst_data_shipper/destinations/base"
|
63
|
+
Dir[File.dirname(__FILE__) + "/inst_data_shipper/destinations/concerns/*.rb"].each { |file| require file }
|
64
|
+
Dir[File.dirname(__FILE__) + "/inst_data_shipper/destinations/*.rb"].each do |file|
|
65
|
+
require file
|
66
|
+
basename = File.basename(file, ".rb")
|
67
|
+
next if basename == "base"
|
68
|
+
|
69
|
+
InstDataShipper.alias_destination(basename.dasherize, "InstDataShipper::Destinations::#{basename.classify}")
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
Dummy Rails App for gem testing
|
data/spec/dummy/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path('../boot', __FILE__)
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
require 'active_record/railtie'
|
5
|
+
# require 'active_storage/engine'
|
6
|
+
require 'action_controller/railtie'
|
7
|
+
require 'action_view/railtie'
|
8
|
+
require 'action_mailer/railtie'
|
9
|
+
require 'active_job/railtie'
|
10
|
+
# require 'action_cable/engine'
|
11
|
+
# require 'action_mailbox/engine'
|
12
|
+
# require 'action_text/engine'
|
13
|
+
require 'rails/test_unit/railtie'
|
14
|
+
# require 'sprockets/railtie'
|
15
|
+
|
16
|
+
Bundler.require(*Rails.groups)
|
17
|
+
require "inst_data_shipper"
|
18
|
+
|
19
|
+
module Dummy
|
20
|
+
class Application < Rails::Application
|
21
|
+
# Settings in config/environments/* take precedence over those specified here.
|
22
|
+
# Application configuration should go into files in config/initializers
|
23
|
+
# -- all .rb files in that directory are automatically loaded.
|
24
|
+
|
25
|
+
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
26
|
+
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
27
|
+
# config.time_zone = 'Central Time (US & Canada)'
|
28
|
+
|
29
|
+
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
30
|
+
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
31
|
+
# config.i18n.default_locale = :de
|
32
|
+
|
33
|
+
# Do not swallow errors in after_commit/after_rollback callbacks.
|
34
|
+
# config.active_record.raise_in_transactional_callbacks = true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
default: &default
|
3
|
+
adapter: postgresql
|
4
|
+
encoding: unicode
|
5
|
+
# For details on connection pooling, see Rails configuration guide
|
6
|
+
# http://guides.rubyonrails.org/configuring.html#database-pooling
|
7
|
+
pool: <%= ENV.fetch("DB_POOL_SIZE", nil) || (ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i + 10) %>
|
8
|
+
username: <%= ENV.fetch("DB_USERNAME", "") %>
|
9
|
+
password: <%= ENV.fetch("DB_PASSWORD", "") %>
|
10
|
+
host: <%= ENV.fetch("DB_ADDRESS", "localhost") %>
|
11
|
+
|
12
|
+
development:
|
13
|
+
<<: *default
|
14
|
+
database: inst_data_shipper_development
|
15
|
+
|
16
|
+
test:
|
17
|
+
<<: *default
|
18
|
+
database: inst_data_shipper_test
|
19
|
+
|
20
|
+
production:
|
21
|
+
<<: *default
|
22
|
+
host: <%= ENV.fetch('DB_ADDRESS', 'localhost') %>
|
23
|
+
database: inst_data_shipper_production
|
24
|
+
username: <%= ENV.fetch("DB_USERNAME", "inst_data_shipper_specs_postgres_user") %>
|
25
|
+
password: <%= ENV.fetch("DB_PASSWORD", 'inst_data_shipper_specs_postgres_password') %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
Rails.application.configure do
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb.
|
3
|
+
|
4
|
+
# In the development environment your application's code is reloaded on
|
5
|
+
# every request. This slows down response time but is perfect for development
|
6
|
+
# since you don't have to restart the web server when you make code changes.
|
7
|
+
config.cache_classes = false
|
8
|
+
|
9
|
+
# Do not eager load code on boot.
|
10
|
+
config.eager_load = false
|
11
|
+
|
12
|
+
# Show full error reports and disable caching.
|
13
|
+
config.consider_all_requests_local = true
|
14
|
+
config.action_controller.perform_caching = false
|
15
|
+
|
16
|
+
# Don't care if the mailer can't send.
|
17
|
+
config.action_mailer.raise_delivery_errors = false
|
18
|
+
|
19
|
+
# Print deprecation notices to the Rails logger.
|
20
|
+
config.active_support.deprecation = :log
|
21
|
+
|
22
|
+
# Raise an error on page load if there are pending migrations.
|
23
|
+
config.active_record.migration_error = :page_load
|
24
|
+
|
25
|
+
# Debug mode disables concatenation and preprocessing of assets.
|
26
|
+
# This option may cause significant delays in view rendering with a large
|
27
|
+
# number of complex assets.
|
28
|
+
# config.assets.debug = true
|
29
|
+
|
30
|
+
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
31
|
+
# yet still be able to expire them through the digest params.
|
32
|
+
# config.assets.digest = true
|
33
|
+
|
34
|
+
# Adds additional error checking when serving assets at runtime.
|
35
|
+
# Checks for improperly declared sprockets dependencies.
|
36
|
+
# Raises helpful error messages.
|
37
|
+
# config.assets.raise_runtime_errors = true
|
38
|
+
|
39
|
+
# Raises error for missing translations
|
40
|
+
# config.action_view.raise_on_missing_translations = true
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
Rails.application.configure do
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb.
|
3
|
+
|
4
|
+
# The test environment is used exclusively to run your application's
|
5
|
+
# test suite. You never need to work with it otherwise. Remember that
|
6
|
+
# your test database is "scratch space" for the test suite and is wiped
|
7
|
+
# and recreated between test runs. Don't rely on the data there!
|
8
|
+
config.cache_classes = true
|
9
|
+
|
10
|
+
# Do not eager load code on boot. This avoids loading your whole application
|
11
|
+
# just for the purpose of running a single test. If you are using a tool that
|
12
|
+
# preloads Rails for running tests, you may have to set it to true.
|
13
|
+
config.eager_load = false
|
14
|
+
|
15
|
+
# Configure static file server for tests with Cache-Control for performance.
|
16
|
+
config.serve_static_files = true
|
17
|
+
config.static_cache_control = 'public, max-age=3600'
|
18
|
+
|
19
|
+
# Show full error reports and disable caching.
|
20
|
+
config.consider_all_requests_local = true
|
21
|
+
config.action_controller.perform_caching = false
|
22
|
+
|
23
|
+
# Raise exceptions instead of rendering exception templates.
|
24
|
+
config.action_dispatch.show_exceptions = false
|
25
|
+
|
26
|
+
# Disable request forgery protection in test environment.
|
27
|
+
config.action_controller.allow_forgery_protection = false
|
28
|
+
|
29
|
+
# Tell Action Mailer not to deliver emails to the real world.
|
30
|
+
# The :test delivery method accumulates sent emails in the
|
31
|
+
# ActionMailer::Base.deliveries array.
|
32
|
+
config.action_mailer.delivery_method = :test
|
33
|
+
|
34
|
+
# Randomize the order test cases are executed.
|
35
|
+
config.active_support.test_order = :random
|
36
|
+
|
37
|
+
# Print deprecation notices to the stderr.
|
38
|
+
config.active_support.deprecation = :stderr
|
39
|
+
|
40
|
+
config.active_job.queue_adapter = :test
|
41
|
+
|
42
|
+
# Raises error for missing translations
|
43
|
+
# config.action_view.raise_on_missing_translations = true
|
44
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Version of your assets, change this if you want to expire all your assets.
|
4
|
+
# Rails.application.config.assets.version = '1.0'
|
5
|
+
|
6
|
+
# Add additional assets to the asset load path
|
7
|
+
# Rails.application.config.assets.paths << Emoji.images_path
|
8
|
+
|
9
|
+
# Precompile additional assets.
|
10
|
+
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
11
|
+
# Rails.application.config.assets.precompile += %w( search.js )
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# This file contains settings for ActionController::ParamsWrapper which
|
4
|
+
# is enabled by default.
|
5
|
+
|
6
|
+
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
7
|
+
ActiveSupport.on_load(:action_controller) do
|
8
|
+
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
|
9
|
+
end
|
10
|
+
|
11
|
+
# To enable root element in JSON for ActiveRecord objects.
|
12
|
+
# ActiveSupport.on_load(:active_record) do
|
13
|
+
# self.include_root_in_json = true
|
14
|
+
# end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Your secret key is used for verifying the integrity of signed cookies.
|
4
|
+
# If you change this key, all old signed cookies will become invalid!
|
5
|
+
|
6
|
+
# Make sure the secret is at least 30 characters and all random,
|
7
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
8
|
+
# You can use `rake secret` to generate a secure secret key.
|
9
|
+
|
10
|
+
# Make sure the secrets in this file are kept private
|
11
|
+
# if you're sharing your code publicly.
|
12
|
+
|
13
|
+
development:
|
14
|
+
secret_key_base: 4fc03e27b5bfc390d7beaf99e739c1a9ad4264d58cd2a1db40fbb83b6ed320e1fa77fb4e0dd7c24816811170a59d65b623bc887b4ca1e0bd0c57348e9e304f73
|
15
|
+
|
16
|
+
test:
|
17
|
+
secret_key_base: 7700238de042256ef63c58a57c6bf431b6ebca79f95f66ccd04b5ad8b89761db15a9b89a85b08ace8a69ae3867462cb9514eb21d0e591d8f3881de79d7b72675
|
18
|
+
|
19
|
+
# Do not keep production secrets in the repository,
|
20
|
+
# instead read values from the environment.
|
21
|
+
production:
|
22
|
+
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|