fury_dumper 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/build.yaml +43 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.rubocop.yml +67 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Breadth-first.png +0 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Depth-first.png +0 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +202 -0
- data/README.md +383 -0
- data/README.ru.md +382 -0
- data/Rakefile +8 -0
- data/app/controllers/fury_dumper/dump_process_controller.rb +25 -0
- data/config/routes.rb +6 -0
- data/fury_dumper.gemspec +37 -0
- data/lib/fury_dumper/api.rb +82 -0
- data/lib/fury_dumper/config.rb +113 -0
- data/lib/fury_dumper/dumper.rb +632 -0
- data/lib/fury_dumper/dumpers/dump_state.rb +61 -0
- data/lib/fury_dumper/dumpers/model.rb +131 -0
- data/lib/fury_dumper/dumpers/model_queue.rb +34 -0
- data/lib/fury_dumper/dumpers/relation_items.rb +79 -0
- data/lib/fury_dumper/encrypter.rb +17 -0
- data/lib/fury_dumper/engine.rb +7 -0
- data/lib/fury_dumper/version.rb +5 -0
- data/lib/fury_dumper.rb +102 -0
- data/lib/generators/fury_dumper/config_generator.rb +21 -0
- data/rails_generators/fury_dumper_config/fury_dumper_config_generator.rb +10 -0
- data/rails_generators/fury_dumper_config/templates/fury_dumper.rb +1 -0
- data/rails_generators/fury_dumper_config/templates/fury_dumper.yml +44 -0
- metadata +181 -0
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FuryDumper
|
4
|
+
module Dumpers
|
5
|
+
class Model
|
6
|
+
attr_reader :source_model, :iteration, :warnings
|
7
|
+
attr_accessor :relation_items, :root_model
|
8
|
+
|
9
|
+
def initialize(source_model:, relation_items:, iteration: 0, root_model: nil)
|
10
|
+
raise ArgumentError unless source_model.is_a?(String)
|
11
|
+
raise ArgumentError unless relation_items.is_a?(RelationItems)
|
12
|
+
raise ArgumentError unless iteration.is_a?(Numeric)
|
13
|
+
raise ArgumentError unless root_model.is_a?(Model) || root_model.nil?
|
14
|
+
|
15
|
+
@source_model = source_model
|
16
|
+
@relation_items = relation_items
|
17
|
+
@iteration = iteration
|
18
|
+
@root_model = root_model
|
19
|
+
@warnings = []
|
20
|
+
end
|
21
|
+
|
22
|
+
def copy
|
23
|
+
self.class.new(source_model: source_model,
|
24
|
+
relation_items: relation_items.copy,
|
25
|
+
iteration: iteration,
|
26
|
+
root_model: root_model)
|
27
|
+
end
|
28
|
+
|
29
|
+
delegate :table_name, to: :active_record_model
|
30
|
+
|
31
|
+
def column_names
|
32
|
+
active_record_model.columns.map(&:name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def ==(other)
|
36
|
+
raise ArgumentError unless other.is_a?(Model)
|
37
|
+
|
38
|
+
@source_model == other.source_model &&
|
39
|
+
@relation_items.eql?(other.relation_items) &&
|
40
|
+
sub_path?(other)
|
41
|
+
end
|
42
|
+
|
43
|
+
def sub_path?(other_model)
|
44
|
+
raise ArgumentError unless other_model.is_a?(Model)
|
45
|
+
|
46
|
+
min_length = [root_path.length, other_model.root_path.length].min - 1
|
47
|
+
root_path[0..min_length] == other_model.root_path[0..min_length]
|
48
|
+
end
|
49
|
+
|
50
|
+
def root_path
|
51
|
+
return [nil] if @root_model.nil?
|
52
|
+
|
53
|
+
@root_model.root_path + [@root_model.source_model]
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_full_str
|
57
|
+
buffer = "MODEL #{@source_model} by #{root_model&.source_model.presence || '-'} WHERE "
|
58
|
+
|
59
|
+
buffer += @relation_items.items.map do |item|
|
60
|
+
if item.complex
|
61
|
+
item.key
|
62
|
+
elsif item.values_for_key.count > 10
|
63
|
+
"#{item.key} = #{item.values_for_key[0..10]} and #{item.values_for_key.count - 10} elements"
|
64
|
+
else
|
65
|
+
"#{item.key} = #{item.values_for_key}"
|
66
|
+
end
|
67
|
+
end.join(' AND ')
|
68
|
+
|
69
|
+
buffer
|
70
|
+
end
|
71
|
+
|
72
|
+
def active_record_model
|
73
|
+
@source_model.constantize
|
74
|
+
end
|
75
|
+
|
76
|
+
delegate :primary_key, to: :active_record_model
|
77
|
+
|
78
|
+
def to_short_str
|
79
|
+
"#{@source_model}.#{@relation_items.keys.join(' & ')}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def fetch_complex_items
|
83
|
+
@relation_items.complex_items.map(&:key).join(' AND ')
|
84
|
+
end
|
85
|
+
|
86
|
+
def fetch_equality_items_hash
|
87
|
+
values = {}
|
88
|
+
@relation_items.equality_items.each do |item|
|
89
|
+
if active_record_model.column_names.include?(item.key)
|
90
|
+
values[item.key] = item.values_for_key
|
91
|
+
else
|
92
|
+
@warnings << "Shit relation: #{@source_model}.#{item.key} does not exist"
|
93
|
+
next
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
values
|
98
|
+
end
|
99
|
+
|
100
|
+
def all_non_scoped_models
|
101
|
+
active_record_model.reflect_on_all_associations.select { |rr| rr.scope.nil? }.map do |rr|
|
102
|
+
rr.klass.to_s
|
103
|
+
rescue NameError, LoadError => e
|
104
|
+
@warnings << e
|
105
|
+
next
|
106
|
+
end.compact.uniq
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_active_record_relation
|
110
|
+
return @active_record_relation if @active_record_relation
|
111
|
+
|
112
|
+
complex_values = fetch_complex_items
|
113
|
+
equality_values = fetch_equality_items_hash
|
114
|
+
@active_record_relation = active_record_model.where(equality_values)
|
115
|
+
.where(complex_values)
|
116
|
+
.limit(FuryDumper::Config.limit)
|
117
|
+
|
118
|
+
unless FuryDumper::Config.fast?
|
119
|
+
order_value = { primary_key => :desc }
|
120
|
+
@active_record_relation = @active_record_relation.order(order_value)
|
121
|
+
end
|
122
|
+
|
123
|
+
@active_record_relation
|
124
|
+
end
|
125
|
+
|
126
|
+
def next_iteration
|
127
|
+
@iteration + 1
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FuryDumper
|
4
|
+
module Dumpers
|
5
|
+
class ModelQueue
|
6
|
+
def initialize
|
7
|
+
@queue = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_element(model:, dump_state:)
|
11
|
+
raise ArgumentError, "Expected model as Dumpers::Model, got: #{model.class}" unless model.is_a?(Model)
|
12
|
+
|
13
|
+
unless dump_state.is_a?(DumpState)
|
14
|
+
raise ArgumentError,
|
15
|
+
"Expected dump_state as Dumpers::DumpState, got: #{dump_state.class}"
|
16
|
+
end
|
17
|
+
|
18
|
+
@queue << [model, dump_state]
|
19
|
+
end
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
@queue.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def fetch_element
|
26
|
+
@queue.delete_at(0)
|
27
|
+
end
|
28
|
+
|
29
|
+
def count
|
30
|
+
@queue.count
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FuryDumper
|
4
|
+
module Dumpers
|
5
|
+
RelationItem = Struct.new(:key, :values_for_key, :complex, :additional) do
|
6
|
+
def initialize(key:, values_for_key:, complex: false, additional: false)
|
7
|
+
super(key, values_for_key, complex, additional)
|
8
|
+
end
|
9
|
+
|
10
|
+
def eql?(other)
|
11
|
+
key == other.key
|
12
|
+
end
|
13
|
+
|
14
|
+
def copy
|
15
|
+
self.class.new(key: key, values_for_key: values_for_key.dup, complex: complex, additional: additional)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class RelationItems
|
20
|
+
attr_accessor :items
|
21
|
+
|
22
|
+
def initialize(items: [])
|
23
|
+
raise ArgumentError unless items.is_a?(Array)
|
24
|
+
raise ArgumentError unless items.all? { |item| item.is_a?(RelationItem) }
|
25
|
+
|
26
|
+
@items = items
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.new_with_key_value(item_key: 'id', item_values: [])
|
30
|
+
new(items: [RelationItem.new(key: item_key, values_for_key: item_values.compact)])
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.new_with_items(items: [])
|
34
|
+
new(items: items)
|
35
|
+
end
|
36
|
+
|
37
|
+
def eql?(other)
|
38
|
+
raise ArgumentError unless other.is_a?(RelationItems)
|
39
|
+
|
40
|
+
other.items.reject(&:additional).all? do |other_item|
|
41
|
+
items.reject(&:additional).any? { |item| item.eql?(other_item) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def equality_items
|
46
|
+
items.reject(&:complex)
|
47
|
+
end
|
48
|
+
|
49
|
+
def complex_items
|
50
|
+
items.select(&:complex)
|
51
|
+
end
|
52
|
+
|
53
|
+
def keys
|
54
|
+
items.map(&:key).sort
|
55
|
+
end
|
56
|
+
|
57
|
+
def values(key)
|
58
|
+
items.select { |item| item.key == key }.values_for_key
|
59
|
+
end
|
60
|
+
|
61
|
+
def copy
|
62
|
+
self.class.new(items: copy_items)
|
63
|
+
end
|
64
|
+
|
65
|
+
def copy_items
|
66
|
+
items.map(&:copy)
|
67
|
+
end
|
68
|
+
|
69
|
+
def copy_with_new_values(key, new_values)
|
70
|
+
new_items = copy_items
|
71
|
+
new_items.each do |item|
|
72
|
+
item.values_for_key = new_values.compact.dup if item.key == key
|
73
|
+
end
|
74
|
+
|
75
|
+
self.class.new_with_items(items: new_items)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FuryDumper
|
4
|
+
class Encrypter
|
5
|
+
KEY = "\xBE\nXx\xE2\xDB\x85\xBD\xE1j}qz?}\xB0j6\xA95\xBAy80\x95\xE6\xC1\x9D\x9F\x89\xA2t"
|
6
|
+
|
7
|
+
def self.encrypt(msg)
|
8
|
+
crypt = ActiveSupport::MessageEncryptor.new(KEY)
|
9
|
+
crypt.encrypt_and_sign(msg)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decrypt(encrypted_data)
|
13
|
+
crypt = ActiveSupport::MessageEncryptor.new(KEY)
|
14
|
+
crypt.decrypt_and_verify(encrypted_data)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/fury_dumper.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
require 'fury_dumper/version'
|
5
|
+
require 'fury_dumper/config'
|
6
|
+
require 'fury_dumper/engine'
|
7
|
+
require 'fury_dumper/dumper'
|
8
|
+
require 'fury_dumper/api'
|
9
|
+
require 'fury_dumper/dumpers/relation_items'
|
10
|
+
require 'fury_dumper/dumpers/dump_state'
|
11
|
+
require 'fury_dumper/dumpers/model_queue'
|
12
|
+
require 'fury_dumper/dumpers/model'
|
13
|
+
require 'fury_dumper/encrypter'
|
14
|
+
require 'httpclient'
|
15
|
+
require 'highline/import'
|
16
|
+
|
17
|
+
module FuryDumper
|
18
|
+
class Error < StandardError
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.configuration
|
22
|
+
@configuration ||= Config.config
|
23
|
+
end
|
24
|
+
|
25
|
+
# Start dumping
|
26
|
+
#
|
27
|
+
# @param password[String] - password for remote DB
|
28
|
+
# @param host[String] - host for remote DB
|
29
|
+
# @param port[String] - port for remote DB
|
30
|
+
# @param user[String] - username for remote DB
|
31
|
+
# @param model_name[String] - name of model for dump
|
32
|
+
# @param field_name[String] - field name for model
|
33
|
+
# @param field_values[Array|Range] - values of field_name
|
34
|
+
# @param database[String] - DB remote name
|
35
|
+
# @param debug_mode[Symbol] - debug mode (full - all msgs, short - part of msgs, none - nothing)
|
36
|
+
# @param ask[Boolean] - ask user for confirm different schema of target & remote DB
|
37
|
+
#
|
38
|
+
# @example FuryDumper.dump( password: '12345',
|
39
|
+
# host: 'localhost',
|
40
|
+
# port: '5432',
|
41
|
+
# user: 'username',
|
42
|
+
# model_name: 'User',
|
43
|
+
# field_name: 'admin_token',
|
44
|
+
# field_values: ['99999999-8888-4444-1212-111111111111'],
|
45
|
+
# database: 'staging',
|
46
|
+
# debug_mode: :short)
|
47
|
+
def self.dump(password:,
|
48
|
+
host:,
|
49
|
+
port:,
|
50
|
+
user:,
|
51
|
+
field_values:, database:, model_name: 'Lead',
|
52
|
+
field_name: 'id',
|
53
|
+
debug_mode: :none,
|
54
|
+
ask: true)
|
55
|
+
|
56
|
+
check_type(model_name, String, 'model name')
|
57
|
+
check_type(field_name, String, 'field name')
|
58
|
+
check_type(field_values, [Array, Range], 'field values')
|
59
|
+
|
60
|
+
states = []
|
61
|
+
field_values.to_a.in_groups_of(FuryDumper::Config.batch_size) do |batch|
|
62
|
+
relation_items = FuryDumper::Dumpers::RelationItems.new_with_key_value(item_key: field_name, item_values: batch)
|
63
|
+
|
64
|
+
sync = Dumper.new \
|
65
|
+
password: password,
|
66
|
+
host: host,
|
67
|
+
port: port,
|
68
|
+
user: user,
|
69
|
+
database: database,
|
70
|
+
model: FuryDumper::Dumpers::Model.new(source_model: model_name, relation_items: relation_items),
|
71
|
+
debug_mode: debug_mode
|
72
|
+
|
73
|
+
if ask && !sync.equal_schemas?
|
74
|
+
confirm = ask('Are you sure to continue? [Y/N] ') { |yn| yn.limit = 1, yn.validate = /[yn]/i }
|
75
|
+
ask = false
|
76
|
+
return unless confirm.downcase == 'y' # rubocop:disable Lint/NonLocalExitFromIterator
|
77
|
+
end
|
78
|
+
|
79
|
+
sync.sync_models
|
80
|
+
states << sync.dump_state
|
81
|
+
end
|
82
|
+
|
83
|
+
states.each_with_index do |state, index|
|
84
|
+
p "Batch ##{index}:"
|
85
|
+
state.print_statistic
|
86
|
+
end
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.check_type(field, expected_type, field_name)
|
91
|
+
is_ok = if expected_type.is_a?(Array)
|
92
|
+
expected_type.any? do |type|
|
93
|
+
field.is_a?(type)
|
94
|
+
end
|
95
|
+
else
|
96
|
+
field.is_a?(expected_type)
|
97
|
+
end
|
98
|
+
types_str = expected_type.is_a?(Array) ? expected_type.join(' or ') : expected_type
|
99
|
+
|
100
|
+
raise ArgumentError, "Expected #{field_name} as #{types_str}, got: #{field.class}" unless is_ok
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FuryDumper
|
4
|
+
module Generators
|
5
|
+
class ConfigGenerator < Rails::Generators::Base
|
6
|
+
def self.gem_root
|
7
|
+
File.expand_path('../../..', __dir__)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.source_root
|
11
|
+
# Use the templates from the 2.3.x generator
|
12
|
+
File.join(gem_root, 'rails_generators', 'fury_dumper_config', 'templates')
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate
|
16
|
+
template 'fury_dumper.rb', File.join('config', 'initializers', 'fury_dumper.rb')
|
17
|
+
template 'fury_dumper.yml', File.join('config', 'fury_dumper.yml')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
FuryDumper::Config.load("#{Rails.root}/config/fury_dumper.yml")
|
@@ -0,0 +1,44 @@
|
|
1
|
+
exclude_relations: <class_name>.<relation_name>, <class_name>.<relation_name>
|
2
|
+
batch_size: 100
|
3
|
+
ratio_records_batches: 10
|
4
|
+
fast: true
|
5
|
+
mode: wide
|
6
|
+
relative_services:
|
7
|
+
<service_name>:
|
8
|
+
database: <database_name>
|
9
|
+
host: <host>
|
10
|
+
port: <port>
|
11
|
+
user: <user>
|
12
|
+
password: <password>
|
13
|
+
tables:
|
14
|
+
<self_table_name>:
|
15
|
+
<remote_table_name>:
|
16
|
+
self_field_name: <self_field_name>
|
17
|
+
ms_model_name: <ms_model_name>
|
18
|
+
ms_field_name: <ms_field_name>
|
19
|
+
<other_remote_table_name>:
|
20
|
+
self_field_name: <self_field_name>
|
21
|
+
ms_model_name: <ms_model_name>
|
22
|
+
ms_field_name: <ms_field_name>
|
23
|
+
<other_self_table_name>:
|
24
|
+
<remote_table_name>:
|
25
|
+
self_field_name: <self_field_name>
|
26
|
+
ms_model_name: <ms_model_name>
|
27
|
+
ms_field_name: <ms_field_name>
|
28
|
+
<other_remote_table_name>:
|
29
|
+
self_field_name: <self_field_name>
|
30
|
+
ms_model_name: <ms_model_name>
|
31
|
+
ms_field_name: <ms_field_name>
|
32
|
+
<other_service_name>:
|
33
|
+
database: <database_name>
|
34
|
+
host: <host>
|
35
|
+
port: <port>
|
36
|
+
user: <user>
|
37
|
+
password: <password>
|
38
|
+
tables:
|
39
|
+
<self_table_name>:
|
40
|
+
<remote_table_name>:
|
41
|
+
self_field_name: <self_field_name>
|
42
|
+
ms_model_name: <ms_model_name>
|
43
|
+
ms_field_name: <ms_field_name>
|
44
|
+
|
metadata
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fury_dumper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nastya Patutina
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-03-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: highline
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.6'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: httpclient
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.8'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pg
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.4'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.4'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '5.0'
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 4.0.13
|
107
|
+
type: :runtime
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - "~>"
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '5.0'
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 4.0.13
|
117
|
+
description: Dump from remote DB by lead_ids interval
|
118
|
+
email:
|
119
|
+
- npatutina@gmail.con
|
120
|
+
executables: []
|
121
|
+
extensions: []
|
122
|
+
extra_rdoc_files: []
|
123
|
+
files:
|
124
|
+
- ".github/workflows/build.yaml"
|
125
|
+
- ".gitignore"
|
126
|
+
- ".rspec"
|
127
|
+
- ".rubocop.yml"
|
128
|
+
- ".ruby-version"
|
129
|
+
- ".travis.yml"
|
130
|
+
- Breadth-first.png
|
131
|
+
- CODE_OF_CONDUCT.md
|
132
|
+
- Depth-first.png
|
133
|
+
- Gemfile
|
134
|
+
- Gemfile.lock
|
135
|
+
- README.md
|
136
|
+
- README.ru.md
|
137
|
+
- Rakefile
|
138
|
+
- app/controllers/fury_dumper/dump_process_controller.rb
|
139
|
+
- config/routes.rb
|
140
|
+
- fury_dumper.gemspec
|
141
|
+
- lib/fury_dumper.rb
|
142
|
+
- lib/fury_dumper/api.rb
|
143
|
+
- lib/fury_dumper/config.rb
|
144
|
+
- lib/fury_dumper/dumper.rb
|
145
|
+
- lib/fury_dumper/dumpers/dump_state.rb
|
146
|
+
- lib/fury_dumper/dumpers/model.rb
|
147
|
+
- lib/fury_dumper/dumpers/model_queue.rb
|
148
|
+
- lib/fury_dumper/dumpers/relation_items.rb
|
149
|
+
- lib/fury_dumper/encrypter.rb
|
150
|
+
- lib/fury_dumper/engine.rb
|
151
|
+
- lib/fury_dumper/version.rb
|
152
|
+
- lib/generators/fury_dumper/config_generator.rb
|
153
|
+
- rails_generators/fury_dumper_config/fury_dumper_config_generator.rb
|
154
|
+
- rails_generators/fury_dumper_config/templates/fury_dumper.rb
|
155
|
+
- rails_generators/fury_dumper_config/templates/fury_dumper.yml
|
156
|
+
homepage: https://github.com/NastyaPatutina/fury_dumper
|
157
|
+
licenses: []
|
158
|
+
metadata:
|
159
|
+
homepage_uri: https://github.com/NastyaPatutina/fury_dumper
|
160
|
+
source_code_uri: https://github.com/NastyaPatutina/fury_dumper
|
161
|
+
rubygems_mfa_required: 'true'
|
162
|
+
post_install_message:
|
163
|
+
rdoc_options: []
|
164
|
+
require_paths:
|
165
|
+
- lib
|
166
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: 2.3.0
|
171
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
requirements: []
|
177
|
+
rubygems_version: 3.1.2
|
178
|
+
signing_key:
|
179
|
+
specification_version: 4
|
180
|
+
summary: Simple dump for main service and other microservices
|
181
|
+
test_files: []
|