dibber 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 '/db/seeds/things.yml' that looks like this:
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.seeds_path = "#{Rails.root}/db/seeds"
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
- Each time seeds.rb is run, Seeder will output a report detailing start and
55
- end time, and a log of how the number of things has changed.
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
- As of version 0.2.0, Seeder#build will not overwrite existing data unless
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.new(Thing, 'things.yml').build
71
+ Seeder.seed :thing
64
72
  thing.reload.colour ----> 'black'
65
73
 
66
- Seeder.new(Thing, 'things.yml', :overwrite => true).build
74
+ Seeder.seed(:thing, :overwrite => true).build
67
75
  thing.reload.colour ----> 'red'
68
76
 
69
- Have a look at the lib/examples folder, for a more detailed guide to how
70
- Dibber is used.
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
@@ -15,5 +15,5 @@ Rake::RDocTask.new do |rdoc|
15
15
  end
16
16
 
17
17
  Rake::TestTask.new do |t|
18
- t.test_files = FileList['test/**/*.rb']
18
+ t.test_files = FileList['test/**/*_test.rb']
19
19
  end
@@ -29,5 +29,9 @@ module Dibber
29
29
  return @report
30
30
  end
31
31
 
32
+ def exists?(name)
33
+ @log.keys.include?(name)
34
+ end
35
+
32
36
  end
33
37
  end
@@ -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
- process_log.start(klass.to_s.tableize.to_sym, "#{klass}.count")
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
- path = path + '/' unless path =~ /\/$/
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
@@ -1,9 +1,13 @@
1
1
  module Dibber
2
- VERSION = "0.2.2"
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
@@ -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
@@ -1,55 +1,5 @@
1
- class Thing
2
- attr_reader :name
3
- attr_accessor :attributes, :other_method
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
@@ -0,0 +1,5 @@
1
+ require_relative '../../not_quite_active_record'
2
+
3
+ class AdminUser < NotQuiteActiveRecord
4
+ attr_accessor :title, :header, :footer
5
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../not_quite_active_record'
2
+
3
+ class Borough < NotQuiteActiveRecord
4
+
5
+ end
@@ -0,0 +1,6 @@
1
+ require_relative '../../not_quite_active_record'
2
+ class Category < NotQuiteActiveRecord
3
+
4
+ attr_accessor :description, :title
5
+
6
+ end
@@ -0,0 +1,6 @@
1
+ require_relative '../../not_quite_active_record'
2
+ module Disclaimer
3
+ class Document < NotQuiteActiveRecord
4
+ attr_accessor :title, :header, :footer
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../not_quite_active_record'
2
+
3
+ class Fee < NotQuiteActiveRecord
4
+ attr_accessor :description, :value, :title
5
+ end
@@ -1,4 +1,4 @@
1
- require_relative '../dibber/process_log'
1
+ require_relative '../../lib/dibber/process_log'
2
2
 
3
3
  process_log = Dibber::ProcessLog.new
4
4
  process_log.start :time_one, 'Time.now'
@@ -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 = "#{Rails.root}/db/seeds"
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. Seeder working with a name spaced object
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 6. Seeder using values in the yaml file to set a single field
37
- Seeder.new(Category, 'categories.yml', 'description').build
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 7. Seeder using alternative name and attributes fields
40
- Seeder.new(
41
- Category,
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
- ).build
59
+ )
46
60
 
47
- # You can also access Seeders attached process log, and set up a custom log
48
- Seeder.process_log.start('First questionnaire questions', 'Questionnaire.count > 0 ? Questionnaire.first.questions.length : 0')
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
@@ -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.2.2
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-01 00:00:00.000000000 Z
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