dumped_railers 0.1.2 → 0.3.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 +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +9 -4
- data/CHANGELOG.md +35 -0
- data/README.md +91 -9
- data/dumped_railers.gemspec +2 -2
- data/gemfiles/{Gemfile.rails_5.2.4 → Gemfile.rails_5.2} +1 -1
- data/gemfiles/{Gemfile.rails_6.1.0 → Gemfile.rails_6.0} +0 -0
- data/gemfiles/{Gemfile.rails_6.0.3.4 → Gemfile.rails_6.1} +0 -0
- data/lib/dumped_railers.rb +31 -19
- data/lib/dumped_railers/configuration.rb +35 -0
- data/lib/dumped_railers/dump.rb +5 -3
- data/lib/dumped_railers/fixture_builder/record.rb +7 -7
- data/lib/dumped_railers/import.rb +16 -5
- data/lib/dumped_railers/preprocessor/strip_ignorables.rb +5 -1
- data/lib/dumped_railers/record_builder/fixture_set.rb +31 -9
- data/lib/dumped_railers/version.rb +1 -1
- metadata +11 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fed65c606bfe60816965d6ded3909c05b3c70e1deaa177607a4ad34adf70b4aa
|
|
4
|
+
data.tar.gz: fab8b30addebfd9d26efefe35a922cac885797c5371ed1a7c4cfa5d573381b72
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef030d65359058b04c74e91f6219bffede2dc2737ab1d3189ee6a1028a64f1f925c128df2e6d438742d9dca1277dace81082aec3d4763791c550d43467b1c50a
|
|
7
|
+
data.tar.gz: 4584cfc5ee262e40d1a6c432960b17b616c886f92fcdbd0c6a976e0e0379797e2b79d8fd8840f10c5d742661ced0dd13c373fe734bc1842b6e42a49721ba6a57
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
language: ruby
|
|
3
3
|
cache: bundler
|
|
4
|
+
before_install: gem install bundler
|
|
4
5
|
rvm:
|
|
6
|
+
- 3.0.0
|
|
5
7
|
- 2.7.2
|
|
6
8
|
- 2.6.6
|
|
7
9
|
- 2.5.8
|
|
8
10
|
gemfile:
|
|
9
|
-
- gemfiles/Gemfile.rails_6.1
|
|
10
|
-
- gemfiles/Gemfile.rails_6.0
|
|
11
|
-
- gemfiles/Gemfile.rails_5.2
|
|
12
|
-
|
|
11
|
+
- gemfiles/Gemfile.rails_6.1
|
|
12
|
+
- gemfiles/Gemfile.rails_6.0
|
|
13
|
+
- gemfiles/Gemfile.rails_5.2
|
|
14
|
+
jobs:
|
|
15
|
+
exclude:
|
|
16
|
+
- rvm: 3.0.0
|
|
17
|
+
gemfile: gemfiles/Gemfile.rails_5.2
|
data/CHANGELOG.md
CHANGED
|
@@ -8,3 +8,38 @@
|
|
|
8
8
|
- Add config options to be able to ignore specific columns
|
|
9
9
|
- Accept preprocessors to make filtering behavior pluggable and customizable
|
|
10
10
|
- Add Readme
|
|
11
|
+
|
|
12
|
+
## [0.1.1]
|
|
13
|
+
### Fixed
|
|
14
|
+
- Fix mis-handling of namespaced class names (separated by `::`)
|
|
15
|
+
|
|
16
|
+
## [0.1.2]
|
|
17
|
+
### Changed
|
|
18
|
+
- Accept wider types of reference labels, allowing spaces in-between (tentative)
|
|
19
|
+
|
|
20
|
+
## [0.1.3]
|
|
21
|
+
### Fixed
|
|
22
|
+
- Cope with relations that has different name with the actual class name
|
|
23
|
+
(e.g. associations defined using `:class_name` and `:foreign_key` options)
|
|
24
|
+
|
|
25
|
+
## [0.1.4]
|
|
26
|
+
### Changed
|
|
27
|
+
- Update documents not to eagerload DumpedRailers to prevent accidental data breakage / leakage.
|
|
28
|
+
To activate, it is preferable to require explicitly where necessary.
|
|
29
|
+
|
|
30
|
+
## [0.1.5]
|
|
31
|
+
### Added
|
|
32
|
+
- Supported in-memopry fixtures. Now users can dump into and import from in-memory fixture object without saving files.
|
|
33
|
+
|
|
34
|
+
## [0.2.0]
|
|
35
|
+
### Added
|
|
36
|
+
- Provide options to limit models to import, so that users can prohibit modification to arbitrary models.
|
|
37
|
+
- Support for Ruby 3.0.0 (requires Rails >= 6.0)
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
- Accept both global configuration as well as runtime (one-off) settings for all the available options.
|
|
41
|
+
Now all the configured settings will be overridden at runtime when the settings are provided with arguments.
|
|
42
|
+
|
|
43
|
+
## [0.3.0]
|
|
44
|
+
### Added
|
|
45
|
+
- Support `before_save`/`after_save` callbacks with import! method. The callbacks are invoked just before (or after) each table's records are saved.
|
data/README.md
CHANGED
|
@@ -22,7 +22,10 @@ This feature can particularily help you in the following senarios:
|
|
|
22
22
|
Add this line to your application's Gemfile:
|
|
23
23
|
|
|
24
24
|
```ruby
|
|
25
|
-
gem
|
|
25
|
+
# if you use this gem in production, `require: false` would be recommended
|
|
26
|
+
# to prevent accidental database leakage/breakage.
|
|
27
|
+
|
|
28
|
+
gem 'dumped_railers', require: false
|
|
26
29
|
```
|
|
27
30
|
|
|
28
31
|
And then execute:
|
|
@@ -37,7 +40,13 @@ Or install it yourself as:
|
|
|
37
40
|
|
|
38
41
|
### Getting Started
|
|
39
42
|
|
|
40
|
-
*
|
|
43
|
+
* Require dumped_railers where necessary (e.g. in your rake tasks, or script files)
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
require 'dumped_railers'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
* if you want to dump records from (let's say) User, Item, and Tag, just run the following.
|
|
41
50
|
|
|
42
51
|
```ruby
|
|
43
52
|
DumpedRailers.dump!(User, Item, Tag, base_dir: 'tmp/fixtures/')
|
|
@@ -58,24 +67,35 @@ DumpedRailers.import!('tmp/fixtures/users.yml', 'tmp/fixtures/items.yml')
|
|
|
58
67
|
|
|
59
68
|
NOTE: you at least have to provide all the dependent records, so that DumpedRailers can resolve dependencies among the fixtures provided.
|
|
60
69
|
|
|
61
|
-
###
|
|
70
|
+
### Using In-Memory Fixtures
|
|
71
|
+
|
|
72
|
+
DumpedRailers.dump! also returns an object, which can be imported directly as in-memory fixture.
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
fixtures = DumpedRailers.dump!(User, Item, Tag)
|
|
76
|
+
DumpedRailers.import!(fixtures)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
DumpedRailers does not save the fixtures when `base_dir` keyword argument is not specified.
|
|
80
|
+
|
|
81
|
+
### Ignoring Certain Columns
|
|
62
82
|
|
|
63
83
|
* By default, DumpedRailers ignore three columns - `id`, `created_at`, `updated_at`. You can always update/change this settings as follows.
|
|
64
84
|
|
|
65
85
|
```ruby
|
|
66
86
|
DumpedRailers.configure do |config|
|
|
67
|
-
config.ignorable_columns += [:published_on] # published_on will be ignored on top of default settings.
|
|
87
|
+
config.ignorable_columns += [:published_on] # :published_on will be ignored *on top of* default settings.
|
|
68
88
|
end
|
|
69
89
|
```
|
|
70
90
|
|
|
71
91
|
* of course you can totally replace the settings with your own.
|
|
72
92
|
```ruby
|
|
73
93
|
DumpedRailers.configure do |config|
|
|
74
|
-
config.ignorable_columns = %i[uuid created_on updated_on] # uuid and created_on will be ignored instead of id, created_at, updated_at
|
|
94
|
+
config.ignorable_columns = %i[uuid created_on updated_on] # :uuid and :created_on will be ignored *instead of* :id, :created_at, :updated_at
|
|
75
95
|
end
|
|
76
96
|
```
|
|
77
97
|
|
|
78
|
-
### Masking,
|
|
98
|
+
### Masking, Filtering
|
|
79
99
|
|
|
80
100
|
* you can pass `preprocessors` to DumpedRailers before it starts dump. All the attributes are filtered through preprocessors in order of registration.
|
|
81
101
|
|
|
@@ -104,7 +124,65 @@ masking_preprocessor = -> (attrs, model) { attrs.transform_values(&:upcase) }
|
|
|
104
124
|
|
|
105
125
|
NOTE: The proprocessors must return attributes in the same format `{ attributes_name: value }` so that preprocessors and dump handlers can preprocessors in nested manner.
|
|
106
126
|
|
|
107
|
-
###
|
|
127
|
+
### Limiting Import with Authorized Models Only
|
|
128
|
+
|
|
129
|
+
* In case you don't want to accept arbitrary fixtures to import, you can limit model access as follows:
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
DumpedRailers.import!(fixtures, authorized_models: [Item, Price])
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
This would allow us to import fixtures for items and prices, but reject modification on User, Purchase, Admin data.
|
|
136
|
+
|
|
137
|
+
NOTE: Only DumpedRailers.import! is affected by this option. DumpedRailers.dump! can't be scoped (at least in the current version).
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
### Setting Callbacks
|
|
141
|
+
|
|
142
|
+
* DumpedRailers can accept a `before_save` / `after_save` callbacks with import! method.
|
|
143
|
+
The callback is invoked just before/after each table's records are saved.
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
before_callback = -> (model, records) {
|
|
147
|
+
if model == User
|
|
148
|
+
# set random initial passwords before saving
|
|
149
|
+
records.each do |user|
|
|
150
|
+
user.password = user.password_confirmation = SecureRandom.hex(12)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
after_callback = -> (model, records) {
|
|
156
|
+
if model == User
|
|
157
|
+
records.each do |user|
|
|
158
|
+
user.confirm!
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
DumpedRailers.import!(fixture_path, before_save: before_callback, after_save: after_callback)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Configuration
|
|
167
|
+
|
|
168
|
+
* All the settings can be configured by either configuration (global) or arguments (at runtime).
|
|
169
|
+
* When you have duplicated setting, arguments are respected: you can always override configured settings by arguments.
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
DumpedRailers.configure do |config|
|
|
173
|
+
config.ignorable_columns = [:archived_at]
|
|
174
|
+
config.preprocessors = [FooPreprocessor, BarPreprocessor]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
DumpedRailers.dump!(Item, ignorable_columns: [:id], preprocessors: [BazPreprocessor], base_dir: 'tmp/')
|
|
178
|
+
# this would ignore `id` column, and apply BazPreprocessor only
|
|
179
|
+
|
|
180
|
+
DumpedRailers.dump!(Price, base_dir: 'tmp/')
|
|
181
|
+
# this would ignore `archived_at`, applies FooPreprocessor and BazPreprocessor
|
|
182
|
+
# (settings provided with arguments are considered as one-off, and don't survive globally)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Dump/Import under default_scope (e.g. ActsAsTenant)
|
|
108
186
|
|
|
109
187
|
* Such library builds multi-tenancy environment on one single database, using default_scope to switch over database access rights between tenants. You can incorporate data from Tenant A to Tenant B as follows. let's say we use [ActsAsTenant](https://github.com/ErwinM/acts_as_tenant)
|
|
110
188
|
|
|
@@ -146,9 +224,13 @@ class Egg < ActiveRecord::Base
|
|
|
146
224
|
end
|
|
147
225
|
```
|
|
148
226
|
|
|
149
|
-
*
|
|
227
|
+
* For the same reason, self-associated model cannot be imported currently. (might be updated in the future version)
|
|
228
|
+
|
|
229
|
+
* When an exception was raised, checking your log might give you a good hint (desperately staring at the backtrace won't give much information)
|
|
150
230
|
consider displaying `tail -f logs/development.log` while executing your script.
|
|
151
231
|
|
|
232
|
+
* DumpedRailers is tested against various association types, as long as target models and underlying tables have 1-on-1 mapping (straightforward ActiveRecord pattern). Currently we haven't test this against STI, CTI, as such. Applying this gem to such models might lead to some unexpected results.
|
|
233
|
+
|
|
152
234
|
## Development
|
|
153
235
|
|
|
154
236
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -157,7 +239,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
|
157
239
|
|
|
158
240
|
## Contributing
|
|
159
241
|
|
|
160
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
242
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/fursich/dumped_railers.
|
|
161
243
|
|
|
162
244
|
|
|
163
245
|
## License
|
data/dumped_railers.gemspec
CHANGED
|
@@ -27,9 +27,9 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
|
|
28
28
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
29
29
|
spec.add_development_dependency 'rake', '~> 12.3.3'
|
|
30
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
|
30
|
+
spec.add_development_dependency 'rspec', '~> 3.10'
|
|
31
31
|
spec.add_development_dependency 'sqlite3'
|
|
32
|
-
spec.add_development_dependency 'activerecord', '
|
|
32
|
+
spec.add_development_dependency 'activerecord', '>= 5.2'
|
|
33
33
|
spec.add_development_dependency 'database_cleaner-active_record', '~> 1.8'
|
|
34
34
|
spec.add_development_dependency 'pry'
|
|
35
35
|
spec.add_development_dependency 'pry-byebug'
|
|
File without changes
|
|
File without changes
|
data/lib/dumped_railers.rb
CHANGED
|
@@ -4,43 +4,55 @@ require 'dumped_railers/version'
|
|
|
4
4
|
require 'dumped_railers/file_helper.rb'
|
|
5
5
|
require 'dumped_railers/dump'
|
|
6
6
|
require 'dumped_railers/import'
|
|
7
|
+
require 'dumped_railers/configuration'
|
|
7
8
|
|
|
8
9
|
module DumpedRailers
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def dump!(*models, base_dir: './', preprocessors: nil)
|
|
12
|
-
preprocessors = [Preprocessor::StripIgnorables.new, *preprocessors].compact.uniq
|
|
10
|
+
extend Configuration
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
class << self
|
|
13
|
+
def dump!(*models, base_dir: nil, preprocessors: nil, ignorable_columns: nil)
|
|
14
|
+
# override global config settings when options are specified
|
|
15
|
+
runtime_options = { preprocessors: preprocessors.presence, ignorable_columns: ignorable_columns.presence }.compact.reverse_merge(dump_options.deep_dup)
|
|
16
|
+
runtime_options[:preprocessors].unshift(
|
|
17
|
+
default_preprocessor(runtime_options[:ignorable_columns])
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
fixture_handler = Dump.new(*models, preprocessors: runtime_options[:preprocessors])
|
|
21
|
+
fixtures = fixture_handler.build_fixtures!
|
|
16
22
|
fixture_handler.persist_all!(base_dir)
|
|
23
|
+
|
|
24
|
+
fixtures
|
|
17
25
|
end
|
|
18
26
|
|
|
19
|
-
def import!(*paths)
|
|
27
|
+
def import!(*paths, authorized_models: nil, before_save: nil, after_save: nil)
|
|
20
28
|
# make sure class-baseed caches starts with clean state
|
|
21
29
|
DumpedRailers::RecordBuilder::FixtureRow::RecordStore.clear!
|
|
22
30
|
DumpedRailers::RecordBuilder::DependencyTracker.clear!
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
# override global config settings when options are specified
|
|
33
|
+
runtime_options = { authorized_models: authorized_models.presence }.compact.reverse_merge(import_options)
|
|
34
|
+
|
|
35
|
+
fixture_handler = Import.new(
|
|
36
|
+
*paths,
|
|
37
|
+
authorized_models: runtime_options[:authorized_models],
|
|
38
|
+
before_save: before_save,
|
|
39
|
+
after_save: after_save,
|
|
40
|
+
)
|
|
25
41
|
fixture_handler.import_all!
|
|
26
42
|
end
|
|
27
43
|
|
|
28
|
-
|
|
44
|
+
private
|
|
29
45
|
|
|
30
|
-
def
|
|
31
|
-
|
|
46
|
+
def default_preprocessor(ignorable_columns)
|
|
47
|
+
Preprocessor::StripIgnorables.new(*ignorable_columns)
|
|
32
48
|
end
|
|
33
49
|
|
|
34
|
-
def
|
|
35
|
-
|
|
50
|
+
def dump_options
|
|
51
|
+
options.slice(:ignorable_columns, :preprocessors)
|
|
36
52
|
end
|
|
37
53
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def configure_defaults!
|
|
41
|
-
configure do |config|
|
|
42
|
-
config.ignorable_columns = IGNORABLE_COLUMNS
|
|
43
|
-
end
|
|
54
|
+
def import_options
|
|
55
|
+
options.slice(:authorized_models)
|
|
44
56
|
end
|
|
45
57
|
end
|
|
46
58
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DumpedRailers
|
|
4
|
+
module Configuration
|
|
5
|
+
extend Forwardable
|
|
6
|
+
def_delegators :@_config, :preprocessors, :ignorable_columns, :authorized_models
|
|
7
|
+
|
|
8
|
+
def configure
|
|
9
|
+
yield config
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def options
|
|
13
|
+
config.to_h
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
IGNORABLE_COLUMNS = %w[id created_at updated_at]
|
|
17
|
+
def configure_defaults!
|
|
18
|
+
clear_configuration!(
|
|
19
|
+
ignorable_columns: IGNORABLE_COLUMNS,
|
|
20
|
+
preprocessors: [],
|
|
21
|
+
authorized_models: :any,
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def config
|
|
26
|
+
@_config ||= OpenStruct.new
|
|
27
|
+
end
|
|
28
|
+
private :config
|
|
29
|
+
|
|
30
|
+
def clear_configuration!(**attrs)
|
|
31
|
+
@_config = OpenStruct.new(attrs)
|
|
32
|
+
end
|
|
33
|
+
private :clear_configuration!
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/dumped_railers/dump.rb
CHANGED
|
@@ -7,7 +7,7 @@ module DumpedRailers
|
|
|
7
7
|
class Dump
|
|
8
8
|
def initialize(*models, preprocessors: [])
|
|
9
9
|
@fixture_tables = models.map { |model|
|
|
10
|
-
FixtureBuilder::Model.new(model,
|
|
10
|
+
FixtureBuilder::Model.new(model, preprocessors: preprocessors)
|
|
11
11
|
}
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -16,8 +16,10 @@ module DumpedRailers
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def persist_all!(base_dir)
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
if base_dir
|
|
20
|
+
FileUtils.mkdir_p(base_dir)
|
|
21
|
+
FileHelper.write(*@fixtures, base_dir: base_dir)
|
|
22
|
+
end
|
|
21
23
|
end
|
|
22
24
|
end
|
|
23
25
|
end
|
|
@@ -20,18 +20,18 @@ module DumpedRailers
|
|
|
20
20
|
@model.reflect_on_all_associations.select(&:belongs_to?).each do |rel|
|
|
21
21
|
# skip ignorables
|
|
22
22
|
next unless attributes.has_key? rel.foreign_key.to_s
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
if rel.polymorphic?
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
class_name = attributes[rel.foreign_type.to_s]
|
|
26
|
+
|
|
27
27
|
attributes[rel.name.to_s] = record_label_for(
|
|
28
|
-
|
|
28
|
+
class_name,
|
|
29
29
|
attributes.delete(rel.foreign_key.to_s),
|
|
30
30
|
attributes.delete(rel.foreign_type.to_s)
|
|
31
31
|
)
|
|
32
32
|
else
|
|
33
33
|
attributes[rel.name.to_s] = record_label_for(
|
|
34
|
-
rel.
|
|
34
|
+
rel.class_name,
|
|
35
35
|
attributes.delete(rel.foreign_key.to_s)
|
|
36
36
|
)
|
|
37
37
|
end
|
|
@@ -42,10 +42,10 @@ module DumpedRailers
|
|
|
42
42
|
|
|
43
43
|
private
|
|
44
44
|
|
|
45
|
-
def record_label_for(
|
|
45
|
+
def record_label_for(class_name, id, type=nil)
|
|
46
46
|
return nil unless id
|
|
47
47
|
|
|
48
|
-
identifier = "#{
|
|
48
|
+
identifier = "#{class_name.to_s.underscore}_#{id}"
|
|
49
49
|
type_specifier = "(#{type})" if type
|
|
50
50
|
|
|
51
51
|
"__#{identifier}#{type_specifier}"
|
|
@@ -6,22 +6,33 @@ module DumpedRailers
|
|
|
6
6
|
class Import
|
|
7
7
|
attr_reader :fixture_set
|
|
8
8
|
|
|
9
|
-
def initialize(*paths)
|
|
10
|
-
@
|
|
11
|
-
@
|
|
9
|
+
def initialize(*paths, authorized_models: [], before_save: nil, after_save: nil)
|
|
10
|
+
@before_save = before_save
|
|
11
|
+
@after_save = after_save
|
|
12
|
+
|
|
13
|
+
if (paths.first.is_a? Hash)
|
|
14
|
+
@raw_fixtures = paths.first.values
|
|
15
|
+
else
|
|
16
|
+
@raw_fixtures = FileHelper.read_fixtures(*paths)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
@fixture_set = RecordBuilder::FixtureSet.new(@raw_fixtures, authorized_models: authorized_models)
|
|
12
20
|
end
|
|
13
21
|
|
|
14
|
-
def import_all!
|
|
22
|
+
def import_all!(&block)
|
|
23
|
+
fixture_set.authorize_models!
|
|
15
24
|
fixture_set.sort_by_table_dependencies!
|
|
16
25
|
@record_sets = fixture_set.build_record_sets!
|
|
17
26
|
|
|
18
27
|
ActiveRecord::Base.transaction(joinable: false, requires_new: true) do
|
|
19
28
|
# models have to be persisted one-by-one so that dependent models are able to
|
|
20
29
|
# resolve "belongs_to" (parent) association
|
|
21
|
-
@record_sets.each do |
|
|
30
|
+
@record_sets.each do |model, records|
|
|
31
|
+
@before_save.call(model, records) if @before_save
|
|
22
32
|
# FIXME: faster implementation wanted, parhaps with activerocord-import
|
|
23
33
|
# (objects needs to be reloaded somehow when using buik insert)
|
|
24
34
|
records.each(&:save!)
|
|
35
|
+
@after_save.call(model, records) if @after_save
|
|
25
36
|
end
|
|
26
37
|
end
|
|
27
38
|
end
|
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
module DumpedRailers
|
|
4
4
|
module Preprocessor
|
|
5
5
|
class StripIgnorables
|
|
6
|
+
def initialize(*ignorable_columns)
|
|
7
|
+
@ignorable_columns = ignorable_columns.compact.map(&:to_s)
|
|
8
|
+
end
|
|
9
|
+
|
|
6
10
|
def call(attributes, _model)
|
|
7
11
|
attributes.reject { |column_name, _v|
|
|
8
|
-
|
|
12
|
+
@ignorable_columns.include?(column_name)
|
|
9
13
|
}
|
|
10
14
|
end
|
|
11
15
|
end
|
|
@@ -8,35 +8,57 @@ module DumpedRailers
|
|
|
8
8
|
class FixtureSet
|
|
9
9
|
include TSort
|
|
10
10
|
attr_reader :fixture_tables, :record_sets
|
|
11
|
-
|
|
12
|
-
def initialize(raw_fixtures)
|
|
11
|
+
|
|
12
|
+
def initialize(raw_fixtures, authorized_models: [])
|
|
13
13
|
@fixture_tables = raw_fixtures.map { |raw_records| build_fixture_table(raw_records) }
|
|
14
|
+
@authorized_models = Array(authorized_models)
|
|
14
15
|
end
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
def sort_by_table_dependencies!
|
|
17
18
|
@fixture_tables.each(&:analyze_metadata_dependencies!)
|
|
18
19
|
# dependency are sorted in topological order using Active Record reflection
|
|
19
20
|
@fixture_tables = tsort
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
self
|
|
22
23
|
end
|
|
23
|
-
|
|
24
|
+
|
|
25
|
+
def authorize_models!
|
|
26
|
+
return if @authorized_models.include?(:any)
|
|
27
|
+
|
|
28
|
+
unauthorized_models = fixture_models.reject { |model|
|
|
29
|
+
@authorized_models.include? model
|
|
30
|
+
}
|
|
31
|
+
return if unauthorized_models.empty?
|
|
32
|
+
|
|
33
|
+
raise RuntimeError, <<~"ERROR_MESSAGE"
|
|
34
|
+
You are trying to import data into unauthorized models.
|
|
35
|
+
Make sure that the fixture contains records for authorized models only.
|
|
36
|
+
|
|
37
|
+
Models that are forbidden to access: #{unauthorized_models.map(&:name).join(', ')}
|
|
38
|
+
|
|
39
|
+
ERROR_MESSAGE
|
|
40
|
+
end
|
|
41
|
+
|
|
24
42
|
def build_record_sets!
|
|
25
43
|
@record_sets = @fixture_tables.map { |table|
|
|
26
44
|
[table.model, table.build_records!]
|
|
27
45
|
}.to_h
|
|
28
46
|
end
|
|
29
|
-
|
|
47
|
+
|
|
30
48
|
private
|
|
31
|
-
|
|
49
|
+
|
|
32
50
|
def build_fixture_table(raw_records)
|
|
33
51
|
FixtureTable.new(raw_records)
|
|
34
52
|
end
|
|
35
|
-
|
|
53
|
+
|
|
54
|
+
def fixture_models
|
|
55
|
+
@fixture_tables.map(&:model)
|
|
56
|
+
end
|
|
57
|
+
|
|
36
58
|
def tsort_each_node(&block)
|
|
37
59
|
@fixture_tables.each { |table| block.call(table) }
|
|
38
60
|
end
|
|
39
|
-
|
|
61
|
+
|
|
40
62
|
def tsort_each_child(node, &block)
|
|
41
63
|
dependent_nodes = @fixture_tables.select { |table| node.dependencies.include? table.model_name }
|
|
42
64
|
dependent_nodes.each &block
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dumped_railers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Koji Onishi
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '3.
|
|
47
|
+
version: '3.10'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '3.
|
|
54
|
+
version: '3.10'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: sqlite3
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -70,14 +70,14 @@ dependencies:
|
|
|
70
70
|
name: activerecord
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- - "
|
|
73
|
+
- - ">="
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
75
|
version: '5.2'
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- - "
|
|
80
|
+
- - ">="
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '5.2'
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
@@ -156,10 +156,11 @@ files:
|
|
|
156
156
|
- bin/console
|
|
157
157
|
- bin/setup
|
|
158
158
|
- dumped_railers.gemspec
|
|
159
|
-
- gemfiles/Gemfile.rails_5.2
|
|
160
|
-
- gemfiles/Gemfile.rails_6.0
|
|
161
|
-
- gemfiles/Gemfile.rails_6.1
|
|
159
|
+
- gemfiles/Gemfile.rails_5.2
|
|
160
|
+
- gemfiles/Gemfile.rails_6.0
|
|
161
|
+
- gemfiles/Gemfile.rails_6.1
|
|
162
162
|
- lib/dumped_railers.rb
|
|
163
|
+
- lib/dumped_railers/configuration.rb
|
|
163
164
|
- lib/dumped_railers/dump.rb
|
|
164
165
|
- lib/dumped_railers/file_helper.rb
|
|
165
166
|
- lib/dumped_railers/fixture_builder/model.rb
|
|
@@ -193,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
193
194
|
- !ruby/object:Gem::Version
|
|
194
195
|
version: '0'
|
|
195
196
|
requirements: []
|
|
196
|
-
rubygems_version: 3.
|
|
197
|
+
rubygems_version: 3.1.4
|
|
197
198
|
signing_key:
|
|
198
199
|
specification_version: 4
|
|
199
200
|
summary: A flexible fixture importer/exporter, that can transport ActiveRecord data
|