sorted_seeder 0.0.10
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 +15 -0
- data/.gitignore +18 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +111 -0
- data/Rakefile +1 -0
- data/lib/sorted_seeder/seeder.rb +447 -0
- data/lib/sorted_seeder/version.rb +3 -0
- data/lib/sorted_seeder.rb +6 -0
- data/sorted_seeder.gemspec +23 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NjkxYWFhMjE3MTQ5MzZiZmQwYjdiYmE1ZjcyOTk0YjNjYTE1OTYxZQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NTA2ODBiNmQyMjEzYzc2MDYxZmVhNzMzMDg2NGQ3MWRkOTFkZTc1Mw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YWJhZWQ1NTdiYTdkNzZiZGU1MDI4M2E1OTE4OGQ0ZTYxOWUwYjcwZjMzOTlm
|
10
|
+
YzU0MDI5ZDlmNDMyMWNlMGQ4NWU4NjJkOTUwZDJmOTNjYTMyMzQ5MzE4Zjkx
|
11
|
+
ZjhhN2I2NGRjYzcxMGIwYjE2NjVkYTI2NzRmM2E0OTFiOTYwMzE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZjQ5NzQ4Yzg3OTM5OTM4MmUxMTNlZDUxMDEwNDYzNmY0NDgwMWQ5YjU2NDQ3
|
14
|
+
ODI3YmU3ZGE3YTJjMjU0OTI5OWZhOTczMjRkMWMxYmU4NzY0OTlkYzA3NmYw
|
15
|
+
MTMwMGExMjM1M2U1ZTExMDk1NmQwMTI1ODZkZDlkZTEwYTZjMzQ=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 RealNobody
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# SortedSeeder
|
2
|
+
|
3
|
+
SortedSeeder is a small utility for organizing how your system is seeded.
|
4
|
+
|
5
|
+
**When using this system, all seeding actions are expected to be idempotent.** That is,
|
6
|
+
the seed system assumes that the seed function can safely be called multiple times without causing any problems with
|
7
|
+
the data.
|
8
|
+
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'sorted_seeder'
|
15
|
+
|
16
|
+
OR
|
17
|
+
|
18
|
+
gem 'sorted_seeder', :git => "git@github.com:RealNobody/sorted_seeder.git"
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install sorted_seeder
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Seeding
|
31
|
+
|
32
|
+
To seed the database, simply call:
|
33
|
+
|
34
|
+
`SortedSeeder::Seeder.seed_all`
|
35
|
+
|
36
|
+
This is the master function which will perform all seeding tasks. Seeding tasks are split into two types of seeding
|
37
|
+
tasks which are generally performed in this order:
|
38
|
+
|
39
|
+
1. Database seeding
|
40
|
+
2. Generic seeding
|
41
|
+
|
42
|
+
I recommend putting this call into your `/db/seeds.rb` and make that file simply:
|
43
|
+
|
44
|
+
require "sorted_seeder"
|
45
|
+
|
46
|
+
SortedSeeder::Seeder.seed_all
|
47
|
+
|
48
|
+
|
49
|
+
#### Database Seeding
|
50
|
+
|
51
|
+
There are 2 different ways to seed a database table, which are tried in this order:
|
52
|
+
|
53
|
+
1. A special seeding class will be looked for that matches the name of the database table class with "Seeder"
|
54
|
+
appended. (i.e. if the database class is `MyTable`, then the seeder class that will be looked for is `MyTableSeeder`.
|
55
|
+
A class function named `seed` will be called on this class to seed the table. If the class cannot be found, the
|
56
|
+
system will look for the appropriately underscore named file in `<Rails.root>/db/seeders/`. (i.e.
|
57
|
+
`<Rails.root>/db/seeders/my_table_seeder.rb`
|
58
|
+
2. A class function named `seed` will be called on the class for the database table.
|
59
|
+
|
60
|
+
I don't recommend the second option, but I support it because this was the initial implementation I made.
|
61
|
+
|
62
|
+
#### Generic Seeding
|
63
|
+
|
64
|
+
All *.rb files under the `<Rails.root>/db/seeders/` folder will be loaded. The full path under the seeder folder
|
65
|
+
will be classified to create a class name for the expected class within the file. That class will be constantized
|
66
|
+
and if the class exists and has a `seed` class function, that function will be called.
|
67
|
+
|
68
|
+
Example custom seed file for a database table named `users`: `/db/seeders/user_seeder.rb`
|
69
|
+
|
70
|
+
class UserSeeder
|
71
|
+
class << self
|
72
|
+
def seed
|
73
|
+
User.find_or_initialize_by(email: "my@email.com").tap do |user|
|
74
|
+
user.name = "Seeded User"
|
75
|
+
user.save!()
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
Example seeder for a non SQL database resource like Redis: `/db/seeders/zip_seeder.rb`
|
82
|
+
|
83
|
+
class ZipSeeder
|
84
|
+
class << self
|
85
|
+
def seed
|
86
|
+
# Load information into Redis
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
#### Seeding order
|
92
|
+
|
93
|
+
Database tables are by default sorted based on the relationships defined in the table classes such that tables which
|
94
|
+
depend on other tables are seeded after the tables that they depend on.
|
95
|
+
|
96
|
+
If there is a cyclic dependency, there is no guarantee in which order the tables will be seeded.
|
97
|
+
|
98
|
+
Custom seed classes can define when they are called by overriding the `<=>(right_operator)` method which is called
|
99
|
+
when sorting the seeding classes. The right operator will either be another custom sorter class or an instance of
|
100
|
+
the SortedSeeder::Seeder class which represents the seeder for a table. This class exposes the `table` that it will seed.
|
101
|
+
|
102
|
+
NOTE: A SortedSeeder:Seeder is created for every table so that you can insert a custom seeder before or after any table
|
103
|
+
you may need to.
|
104
|
+
|
105
|
+
## Contributing
|
106
|
+
|
107
|
+
1. Fork it
|
108
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
109
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
110
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
111
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,447 @@
|
|
1
|
+
module SortedSeeder
|
2
|
+
class Seeder
|
3
|
+
attr_reader :table
|
4
|
+
attr_reader :seeder_class
|
5
|
+
|
6
|
+
@@create_order = nil
|
7
|
+
@@seeder_classes = nil
|
8
|
+
@@database_connection = nil
|
9
|
+
|
10
|
+
class SeederSorter
|
11
|
+
attr_accessor :seed_base_object
|
12
|
+
|
13
|
+
def initialize(seed_base_object)
|
14
|
+
@seed_base_object = seed_base_object
|
15
|
+
end
|
16
|
+
|
17
|
+
def <=>(other_object)
|
18
|
+
compare_value = nil
|
19
|
+
compare_value = (@seed_base_object <=> other_object.seed_base_object) if @seed_base_object.respond_to?(:<=>)
|
20
|
+
|
21
|
+
unless compare_value
|
22
|
+
compare_value = (other_object.seed_base_object <=> @seed_base_object) if other_object.seed_base_object.respond_to?(:<=>)
|
23
|
+
|
24
|
+
if compare_value
|
25
|
+
compare_value = -1 * compare_value
|
26
|
+
else
|
27
|
+
if other_object.seed_base_object.is_a?(Class)
|
28
|
+
if seed_base_object.is_a?(Class)
|
29
|
+
compare_value = (seed_base_object.name <=> other_object.seed_base_object.name)
|
30
|
+
else
|
31
|
+
compare_value = -1
|
32
|
+
end
|
33
|
+
else
|
34
|
+
if seed_base_object.is_a?(Class)
|
35
|
+
compare_value = 1
|
36
|
+
else
|
37
|
+
compare_value = 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
compare_value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class << self
|
48
|
+
def seed_all(db_connection = nil)
|
49
|
+
seeder_classes(db_connection).each do |seed_class|
|
50
|
+
seed_class.seed
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def seeder_classes(db_connection = nil)
|
55
|
+
unless @@seeder_classes
|
56
|
+
@@seeder_classes = []
|
57
|
+
|
58
|
+
# table object seeders
|
59
|
+
SortedSeeder::Seeder.create_order(db_connection).each do |table|
|
60
|
+
table_seed_class = SortedSeeder::Seeder.seed_class(table.name)
|
61
|
+
|
62
|
+
if !table_seed_class && table.respond_to?(:seed)
|
63
|
+
table_seed_class = table
|
64
|
+
end
|
65
|
+
|
66
|
+
@@seeder_classes << SortedSeeder::Seeder.new(table, table_seed_class)
|
67
|
+
end
|
68
|
+
|
69
|
+
# table object seeders
|
70
|
+
SortedSeeder::Seeder.unclassed_tables(db_connection).each do |table|
|
71
|
+
table_seed_class = SortedSeeder::Seeder.seed_class(table)
|
72
|
+
|
73
|
+
@@seeder_classes << SortedSeeder::Seeder.new(table, table_seed_class)
|
74
|
+
end
|
75
|
+
|
76
|
+
if Object.const_defined?("Rails", false)
|
77
|
+
seeder_root = Rails.root.join("db/seeders/").to_s
|
78
|
+
seeder_files = Dir[Rails.root.join("db/seeders/**/*.rb")]
|
79
|
+
|
80
|
+
seeder_files.each do |seeder_file|
|
81
|
+
class_name = File.basename(seeder_file, ".rb").classify
|
82
|
+
|
83
|
+
check_class, full_module_name = find_file_class(seeder_file, seeder_root)
|
84
|
+
unless check_class && check_class.const_defined?(class_name, false)
|
85
|
+
require seeder_file
|
86
|
+
check_class, full_module_name = find_file_class(seeder_file, seeder_root)
|
87
|
+
end
|
88
|
+
|
89
|
+
if check_class
|
90
|
+
full_module_name << class_name
|
91
|
+
if check_class.const_defined?(class_name, false)
|
92
|
+
check_class = full_module_name.join("::").constantize
|
93
|
+
else
|
94
|
+
check_class = nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
if check_class && check_class.respond_to?(:seed)
|
99
|
+
unless @@seeder_classes.include?(check_class) ||
|
100
|
+
@@seeder_classes.any? { |seeder| seeder.is_a?(SortedSeeder::Seeder) && seeder.seeder_class == check_class }
|
101
|
+
@@seeder_classes << check_class
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
seed_sorts = @@seeder_classes.map { |seed_class| SeederSorter.new(seed_class) }
|
108
|
+
seed_sorts.sort!
|
109
|
+
|
110
|
+
@@seeder_classes = seed_sorts.map(&:seed_base_object)
|
111
|
+
end
|
112
|
+
|
113
|
+
@@seeder_classes
|
114
|
+
end
|
115
|
+
|
116
|
+
def find_file_class(seeder_file, seeder_root)
|
117
|
+
check_class = Object
|
118
|
+
full_module_name = []
|
119
|
+
|
120
|
+
File.dirname(seeder_file.to_s[seeder_root.length..-1]).split("/").map do |module_element|
|
121
|
+
if (module_element != ".")
|
122
|
+
full_module_name << module_element.classify
|
123
|
+
if check_class.const_defined?(full_module_name[-1], false)
|
124
|
+
check_class = full_module_name.join("::").constantize
|
125
|
+
else
|
126
|
+
check_class = nil
|
127
|
+
break
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
return check_class, full_module_name
|
133
|
+
end
|
134
|
+
|
135
|
+
def unclassed_tables(db_connection = nil)
|
136
|
+
create_order(db_connection)
|
137
|
+
|
138
|
+
@@other_tables
|
139
|
+
end
|
140
|
+
|
141
|
+
def create_order(db_connection = nil)
|
142
|
+
unless @@create_order
|
143
|
+
@@database_connection = db_connection
|
144
|
+
|
145
|
+
if Object.const_defined?("ActiveRecord", false) && ActiveRecord.const_defined?("Base", false)
|
146
|
+
@@database_connection ||= ActiveRecord::Base
|
147
|
+
end
|
148
|
+
|
149
|
+
if Object.const_defined?("Sequel", false) && Sequel.const_defined?("Model", false)
|
150
|
+
@@database_connection ||= Sequel::DATABASES[0]
|
151
|
+
end
|
152
|
+
|
153
|
+
@@create_order = []
|
154
|
+
@@other_tables = []
|
155
|
+
|
156
|
+
if Object.const_defined?("ActiveRecord", false) && ActiveRecord.const_defined?("Base", false)
|
157
|
+
active_record_create_order
|
158
|
+
end
|
159
|
+
|
160
|
+
if Object.const_defined?("Sequel", false) && Sequel.const_defined?("Model", false)
|
161
|
+
sequel_record_create_order
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
@@create_order
|
166
|
+
end
|
167
|
+
|
168
|
+
def active_record_create_order
|
169
|
+
table_objects = []
|
170
|
+
polymorphic_tables = {}
|
171
|
+
|
172
|
+
@@database_connection.connection rescue nil
|
173
|
+
if @@database_connection.respond_to?(:connected?) && @@database_connection.connected?
|
174
|
+
@@database_connection.connection.tables.each do |table_name|
|
175
|
+
table = nil
|
176
|
+
|
177
|
+
seeder = SortedSeeder::Seeder.seed_class(table_name, true)
|
178
|
+
if seeder && seeder.respond_to?(:table)
|
179
|
+
table = seeder.table
|
180
|
+
end
|
181
|
+
if !table && Object.const_defined?(table_name.to_s.classify)
|
182
|
+
table = table_name.to_s.classify.constantize
|
183
|
+
end
|
184
|
+
|
185
|
+
# is_a?(ActiveRecord::Base) doesn't work, so I am doing it this way...
|
186
|
+
table_is_active_record = false
|
187
|
+
table_super_class = table.superclass if table
|
188
|
+
while !table_is_active_record && table_super_class
|
189
|
+
table_is_active_record = (table_super_class == ActiveRecord::Base)
|
190
|
+
table_super_class = table_super_class.superclass
|
191
|
+
end
|
192
|
+
|
193
|
+
if table && table_is_active_record
|
194
|
+
table_objects << table
|
195
|
+
else
|
196
|
+
SortedSeeder::Seeder.unclassed_tables << table_name
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
table_objects.each do |table|
|
201
|
+
[:has_one, :has_many].each do |relationship|
|
202
|
+
table.reflect_on_all_associations(relationship).each do |association|
|
203
|
+
if association.options[:as]
|
204
|
+
polymorphic_tables[association.class_name] ||= []
|
205
|
+
|
206
|
+
unless polymorphic_tables[association.class_name].include?(table)
|
207
|
+
polymorphic_tables[association.class_name] << table
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
table_objects.each do |table|
|
215
|
+
unless SortedSeeder::Seeder.create_order.include?(table)
|
216
|
+
prev_table = active_record_pre_table(table, polymorphic_tables, [])
|
217
|
+
|
218
|
+
while (prev_table)
|
219
|
+
SortedSeeder::Seeder.create_order << prev_table
|
220
|
+
prev_table = active_record_pre_table(table, polymorphic_tables, [])
|
221
|
+
end
|
222
|
+
|
223
|
+
SortedSeeder::Seeder.create_order << table
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def sequel_record_create_order
|
230
|
+
if Sequel::DATABASES.length > 0
|
231
|
+
table_objects = []
|
232
|
+
polymorphic_tables = {}
|
233
|
+
|
234
|
+
raise("Unsure what database to use.") if Sequel::DATABASES.length > 1
|
235
|
+
@@database_connection.tables.each do |table_name|
|
236
|
+
table = nil
|
237
|
+
|
238
|
+
seeder = SortedSeeder::Seeder.seed_class(table_name, true)
|
239
|
+
if seeder && seeder.respond_to?(:table)
|
240
|
+
table = seeder.table
|
241
|
+
end
|
242
|
+
if !table && Object.const_defined?(table_name.to_s.classify)
|
243
|
+
table = table_name.to_s.classify.constantize
|
244
|
+
end
|
245
|
+
|
246
|
+
# is_a?(Sequel::Model) doesn't work, so I am doing it this way...
|
247
|
+
table_is_sequel_model = false
|
248
|
+
table_super_class = table.superclass if table
|
249
|
+
while !table_is_sequel_model && table_super_class
|
250
|
+
table_is_sequel_model = (table_super_class == Sequel::Model)
|
251
|
+
table_super_class = table_super_class.superclass
|
252
|
+
end
|
253
|
+
|
254
|
+
if table && table_is_sequel_model
|
255
|
+
table_objects << table
|
256
|
+
else
|
257
|
+
SortedSeeder::Seeder.unclassed_tables << table_name
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# Sequel doesn't natively support polymorphic tables, so we don't support them here.
|
262
|
+
table_objects.each do |table|
|
263
|
+
unless SortedSeeder::Seeder.create_order.include?(table)
|
264
|
+
prev_table = sequel_pre_table(table, polymorphic_tables, [])
|
265
|
+
|
266
|
+
while (prev_table)
|
267
|
+
SortedSeeder::Seeder.create_order << prev_table
|
268
|
+
prev_table = sequel_pre_table(table, polymorphic_tables, [])
|
269
|
+
end
|
270
|
+
|
271
|
+
SortedSeeder::Seeder.create_order << table
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def active_record_pre_table(table, polymorphic_tables, processing_tables)
|
278
|
+
processing_tables << table
|
279
|
+
prev_table = nil
|
280
|
+
|
281
|
+
relations = table.reflect_on_all_associations(:belongs_to)
|
282
|
+
relations.each do |belongs_to|
|
283
|
+
if belongs_to.options && belongs_to.options[:polymorphic]
|
284
|
+
if polymorphic_tables[table.name]
|
285
|
+
polymorphic_tables[table.name].each do |polymorphic_prev_table|
|
286
|
+
prev_table = polymorphic_prev_table unless SortedSeeder::Seeder.create_order.include?(polymorphic_prev_table)
|
287
|
+
break if prev_table
|
288
|
+
end
|
289
|
+
end
|
290
|
+
else
|
291
|
+
belongs_to_table_name = (belongs_to.options[:class_name] || belongs_to.name.to_s.classify).to_s
|
292
|
+
prev_table = belongs_to_table_name.constantize
|
293
|
+
|
294
|
+
if prev_table &&
|
295
|
+
(SortedSeeder::Seeder.create_order.include?(prev_table) ||
|
296
|
+
table == prev_table ||
|
297
|
+
processing_tables.include?(prev_table))
|
298
|
+
prev_table = nil
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
prev_prev_table = nil
|
303
|
+
prev_prev_table = active_record_pre_table(prev_table, polymorphic_tables, processing_tables) if prev_table
|
304
|
+
prev_table = prev_prev_table || prev_table
|
305
|
+
|
306
|
+
break if prev_table
|
307
|
+
end
|
308
|
+
|
309
|
+
prev_table
|
310
|
+
end
|
311
|
+
|
312
|
+
# associated_class is late-bound, and Sequel doesn't validate it until it is called.
|
313
|
+
# This causes it to be able to fail unexpectedly, This is just a little safer...
|
314
|
+
def sequel_associated_class(relation)
|
315
|
+
begin
|
316
|
+
relation.associated_class
|
317
|
+
rescue NameError => error
|
318
|
+
if Object.const_defined?(relation[:class_name].to_s.classify)
|
319
|
+
relation[:class_name].to_s.classify.constantize
|
320
|
+
else
|
321
|
+
nil
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def sequel_pre_table(table, polymorphic_tables, processing_tables)
|
327
|
+
processing_tables << table
|
328
|
+
prev_table = nil
|
329
|
+
|
330
|
+
relations = table.all_association_reflections
|
331
|
+
relations.each do |belongs_to|
|
332
|
+
next unless [:one_through_one, :one_to_one, :many_to_one].include?(belongs_to[:type])
|
333
|
+
|
334
|
+
if [:one_through_one, :one_to_one].include?(belongs_to[:type])
|
335
|
+
related_table = sequel_associated_class(belongs_to)
|
336
|
+
if related_table
|
337
|
+
related_table.all_association_reflections.each do |reverse_reflection|
|
338
|
+
if sequel_associated_class(reverse_reflection) == table
|
339
|
+
if [:one_to_many].include? reverse_reflection[:type]
|
340
|
+
prev_table = related_table
|
341
|
+
break
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
else
|
347
|
+
prev_table = sequel_associated_class(belongs_to)
|
348
|
+
end
|
349
|
+
|
350
|
+
if prev_table &&
|
351
|
+
(SortedSeeder::Seeder.create_order.include?(prev_table) ||
|
352
|
+
table == prev_table ||
|
353
|
+
processing_tables.include?(prev_table))
|
354
|
+
prev_table = nil
|
355
|
+
end
|
356
|
+
|
357
|
+
prev_prev_table = nil
|
358
|
+
prev_prev_table = sequel_pre_table(prev_table, polymorphic_tables, processing_tables) if prev_table
|
359
|
+
prev_table = prev_prev_table || prev_table
|
360
|
+
|
361
|
+
break if prev_table
|
362
|
+
end
|
363
|
+
|
364
|
+
prev_table
|
365
|
+
end
|
366
|
+
|
367
|
+
def seed_class(table_name, seek_table_name = false)
|
368
|
+
seed_class_name = "#{table_name.to_s.classify}Seeder"
|
369
|
+
seed_class_base_name = seed_class_name.demodulize
|
370
|
+
base_module = seed_class_name.split("::")[0..-2].join("::")
|
371
|
+
base_module_classes = [Object]
|
372
|
+
|
373
|
+
unless base_module.blank?
|
374
|
+
base_module_classes = base_module_classes.unshift base_module.constantize
|
375
|
+
end
|
376
|
+
|
377
|
+
return_class = nil
|
378
|
+
2.times do
|
379
|
+
base_module_classes.each do |base_class|
|
380
|
+
if (base_class.const_defined?(seed_class_base_name, false))
|
381
|
+
if base_class == Object
|
382
|
+
return_class = seed_class_base_name.constantize
|
383
|
+
else
|
384
|
+
return_class = "#{base_class.name}::#{seed_class_base_name}".constantize
|
385
|
+
end
|
386
|
+
|
387
|
+
break
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
break if return_class
|
392
|
+
|
393
|
+
seeder_file = "db/seeders/"
|
394
|
+
seeder_file += base_module.split("::").map { |module_name| module_name.underscore }.join("/")
|
395
|
+
seeder_file += "/" unless seeder_file[-1] == "/"
|
396
|
+
seeder_file += seed_class_base_name.underscore
|
397
|
+
seeder_file += ".rb"
|
398
|
+
seeder_file = File.join(Rails.root, seeder_file)
|
399
|
+
|
400
|
+
break unless File.exists?(seeder_file)
|
401
|
+
|
402
|
+
require seeder_file
|
403
|
+
end
|
404
|
+
|
405
|
+
unless return_class.respond_to?(:seed)
|
406
|
+
unless seek_table_name && return_class.respond_to?(:table)
|
407
|
+
return_class = nil
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
return_class
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
def initialize(table, seeder_class)
|
416
|
+
@table = table
|
417
|
+
@seeder_class = seeder_class
|
418
|
+
end
|
419
|
+
|
420
|
+
def seed
|
421
|
+
seeder_class.seed if seeder_class
|
422
|
+
end
|
423
|
+
|
424
|
+
def <=>(other_object)
|
425
|
+
if (other_object.is_a?(SortedSeeder::Seeder))
|
426
|
+
return 0 if other_object.table == self.table
|
427
|
+
|
428
|
+
SortedSeeder::Seeder.create_order.each do |create_table|
|
429
|
+
if create_table == self.table
|
430
|
+
return -1
|
431
|
+
elsif create_table == other_object.table
|
432
|
+
return 1
|
433
|
+
end
|
434
|
+
end
|
435
|
+
else
|
436
|
+
if other_object.respond_to?(:<=>)
|
437
|
+
comparison = (other_object <=> self)
|
438
|
+
if comparison
|
439
|
+
return -1 * comparison
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
return -1
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sorted_seeder/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sorted_seeder"
|
8
|
+
spec.version = SortedSeeder::VERSION
|
9
|
+
spec.authors = ["RealNobody"]
|
10
|
+
spec.email = ["Erik.Littell@Deem.com"]
|
11
|
+
spec.description = %q{A system for organizing and simplifying seeding your environment.}
|
12
|
+
spec.summary = %q{A system for organizing and simplifying seeding your environment.}
|
13
|
+
spec.homepage = "https://github.com/RealNobody/sorted_seeder"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sorted_seeder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.10
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- RealNobody
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-07 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: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: A system for organizing and simplifying seeding your environment.
|
42
|
+
email:
|
43
|
+
- Erik.Littell@Deem.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- lib/sorted_seeder.rb
|
54
|
+
- lib/sorted_seeder/seeder.rb
|
55
|
+
- lib/sorted_seeder/version.rb
|
56
|
+
- sorted_seeder.gemspec
|
57
|
+
homepage: https://github.com/RealNobody/sorted_seeder
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.4.5
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: A system for organizing and simplifying seeding your environment.
|
81
|
+
test_files: []
|
82
|
+
has_rdoc:
|