dibber 0.2.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.
- data/README.rdoc +44 -12
- data/Rakefile +1 -1
- data/lib/dibber/process_log.rb +4 -0
- data/lib/dibber/seeder.rb +25 -6
- data/lib/dibber/version.rb +5 -1
- data/test/dibber/process_log_test.rb +6 -0
- data/test/dibber/seeder_test.rb +60 -1
- data/test/dibber/thing.rb +4 -54
- data/test/examples/models/admin_user.rb +5 -0
- data/test/examples/models/borough.rb +5 -0
- data/test/examples/models/category.rb +6 -0
- data/test/examples/models/disclaimer.rb +6 -0
- data/test/examples/models/fee.rb +5 -0
- data/{lib → test}/examples/process_logs.rb +1 -1
- data/{lib → test}/examples/seeds.rb +26 -11
- data/{lib → test}/examples/seeds/boroughs.yml +0 -0
- data/{lib → test}/examples/seeds/categories.yml +0 -0
- data/{lib → test}/examples/seeds/disclaimer/documents.yml +0 -0
- data/{lib → test}/examples/seeds/fees.yml +0 -0
- data/test/not_quite_active_record.rb +79 -0
- metadata +26 -8
data/README.rdoc
CHANGED
@@ -19,11 +19,11 @@ Add this to your Gemfile:
|
|
19
19
|
|
20
20
|
gem 'dibber'
|
21
21
|
|
22
|
-
=== Examples
|
22
|
+
=== Rails Examples
|
23
23
|
|
24
24
|
You have a rails app with a Thing model, and you want to seed it with some
|
25
25
|
things. Thing instances have the attributes 'name', 'colour', 'size'.
|
26
|
-
You have a YAML file '
|
26
|
+
You have a YAML file 'db/seeds/things.yml' that looks like this:
|
27
27
|
|
28
28
|
foo:
|
29
29
|
colour: red
|
@@ -36,8 +36,7 @@ You have a YAML file '/db/seeds/things.yml' that looks like this:
|
|
36
36
|
Add this to your 'db/seeds.rb'
|
37
37
|
|
38
38
|
Seeder = Dibber::Seeder
|
39
|
-
Seeder.
|
40
|
-
Seeder.new(Thing, 'things.yml').build
|
39
|
+
Seeder.seed :thing
|
41
40
|
puts Seeder.report
|
42
41
|
|
43
42
|
Then run 'rake db:seed'
|
@@ -48,23 +47,56 @@ You'll then be able to do this:
|
|
48
47
|
|
49
48
|
thing = Thing.find_by_name(:foo)
|
50
49
|
thing.colour ---> 'red'
|
50
|
+
|
51
|
+
=== Outside Rails
|
52
|
+
|
53
|
+
Dibber can be used outside of Rails, but in this case you will need to
|
54
|
+
specify the location of the seed files.
|
55
|
+
|
56
|
+
Seeder.seeds_path = "some/path/to/seeds"
|
57
|
+
|
58
|
+
You can also use this technique in Rails if you want to put your seed files
|
59
|
+
in an alternative folder to 'db/seeds'
|
51
60
|
|
52
61
|
== Report
|
53
62
|
|
54
|
-
|
55
|
-
|
63
|
+
Seeder.report outputs a report detailing start and end time, and a log of how
|
64
|
+
the number of things has changed
|
56
65
|
|
57
66
|
== Overwriting existing entries
|
58
67
|
|
59
|
-
|
60
|
-
directed to do so.
|
68
|
+
Seeder#build will not overwrite existing data unless directed to do so.
|
61
69
|
|
62
70
|
thing.update_attribute(:colour, 'black')
|
63
|
-
Seeder.
|
71
|
+
Seeder.seed :thing
|
64
72
|
thing.reload.colour ----> 'black'
|
65
73
|
|
66
|
-
Seeder.
|
74
|
+
Seeder.seed(:thing, :overwrite => true).build
|
67
75
|
thing.reload.colour ----> 'red'
|
68
76
|
|
69
|
-
|
70
|
-
|
77
|
+
|
78
|
+
== Using alternative class and field name mappings
|
79
|
+
|
80
|
+
Seeder.seed calls Seeder#build to build the objects defined in the seed files.
|
81
|
+
You can call the build method directly if your seed file names do not match
|
82
|
+
the class name:
|
83
|
+
|
84
|
+
Seeder.new(Thing, 'other_things.yml').build
|
85
|
+
|
86
|
+
== More examples
|
87
|
+
|
88
|
+
Take a look at test/examples/seeds.rb for some more usage examples.
|
89
|
+
|
90
|
+
If you clone this app, you can run this example at the project root:
|
91
|
+
|
92
|
+
ruby test/examples/seeds.rb
|
93
|
+
|
94
|
+
There is also an example of process log usage:
|
95
|
+
|
96
|
+
ruby test/examples/process_logs.rb
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
|
data/Rakefile
CHANGED
data/lib/dibber/process_log.rb
CHANGED
data/lib/dibber/seeder.rb
CHANGED
@@ -5,6 +5,13 @@ module Dibber
|
|
5
5
|
class Seeder
|
6
6
|
attr_accessor :klass, :file, :attribute_method, :name_method, :overwrite
|
7
7
|
|
8
|
+
def self.seed(name, args = {})
|
9
|
+
class_name = name.to_s.strip.classify
|
10
|
+
new_klass = (/\A\w+(::\w+)+\Z/ =~ class_name) ? eval(class_name) : Kernel.const_get(class_name)
|
11
|
+
new_file = "#{name.to_s.pluralize}.yml"
|
12
|
+
new(new_klass, new_file, args).build
|
13
|
+
end
|
14
|
+
|
8
15
|
def self.process_log
|
9
16
|
@process_log || start_process_log
|
10
17
|
end
|
@@ -20,7 +27,10 @@ module Dibber
|
|
20
27
|
end
|
21
28
|
|
22
29
|
def self.monitor(klass)
|
23
|
-
|
30
|
+
log_name = klass.to_s.tableize.to_sym
|
31
|
+
unless process_log.exists?(log_name)
|
32
|
+
process_log.start(log_name, "#{klass}.count")
|
33
|
+
end
|
24
34
|
end
|
25
35
|
|
26
36
|
def self.objects_from(file)
|
@@ -28,15 +38,13 @@ module Dibber
|
|
28
38
|
end
|
29
39
|
|
30
40
|
def self.seeds_path
|
31
|
-
@seeds_path || raise_no_seeds_path_error
|
41
|
+
@seeds_path || try_to_guess_seeds_path || raise_no_seeds_path_error
|
32
42
|
end
|
33
43
|
|
34
44
|
def self.seeds_path=(path)
|
35
|
-
|
36
|
-
@seeds_path = path
|
45
|
+
@seeds_path = add_trailing_slash_to(path)
|
37
46
|
end
|
38
47
|
|
39
|
-
|
40
48
|
def initialize(klass, file, args = {})
|
41
49
|
@klass = klass
|
42
50
|
@file = file
|
@@ -47,8 +55,8 @@ module Dibber
|
|
47
55
|
end
|
48
56
|
|
49
57
|
def build
|
50
|
-
start_log
|
51
58
|
check_objects_exist
|
59
|
+
start_log
|
52
60
|
objects.each do |name, attributes|
|
53
61
|
object = klass.send(retrieval_method, name)
|
54
62
|
if overwrite or object.new_record?
|
@@ -79,5 +87,16 @@ module Dibber
|
|
79
87
|
"find_or_initialize_by_#{name_method}"
|
80
88
|
end
|
81
89
|
|
90
|
+
def self.try_to_guess_seeds_path
|
91
|
+
path = File.expand_path('db/seeds', Rails.root) if defined? Rails
|
92
|
+
add_trailing_slash_to(path)
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def self.add_trailing_slash_to(path = nil)
|
97
|
+
path = path + '/' if path and path !~ /\/$/
|
98
|
+
path
|
99
|
+
end
|
100
|
+
|
82
101
|
end
|
83
102
|
end
|
data/lib/dibber/version.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
module Dibber
|
2
|
-
VERSION = "0.
|
2
|
+
VERSION = "0.3.0"
|
3
3
|
end
|
4
4
|
|
5
5
|
# History
|
6
6
|
# =======
|
7
|
+
# 0.3.0 Adds seed method
|
8
|
+
# Allows seeding to be carried out via Dibber::Seeder.seed(:thing).
|
9
|
+
# Also tidies up examples
|
10
|
+
#
|
7
11
|
# 0.2.2 Minor bug fix. There was an error in the example. Also a small bit
|
8
12
|
# of house keeping (adding license to gemspec, and removing Gemfile.lock
|
9
13
|
# from repository.
|
@@ -44,5 +44,11 @@ module Dibber
|
|
44
44
|
expected = ['No finish was 1, now 1.']
|
45
45
|
assert_equal(expected, @process_log.report)
|
46
46
|
end
|
47
|
+
|
48
|
+
def test_exists_method
|
49
|
+
assert !@process_log.exists?(:one), "There should not be a log for :one yet"
|
50
|
+
test_one
|
51
|
+
assert @process_log.exists?(:one), "There should be log for :one"
|
52
|
+
end
|
47
53
|
end
|
48
54
|
end
|
data/test/dibber/seeder_test.rb
CHANGED
@@ -9,7 +9,7 @@ module Dibber
|
|
9
9
|
class SeederTest < Test::Unit::TestCase
|
10
10
|
|
11
11
|
def setup
|
12
|
-
Seeder.seeds_path = File.join(File.dirname(__FILE__),'seeds')
|
12
|
+
Seeder.seeds_path = File.join(File.dirname(__FILE__), 'seeds')
|
13
13
|
end
|
14
14
|
|
15
15
|
def teardown
|
@@ -121,6 +121,65 @@ module Dibber
|
|
121
121
|
assert_equal([foo, bar], Thing.saved)
|
122
122
|
assert_equal({'title' => 'one'}, foo.attributes)
|
123
123
|
end
|
124
|
+
|
125
|
+
def test_seed
|
126
|
+
assert_equal(0, Thing.count)
|
127
|
+
Seeder.seed(:things)
|
128
|
+
assert_equal(2, Thing.count)
|
129
|
+
foo = Thing.find_or_initialize_by_name(:foo)
|
130
|
+
bar = Thing.find_or_initialize_by_name(:bar)
|
131
|
+
assert_equal([foo, bar], Thing.saved)
|
132
|
+
assert_equal({'title' => 'one'}, foo.attributes)
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_seed_with_alternative_name_method
|
136
|
+
Seeder.seed(:things, :name_method => 'other_method')
|
137
|
+
assert_equal(2, Thing.count)
|
138
|
+
foo = Thing.find_or_initialize_by_other_method(:foo)
|
139
|
+
bar = Thing.find_or_initialize_by_other_method(:bar)
|
140
|
+
assert_equal([foo, bar], Thing.saved)
|
141
|
+
assert_equal({'title' => 'one'}, foo.attributes)
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_seed_with_non_existent_class
|
145
|
+
assert_raise NameError do
|
146
|
+
Seeder.seed(:non_existent_class)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_seed_with_non_existent_seed_file
|
151
|
+
no_file_found_error = Errno::ENOENT
|
152
|
+
assert_raise no_file_found_error do
|
153
|
+
Seeder.seed(:array)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_seeds_path_with_none_set
|
158
|
+
Seeder.seeds_path = nil
|
159
|
+
assert_raise RuntimeError do
|
160
|
+
Seeder.seeds_path
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_process_log_not_reset_by_second_seed_process_on_same_class
|
165
|
+
Seeder.seed(:things)
|
166
|
+
original_start = Seeder.process_log.raw[:things][:start]
|
167
|
+
Seeder.seed(:things)
|
168
|
+
assert_equal original_start, Seeder.process_log.raw[:things][:start]
|
169
|
+
end
|
170
|
+
|
171
|
+
module DummyRails
|
172
|
+
def self.root
|
173
|
+
'/some/path'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_seeds_path_if_Rails_exists
|
178
|
+
Dibber.const_set :Rails, DummyRails
|
179
|
+
Seeder.seeds_path = nil
|
180
|
+
assert_equal '/some/path/db/seeds/', Seeder.seeds_path
|
181
|
+
Dibber.send(:remove_const, :Rails)
|
182
|
+
end
|
124
183
|
|
125
184
|
|
126
185
|
private
|
data/test/dibber/thing.rb
CHANGED
@@ -1,55 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
def initialize(name = nil)
|
6
|
-
@name = name.to_s if name
|
7
|
-
self.class.members << self
|
8
|
-
end
|
9
|
-
|
10
|
-
def save
|
11
|
-
self.class.saved << self if new_record?
|
12
|
-
true
|
13
|
-
end
|
14
|
-
|
15
|
-
def new_record?
|
16
|
-
!self.class.saved.include? self
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.find_or_initialize_by_name(name)
|
20
|
-
existing = members.select{|m| m.name == name.to_s}
|
21
|
-
if existing.empty?
|
22
|
-
new(name)
|
23
|
-
else
|
24
|
-
existing.first
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.find_or_initialize_by_other_method(data)
|
29
|
-
existing = members.select{|m| m.other_method == data.to_s}
|
30
|
-
if existing.empty?
|
31
|
-
thing = new
|
32
|
-
thing.other_method = data.to_s
|
33
|
-
thing
|
34
|
-
else
|
35
|
-
existing.first
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.members
|
40
|
-
@members ||= []
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.count
|
44
|
-
members.length
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.saved
|
48
|
-
@saved ||= []
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.clear_all
|
52
|
-
@members = []
|
53
|
-
@saved = []
|
54
|
-
end
|
1
|
+
require_relative '../not_quite_active_record'
|
2
|
+
|
3
|
+
class Thing < NotQuiteActiveRecord
|
4
|
+
attr_accessor :other_method
|
55
5
|
end
|
@@ -1,7 +1,13 @@
|
|
1
|
+
require_relative '../../lib/dibber'
|
2
|
+
|
3
|
+
models = %w{borough admin_user fee disclaimer category}
|
4
|
+
models.each {|model| require_relative "models/#{model}"}
|
5
|
+
|
6
|
+
|
1
7
|
Seeder = Dibber::Seeder
|
2
8
|
|
3
9
|
# Set up the path to seed YAML files
|
4
|
-
Seeder.seeds_path =
|
10
|
+
Seeder.seeds_path = File.expand_path('seeds', File.dirname(__FILE__))
|
5
11
|
|
6
12
|
# Example 1. Seeder is used to monitor the process
|
7
13
|
# and grab the attributes from the YAML file
|
@@ -30,22 +36,31 @@ Seeder.new(Fee, 'fees.yml').build
|
|
30
36
|
# Example 4. Seeder using an alternative name field
|
31
37
|
Seeder.new(Fee, 'fees.yml', :name_method => :title).build
|
32
38
|
|
33
|
-
# Example 5.
|
39
|
+
# Example 5. If the seed file's name is the lower case plural of the class name
|
40
|
+
# you can use the seed method:
|
41
|
+
Seeder.seed(:fee)
|
42
|
+
|
43
|
+
# Example 6. Seeder working with a name-spaced object
|
34
44
|
Seeder.new(Disclaimer::Document, 'disclaimer/documents.yml').build
|
35
45
|
|
36
|
-
# Example
|
37
|
-
|
46
|
+
# Example 7. You can also use the seed method with name-spaced objects.
|
47
|
+
# In this case the seed files need to be in a name-spaced path (see previous
|
48
|
+
# example)
|
49
|
+
Seeder.seed('disclaimer/document')
|
50
|
+
|
51
|
+
# Example 8. Seeder using values in the yaml file to set a single field
|
52
|
+
Seeder.seed(:category, 'description')
|
38
53
|
|
39
|
-
# Example
|
40
|
-
Seeder.
|
41
|
-
|
42
|
-
'categories.yml',
|
54
|
+
# Example 9. Seeder using alternative name and attributes fields
|
55
|
+
Seeder.seed(
|
56
|
+
:category,
|
43
57
|
:name_method => :title,
|
44
58
|
:attributes_method => :description
|
45
|
-
)
|
59
|
+
)
|
46
60
|
|
47
|
-
# You can also access Seeders attached process log, and set up a
|
48
|
-
|
61
|
+
# Example 10. You can also access Seeders attached process log, and set up a
|
62
|
+
# custom log
|
63
|
+
Seeder.process_log.start('Time to end of report', 'Time.now')
|
49
64
|
|
50
65
|
# Output a report showing how the numbers of each type of object
|
51
66
|
# have changed through the process. Also has a log of start and end time.
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Mock ActiveRecord::Base
|
2
|
+
class NotQuiteActiveRecord
|
3
|
+
attr_reader :name
|
4
|
+
attr_accessor :attributes
|
5
|
+
|
6
|
+
def initialize(name = nil)
|
7
|
+
@name = name.to_s if name
|
8
|
+
self.class.members << self
|
9
|
+
end
|
10
|
+
|
11
|
+
def save
|
12
|
+
self.class.saved << self if new_record?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def new_record?
|
17
|
+
!self.class.saved.include? self
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find_or_initialize_by_name(name)
|
21
|
+
existing = members.select{|m| m.name == name.to_s}
|
22
|
+
if existing.empty?
|
23
|
+
new(name)
|
24
|
+
else
|
25
|
+
existing.first
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.find_or_initialize_by_title(title)
|
30
|
+
existing = members.select{|m| m.title == title.to_s}
|
31
|
+
if existing.empty?
|
32
|
+
fee = new
|
33
|
+
fee.title = title
|
34
|
+
fee
|
35
|
+
else
|
36
|
+
existing.first
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.find_or_create_by_name(name)
|
41
|
+
find_or_initialize_by_name(name).save
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.find_or_initialize_by_other_method(data)
|
45
|
+
existing = members.select{|m| m.other_method == data.to_s}
|
46
|
+
if existing.empty?
|
47
|
+
thing = new
|
48
|
+
thing.other_method = data.to_s
|
49
|
+
thing
|
50
|
+
else
|
51
|
+
existing.first
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.exists?(hash)
|
56
|
+
!members.select{|m| m.send(hash.first[0]) == hash.first[1].to_s}.empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.create!(hash)
|
60
|
+
new(hash).save
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.members
|
64
|
+
@members ||= []
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.count
|
68
|
+
members.length
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.saved
|
72
|
+
@saved ||= []
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.clear_all
|
76
|
+
@members = []
|
77
|
+
@saved = []
|
78
|
+
end
|
79
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dibber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.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: 2013-08-
|
12
|
+
date: 2013-08-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: active_support
|
@@ -35,12 +35,6 @@ executables: []
|
|
35
35
|
extensions: []
|
36
36
|
extra_rdoc_files: []
|
37
37
|
files:
|
38
|
-
- lib/examples/process_logs.rb
|
39
|
-
- lib/examples/seeds/boroughs.yml
|
40
|
-
- lib/examples/seeds/disclaimer/documents.yml
|
41
|
-
- lib/examples/seeds/fees.yml
|
42
|
-
- lib/examples/seeds/categories.yml
|
43
|
-
- lib/examples/seeds.rb
|
44
38
|
- lib/dibber.rb
|
45
39
|
- lib/dibber/version.rb
|
46
40
|
- lib/dibber/process_log.rb
|
@@ -48,6 +42,18 @@ files:
|
|
48
42
|
- MIT-LICENSE
|
49
43
|
- Rakefile
|
50
44
|
- README.rdoc
|
45
|
+
- test/examples/process_logs.rb
|
46
|
+
- test/examples/models/admin_user.rb
|
47
|
+
- test/examples/models/disclaimer.rb
|
48
|
+
- test/examples/models/category.rb
|
49
|
+
- test/examples/models/borough.rb
|
50
|
+
- test/examples/models/fee.rb
|
51
|
+
- test/examples/seeds/boroughs.yml
|
52
|
+
- test/examples/seeds/disclaimer/documents.yml
|
53
|
+
- test/examples/seeds/fees.yml
|
54
|
+
- test/examples/seeds/categories.yml
|
55
|
+
- test/examples/seeds.rb
|
56
|
+
- test/not_quite_active_record.rb
|
51
57
|
- test/dibber/seeder_test.rb
|
52
58
|
- test/dibber/thing.rb
|
53
59
|
- test/dibber/process_log_test.rb
|
@@ -80,6 +86,18 @@ signing_key:
|
|
80
86
|
specification_version: 3
|
81
87
|
summary: Tool for seeding database from YAML.
|
82
88
|
test_files:
|
89
|
+
- test/examples/process_logs.rb
|
90
|
+
- test/examples/models/admin_user.rb
|
91
|
+
- test/examples/models/disclaimer.rb
|
92
|
+
- test/examples/models/category.rb
|
93
|
+
- test/examples/models/borough.rb
|
94
|
+
- test/examples/models/fee.rb
|
95
|
+
- test/examples/seeds/boroughs.yml
|
96
|
+
- test/examples/seeds/disclaimer/documents.yml
|
97
|
+
- test/examples/seeds/fees.yml
|
98
|
+
- test/examples/seeds/categories.yml
|
99
|
+
- test/examples/seeds.rb
|
100
|
+
- test/not_quite_active_record.rb
|
83
101
|
- test/dibber/seeder_test.rb
|
84
102
|
- test/dibber/thing.rb
|
85
103
|
- test/dibber/process_log_test.rb
|