application_seeds 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,4 +1,11 @@
1
- v0.3.0, 2013-01-09
1
+ v0.4.0, 2014-02-09
2
+ ------------------
3
+
4
+ * Added support for nested/inheritable datasets
5
+ * Warn user if `ApplicationSeeds.config=` is called after `ApplicationSeeds.dataset=`
6
+
7
+
8
+ v0.3.0, 2014-01-09
2
9
  ------------------
3
10
 
4
11
  * Added support for Capistrano 3.x
data/README.md CHANGED
@@ -34,12 +34,12 @@ the YAML files into a gem. The gem should have the following directory
34
34
  structure:
35
35
 
36
36
  ```
37
- lib
38
- +-- seeds
39
- |-- seed_data_set_1
37
+ lib/
38
+ +-- seeds/
39
+ |-- seed_data_set_1/
40
40
  | |-- some_data.yml
41
41
  | +-- some_other_data.yml
42
- +-- seed_data_set_2
42
+ +-- seed_data_set_2/
43
43
  |-- some_data.yml
44
44
  +-- some_other_data.yml
45
45
  ```
@@ -63,11 +63,11 @@ be identical to what is described above in the "Via a gem" section, but the `lib
63
63
  diretory is not required.
64
64
 
65
65
  ```
66
- seeds
67
- |-- seed_data_set_1
66
+ seeds/
67
+ |-- seed_data_set_1/
68
68
  | |-- some_data.yml
69
69
  | +-- some_other_data.yml
70
- +-- seed_data_set_2
70
+ +-- seed_data_set_2/
71
71
  |-- some_data.yml
72
72
  +-- some_other_data.yml
73
73
  ```
@@ -160,6 +160,65 @@ Then, you can seed a remote database by running the following:
160
160
  bundle exec cap <environment> deploy:application_seeds -s dataset=your_data_set
161
161
 
162
162
 
163
+ ## The Datasets
164
+
165
+ The `application_seeds` library supports multiple datasets within the
166
+ same source (place on the file system, gem, etc). The user specifies
167
+ which dataset to load when beginning to work with the seed data.
168
+
169
+ ApplicationSeeds.dataset = "my_data_set"
170
+
171
+ ### Nested Datasets
172
+
173
+ Datasets can be structured so that child directories can inherit the
174
+ seed data files that are stored in the parent directories. For example,
175
+ let's look at the following directory structure:
176
+
177
+ ```
178
+ seeds/
179
+ +-- parent_data_set/
180
+ |-- companies.yml
181
+ +-- child_data_set/
182
+ |-- departments.yml
183
+ +-- grandchild_data_set/
184
+ +-- people.yml
185
+ ```
186
+
187
+ In this example, if the `grandchild_data_set` is loaded, you will have
188
+ access to the seed data files in `grandchild_data_set`,
189
+ `child_data_set`, and `parent_data_set`. Because of this, data from
190
+ `people.yml`, `departments.yml`, and `companies.yml` can be loaded.
191
+
192
+ If `child_data_set` is loaded, you will have access to the seed data
193
+ files in `child_data_set` and `parent_data_set`, but **not**
194
+ `grandchild_data_set`. This includes the `departments.yml` and
195
+ `companies.yml` data files.
196
+
197
+ ### Merging Data Files
198
+
199
+ It is possible to have files for the same data type scattered throughout
200
+ the dataset hierarchy.
201
+
202
+ ```
203
+ seeds/
204
+ +-- parent_data_set/
205
+ |-- companies.yml
206
+ |-- people.yml
207
+ +-- child_data_set/
208
+ |-- departments.yml
209
+ |-- people.yml
210
+ +-- grandchild_data_set/
211
+ +-- people.yml
212
+ ```
213
+
214
+ In this example, when data is loaded from the `people` dataset via call
215
+ to `ApplicationSeeds.people`, then the result will contain the data from
216
+ all three files.
217
+
218
+ If the files contain conflicting labels, then precedence is given to
219
+ data at the lowest level (`grandchild_data_set` in this example).
220
+
221
+
163
222
  ## The Seed Files
164
223
 
165
224
  The seed files contain the data that the Rake task works with to
@@ -86,6 +86,7 @@ module ApplicationSeeds
86
86
  # Specify any configuration, such as the type of ids to generate (:integer or :uuid).
87
87
  #
88
88
  def config=(config)
89
+ warn "WARNING! Calling ApplicationSeeds.config= after dataset has been set (ApplicationSeeds.dataset=) may not produce expected results." unless @dataset.nil?
89
90
  @_config = config
90
91
  end
91
92
 
@@ -140,8 +141,8 @@ module ApplicationSeeds
140
141
  # the dataset could not be found.
141
142
  #
142
143
  def dataset=(dataset)
143
- if dataset.nil? || dataset.strip.empty? || !Dir.exist?(File.join(seed_data_path, dataset))
144
- datasets = Dir[File.join(seed_data_path, "*")].map { |x| File.basename(x) }.join(', ')
144
+ if dataset.nil? || dataset.strip.empty? || dataset_path(dataset).nil?
145
+ datasets = Dir[File.join(seed_data_path, "**", "*")].select { |x| File.directory?(x) }.map { |x| File.basename(x) }.join(', ')
145
146
 
146
147
  error_message = "\nERROR: A valid dataset is required!\n"
147
148
  error_message << "Usage: bundle exec rake application_seeds:load[your_data_set]\n\n"
@@ -150,6 +151,7 @@ module ApplicationSeeds
150
151
  end
151
152
 
152
153
  store_dataset(dataset)
154
+ find_seed_data_files(dataset)
153
155
  process_labels(dataset)
154
156
  load_seed_data(dataset)
155
157
  @dataset = dataset
@@ -241,14 +243,19 @@ module ApplicationSeeds
241
243
 
242
244
  def load_seed_data(dataset)
243
245
  @seed_data = {}
244
- seed_files(dataset).each do |seed_file|
246
+ @seed_data_files.each do |seed_file|
245
247
  basename = File.basename(seed_file, ".yml")
246
248
  data = YAML.load(ERB.new(File.read(seed_file)).result)
247
249
  if data
248
250
  data.each do |label, attributes|
249
251
  data[label] = replace_labels_with_ids(attributes)
250
252
  end
251
- @seed_data[basename] = data
253
+
254
+ if @seed_data[basename].nil?
255
+ @seed_data[basename] = data
256
+ else
257
+ @seed_data[basename] = data.merge(@seed_data[basename])
258
+ end
252
259
  end
253
260
  end
254
261
  end
@@ -313,6 +320,10 @@ module ApplicationSeeds
313
320
  end
314
321
  end
315
322
 
323
+ def dataset_path(dataset)
324
+ Dir[File.join(seed_data_path, "**", "*")].select { |x| File.directory?(x) && File.basename(x) == dataset }.first
325
+ end
326
+
316
327
  def fetch(type, &block)
317
328
  result = {}
318
329
  @seed_data[type].each do |label, attrs|
@@ -350,11 +361,20 @@ module ApplicationSeeds
350
361
  Database.connection.exec("INSERT INTO application_seeds (dataset) VALUES ('#{dataset}');")
351
362
  end
352
363
 
364
+ def find_seed_data_files(dataset)
365
+ @seed_data_files = []
366
+ path = dataset_path(dataset)
367
+ while (seed_data_path != path) do
368
+ @seed_data_files.concat(Dir[File.join(path, "*.yml")])
369
+ path.sub!(/\/[^\/]+$/, "")
370
+ end
371
+ end
372
+
353
373
  def process_labels(dataset)
354
374
  return @seed_labels unless @seed_labels.nil?
355
375
 
356
376
  @seed_labels = {}
357
- seed_files(dataset).each do |seed_file|
377
+ @seed_data_files.each do |seed_file|
358
378
  seed_type = File.basename(seed_file, ".yml")
359
379
  @seed_labels[seed_type] = {}
360
380
 
@@ -379,10 +399,6 @@ module ApplicationSeeds
379
399
  { :integer => id, :uuid => "00000000-0000-0000-0000-%012d" % id }
380
400
  end
381
401
 
382
- def seed_files(dataset)
383
- Dir[File.join(seed_data_path, dataset, "*.yml")]
384
- end
385
-
386
402
  def id_type(type)
387
403
  self.config["#{type}_id_type".to_sym] || self.config[:id_type]
388
404
  end
@@ -1,3 +1,3 @@
1
1
  module ApplicationSeeds
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -9,6 +9,24 @@ class Person
9
9
  end
10
10
  end
11
11
 
12
+ class Company
13
+ attr_accessor :attributes, :id, :saved
14
+ attr_accessor :name
15
+
16
+ def save!(options={})
17
+ @saved = true
18
+ end
19
+ end
20
+
21
+ class Department
22
+ attr_accessor :attributes, :id, :saved
23
+ attr_accessor :name
24
+
25
+ def save!(options={})
26
+ @saved = true
27
+ end
28
+ end
29
+
12
30
  describe "ApplicationSeeds" do
13
31
  before do
14
32
  ApplicationSeeds.data_directory = File.join(File.dirname(__FILE__), "seed_data")
@@ -219,8 +237,44 @@ describe "ApplicationSeeds" do
219
237
  end
220
238
  end
221
239
 
240
+ describe "with a nested dataset" do
241
+ before do
242
+ ApplicationSeeds.stub(:store_dataset)
243
+ ApplicationSeeds.dataset = "level_3"
244
+ end
245
+
246
+ describe "finding seed data" do
247
+ it "can find data at the root level" do
248
+ company = ApplicationSeeds.companies(:mega_corp)
249
+ expect(company['name']).to eql("Megacorp")
250
+ end
251
+ it "can find data at the middle level" do
252
+ department = ApplicationSeeds.departments(:engineering)
253
+ expect(department['name']).to eql("Engineering")
254
+ end
255
+ it "can find data at the lowest level" do
256
+ person = ApplicationSeeds.people(:joe_smith)
257
+ expect(person['first_name']).to eql("Joe")
258
+ end
259
+ end
260
+
261
+ describe "merging seed data" do
262
+ it "can merge data from different levels" do
263
+ person = ApplicationSeeds.people(:joe_smith)
264
+ expect(person['first_name']).to eql("Joe")
265
+ person = ApplicationSeeds.people(:sam_jones)
266
+ expect(person['first_name']).to eql("Sam")
267
+ end
268
+ it "gives the data in lower levels precendence" do
269
+ person = ApplicationSeeds.people(:ken_adams)
270
+ expect(person['first_name']).to eql("Ken")
271
+ end
272
+ end
273
+ end
274
+
222
275
  describe "with UUIDs configured for all seed types" do
223
276
  before do
277
+ ApplicationSeeds.instance_variable_set("@dataset", nil)
224
278
  ApplicationSeeds.stub(:store_dataset)
225
279
  ApplicationSeeds.config = { :id_type => :uuid }
226
280
  ApplicationSeeds.dataset = "test_data_set"
@@ -239,6 +293,7 @@ describe "ApplicationSeeds" do
239
293
 
240
294
  describe "with data type specific key types configured" do
241
295
  before do
296
+ ApplicationSeeds.instance_variable_set("@dataset", nil)
242
297
  ApplicationSeeds.stub(:store_dataset)
243
298
  ApplicationSeeds.config = { :id_type => :uuid, :companies_id_type => :integer }
244
299
  ApplicationSeeds.dataset = "test_data_set"
@@ -0,0 +1,9 @@
1
+ mega_corp:
2
+ name: Megacorp
3
+
4
+ ma_and_pa:
5
+ name: Ma and Pa
6
+
7
+ global_corp:
8
+ id: 123
9
+ name: Global Corp
@@ -0,0 +1,7 @@
1
+ engineering:
2
+ name: Engineering
3
+ people_ids: [joe_smith, jane_doe, john_walsh]
4
+
5
+ sales:
6
+ name: Sales
7
+ employee_ids: "[sam_jones, ken_adams] (people)"
@@ -0,0 +1,26 @@
1
+ joe_smith:
2
+ first_name: Joe
3
+ last_name: Smith
4
+ company_id: mega_corp
5
+ start_date: <%= 2.months.ago.to_date %>
6
+ bogus_attribute: foo
7
+
8
+ jane_doe:
9
+ first_name: Jane
10
+ last_name: Doe
11
+ company_id: mega_corp
12
+ start_date: <%= 10.months.ago.to_date %>
13
+ bogus_attribute: foo
14
+
15
+ john_walsh:
16
+ first_name: John
17
+ last_name: Walsh
18
+ company_id: ma_and_pa
19
+ start_date: <%= 10.years.ago.to_date %>
20
+ bogus_attribute: foo
21
+
22
+ ken_adams:
23
+ first_name: Ken
24
+ last_name: Adams
25
+ employer_id: ma_and_pa (companies)
26
+ start_date: <%= 10.years.ago.to_date %>
@@ -0,0 +1,12 @@
1
+ sam_jones:
2
+ id: 456
3
+ first_name: Sam
4
+ last_name: Jones
5
+ company_id: 123
6
+ start_date: <%= 10.years.ago.to_date %>
7
+
8
+ ken_adams:
9
+ first_name: Kenneth
10
+ last_name: Adams
11
+ employer_id: ma_and_pa (companies)
12
+ start_date: <%= 10.years.ago.to_date %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: application_seeds
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-09 00:00:00.000000000 Z
12
+ date: 2014-02-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -101,6 +101,10 @@ files:
101
101
  - spec/seed_data/test_data_set/companies.yml
102
102
  - spec/seed_data/test_data_set/departments.yml
103
103
  - spec/seed_data/test_data_set/people.yml
104
+ - spec/seed_data/test_inheritable_data_set/companies.yml
105
+ - spec/seed_data/test_inheritable_data_set/level_2/departments.yml
106
+ - spec/seed_data/test_inheritable_data_set/level_2/level_3/people.yml
107
+ - spec/seed_data/test_inheritable_data_set/level_2/people.yml
104
108
  homepage: https://github.com/centro/application_seeds
105
109
  licenses:
106
110
  - MIT
@@ -116,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
120
  version: '0'
117
121
  segments:
118
122
  - 0
119
- hash: 1780168384698824643
123
+ hash: 1911143344573555233
120
124
  required_rubygems_version: !ruby/object:Gem::Requirement
121
125
  none: false
122
126
  requirements:
@@ -125,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
129
  version: '0'
126
130
  segments:
127
131
  - 0
128
- hash: 1780168384698824643
132
+ hash: 1911143344573555233
129
133
  requirements: []
130
134
  rubyforge_project:
131
135
  rubygems_version: 1.8.23
@@ -139,3 +143,7 @@ test_files:
139
143
  - spec/seed_data/test_data_set/companies.yml
140
144
  - spec/seed_data/test_data_set/departments.yml
141
145
  - spec/seed_data/test_data_set/people.yml
146
+ - spec/seed_data/test_inheritable_data_set/companies.yml
147
+ - spec/seed_data/test_inheritable_data_set/level_2/departments.yml
148
+ - spec/seed_data/test_inheritable_data_set/level_2/level_3/people.yml
149
+ - spec/seed_data/test_inheritable_data_set/level_2/people.yml