dibber 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -5,10 +5,53 @@ A set of tools to tidy up rails seeds.rb files.
5
5
  Dibber has two compoments:
6
6
 
7
7
  === Seeder
8
+
8
9
  Seeder is designed to simplify the process of pulling attributes from
9
10
  YAML files, and populating ActiveRecord objects with those attributes.
10
11
 
11
12
  === ProcessLog
13
+
12
14
  ProcessLog provides Seeder with a simple before and after reporting tool.
13
15
 
14
- Have a look at the lib/examples folder, for a guide to how Dibber is used.
16
+ === Installation
17
+
18
+ Add this to your Gemfile:
19
+
20
+ gem 'dibber'
21
+
22
+ === Examples
23
+
24
+ You have a rails app with a Thing model, and you want to seed it with some
25
+ things. Thing instances have the attributes 'name', 'colour', 'size'.
26
+ You have a YAML file '/db/seeds/things.yml' that looks like this:
27
+
28
+ foo:
29
+ colour: red
30
+ size: large
31
+
32
+ bar:
33
+ colour: blue
34
+ size: small
35
+
36
+ Add this to your 'db/seeds.rb'
37
+
38
+ Seeder = Dibber::Seeder
39
+ Seeder.seeds_path = "#{Rails.root}/db/seeds"
40
+ Seeder.new(Thing, 'things.yml').build
41
+
42
+ Then run 'rake db:seed'
43
+
44
+ Seeder will create two new things (unless things with the names 'foo' or
45
+ 'bar' already exist, in which case it will update those things with the
46
+ values in the YAML file).
47
+
48
+ You'll then be able to do this:
49
+
50
+ thing = Thing.find_by_name(:foo)
51
+ thing.colour ---> 'red'
52
+
53
+ Each time seeds.rb is run, Seeder will output a report detailing start and
54
+ end time, and a log of how the number of things has changed.
55
+
56
+ Have a look at the lib/examples folder, for a more detailed guide to how
57
+ Dibber is used.
data/lib/dibber/seeder.rb CHANGED
@@ -1,6 +1,9 @@
1
+ require 'active_support/inflector'
2
+ require 'yaml'
3
+
1
4
  module Dibber
2
5
  class Seeder
3
- attr_accessor :klass, :file, :method
6
+ attr_accessor :klass, :file, :attribute_method, :name_method
4
7
 
5
8
  def self.process_log
6
9
  @process_log || start_process_log
@@ -13,7 +16,7 @@ module Dibber
13
16
  end
14
17
 
15
18
  def self.report
16
- @process_log.report
19
+ process_log.report
17
20
  end
18
21
 
19
22
  def self.monitor(klass)
@@ -34,17 +37,20 @@ module Dibber
34
37
  end
35
38
 
36
39
 
37
- def initialize(klass, file, method = 'attributes')
40
+ def initialize(klass, file, args = {})
38
41
  @klass = klass
39
42
  @file = file
40
- @method = method
43
+ args = {:attributes_method => args} unless args.kind_of?(Hash)
44
+ @attribute_method = args[:attributes_method] || 'attributes'
45
+ @name_method = args[:name_method] || 'name'
41
46
  end
42
47
 
43
48
  def build
44
49
  start_log
50
+ check_objects_exist
45
51
  objects.each do |name, attributes|
46
- object = klass.find_or_initialize_by_name(name)
47
- object.send("#{method}=", attributes)
52
+ object = klass.send(retrieval_method, name)
53
+ object.send("#{attribute_method}=", attributes)
48
54
  object.save
49
55
  end
50
56
  end
@@ -54,13 +60,21 @@ module Dibber
54
60
  end
55
61
 
56
62
  def objects
57
- self.class.objects_from(file)
63
+ @objects ||= self.class.objects_from(file)
58
64
  end
59
65
 
60
66
  private
61
67
  def self.raise_no_seeds_path_error
62
68
  raise "You must set the path to your seed files via Seeder.seeds_path = 'path/to/seed/files'"
63
69
  end
70
+
71
+ def check_objects_exist
72
+ raise "No objects returned from file: #{self.class.seeds_path}#{file}" unless objects
73
+ end
74
+
75
+ def retrieval_method
76
+ "find_or_initialize_by_#{name_method}"
77
+ end
64
78
 
65
79
  end
66
80
  end
@@ -0,0 +1,51 @@
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 unless self.class.saved.include? self
12
+ true
13
+ end
14
+
15
+ def self.find_or_initialize_by_name(name)
16
+ existing = members.select{|m| m.name == name.to_s}
17
+ if existing.empty?
18
+ new(name)
19
+ else
20
+ existing.first
21
+ end
22
+ end
23
+
24
+ def self.find_or_initialize_by_other_method(data)
25
+ existing = members.select{|m| m.other_method == data.to_s}
26
+ if existing.empty?
27
+ thing = new
28
+ thing.other_method = data.to_s
29
+ thing
30
+ else
31
+ existing.first
32
+ end
33
+ end
34
+
35
+ def self.members
36
+ @members ||= []
37
+ end
38
+
39
+ def self.count
40
+ members.length
41
+ end
42
+
43
+ def self.saved
44
+ @saved ||= []
45
+ end
46
+
47
+ def self.clear_all
48
+ @members = []
49
+ @saved = []
50
+ end
51
+ end
@@ -1,3 +1,3 @@
1
1
  module Dibber
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -23,18 +23,30 @@ AdminUser.create!(
23
23
  # Example 3. Seeder grabs the attributes from the YAML and builds a
24
24
  # set of Fee objects with those attributes (or updates them if
25
25
  # they already exist).
26
- # Note that the build process requires the model to have a name field.
26
+ # Note that the build process defaults to using a 'name' field to store
27
+ # the root key.
27
28
  Seeder.new(Fee, 'fees.yml').build
28
29
 
29
- # Example 4. Seeder working with a name spaced object
30
+ # Example 4. Seeder using an alternative name field
31
+ Seeder.new(Fee, 'fees.yml', :name_field => :title).build
32
+
33
+ # Example 5. Seeder working with a name spaced object
30
34
  Seeder.new(Disclaimer::Document, 'disclaimer/documents.yml').build
31
35
 
32
- # Example 5. Seeder using values in the yaml file to set a single field
36
+ # Example 6. Seeder using values in the yaml file to set a single field
33
37
  Seeder.new(Category, 'categories.yml', 'description').build
34
38
 
39
+ # Example 7. Seeder using alternative name and attributes fields
40
+ Seeder.new(
41
+ Category,
42
+ 'categories.yml',
43
+ :name_field => :title,
44
+ :attributes_field => :description
45
+ ).build
46
+
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')
49
+
35
50
  # Output a report showing how the numbers of each type of object
36
51
  # have changed through the process. Also has a log of start and end time.
37
52
  puts Seeder.report
38
-
39
- # You can also access Seeders attached process log, and set up a custom log
40
- Seeder.process_log.start('First questionnaire questions', 'Questionnaire.count > 0 ? Questionnaire.first.questions.length : 0')
@@ -0,0 +1,112 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'../..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'dibber'
5
+ require 'dibber/thing'
6
+
7
+ module Dibber
8
+
9
+ class SeederTest < Test::Unit::TestCase
10
+
11
+ def setup
12
+ Seeder.seeds_path = File.join(File.dirname(__FILE__),'seeds')
13
+ end
14
+
15
+ def teardown
16
+ Thing.clear_all
17
+ end
18
+
19
+ def test_process_log
20
+ assert_kind_of(ProcessLog, Seeder.process_log)
21
+ end
22
+
23
+ def test_process_log_start
24
+ @log = Seeder.process_log
25
+ assert(@log.raw.keys.include?(:time), 'time should be logged')
26
+ end
27
+
28
+ def test_report
29
+ test_process_log_start
30
+ assert_equal(@log.report, Seeder.report)
31
+ end
32
+
33
+ def test_monitor
34
+ Seeder.monitor(Thing)
35
+ assert_equal({:command => 'Thing.count', :start => Thing.count}, Seeder.process_log.raw[:things])
36
+ end
37
+
38
+ def test_seeds_path
39
+ assert_match(/test\/dibber\/seeds\/$/, Seeder.seeds_path)
40
+ end
41
+
42
+ def test_objects_from
43
+ content = YAML.load_file(thing_file_path)
44
+ assert_equal(content, Seeder.objects_from('things.yml'))
45
+ end
46
+
47
+ def test_start_log
48
+ thing_seeder.start_log
49
+ assert(Seeder.process_log.raw.keys.include?(:things), 'Things should be logged')
50
+ end
51
+
52
+ def test_objects
53
+ content = YAML.load_file(thing_file_path)
54
+ assert_equal(content, thing_seeder.objects)
55
+ end
56
+
57
+ def test_build_with_no_objects
58
+ thing_seeder = Seeder.new(Thing, 'empty.yml')
59
+ assert_raise RuntimeError do
60
+ thing_seeder.build
61
+ end
62
+ end
63
+
64
+ def test_build
65
+ assert_equal(0, Thing.count)
66
+ thing_seeder.build
67
+ assert_equal(2, Thing.count)
68
+ foo = Thing.find_or_initialize_by_name(:foo)
69
+ bar = Thing.find_or_initialize_by_name(:bar)
70
+ assert_equal([foo, bar], Thing.saved)
71
+ assert_equal({'title' => 'one'}, foo.attributes)
72
+ end
73
+
74
+ def test_other_method_replacing_attributes
75
+ thing_seeder('other_method').build
76
+ foo = Thing.find_or_initialize_by_name(:foo)
77
+ bar = Thing.find_or_initialize_by_name(:bar)
78
+ assert_equal([foo, bar], Thing.saved)
79
+ assert_nil(foo.attributes)
80
+ assert_equal({'title' => 'one'}, foo.other_method)
81
+ end
82
+
83
+ def test_other_method_replacing_attributes_via_args
84
+ thing_seeder(:attributes_method => 'other_method').build
85
+ foo = Thing.find_or_initialize_by_name(:foo)
86
+ bar = Thing.find_or_initialize_by_name(:bar)
87
+ assert_equal([foo, bar], Thing.saved)
88
+ assert_nil(foo.attributes)
89
+ assert_equal({'title' => 'one'}, foo.other_method)
90
+ end
91
+
92
+ def test_alternative_name_method
93
+ thing_seeder(:name_method => 'other_method').build
94
+ assert_equal(2, Thing.count)
95
+ foo = Thing.find_or_initialize_by_other_method(:foo)
96
+ bar = Thing.find_or_initialize_by_other_method(:bar)
97
+ assert_equal([foo, bar], Thing.saved)
98
+ assert_equal({'title' => 'one'}, foo.attributes)
99
+ end
100
+
101
+
102
+ private
103
+ def thing_seeder(method = 'attributes')
104
+ @thing_seeder = Seeder.new(Thing, 'things.yml', method)
105
+ end
106
+
107
+ def thing_file_path
108
+ File.join(File.dirname(__FILE__),'seeds', 'things.yml')
109
+ end
110
+ end
111
+
112
+ end
@@ -0,0 +1,2 @@
1
+ ## YAML Template.
2
+ ---
@@ -0,0 +1,5 @@
1
+ foo:
2
+ title: one
3
+
4
+ bar:
5
+ title: two
@@ -0,0 +1,81 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'../..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'dibber/thing'
5
+
6
+ module Dibber
7
+
8
+ class ThingTest < Test::Unit::TestCase
9
+
10
+ def teardown
11
+ Thing.clear_all
12
+ end
13
+
14
+ def test_find_or_initialize_by_name
15
+ @name = 'foo'
16
+ @thing = Thing.find_or_initialize_by_name(@name)
17
+ assert_equal(@name, @thing.name)
18
+ end
19
+
20
+ def test_find_or_initialize_by_name_with_symbol
21
+ test_find_or_initialize_by_name
22
+ assert_equal(1, Thing.count)
23
+ thing = Thing.find_or_initialize_by_name(:foo)
24
+ assert_equal(1, Thing.count)
25
+ assert_equal('foo', thing.name)
26
+ end
27
+
28
+ def test_find_or_initialize_by_name_when_thing_exists
29
+ test_find_or_initialize_by_name
30
+ test_find_or_initialize_by_name
31
+ assert_equal(1, Thing.count)
32
+ end
33
+
34
+ def test_count
35
+ assert_equal(0, Thing.count)
36
+ Thing.find_or_initialize_by_name(:thing_for_count_test)
37
+ assert_equal(1, Thing.count)
38
+ end
39
+
40
+ def test_attributes
41
+ stuff = %w{this that}
42
+ test_find_or_initialize_by_name
43
+ @thing.attributes = stuff
44
+ assert_equal(stuff, @thing.attributes)
45
+ end
46
+
47
+ def test_other_method
48
+ stuff = %w{come home mother}
49
+ test_find_or_initialize_by_name
50
+ @thing.other_method = stuff
51
+ assert_equal(stuff, @thing.other_method)
52
+ end
53
+
54
+ def test_save_and_saved
55
+ thing = Thing.find_or_initialize_by_name(:thing_for_save_test)
56
+ assert !Thing.saved.include?(thing), 'saved things should not include thing'
57
+ assert thing.save, 'should return true on save'
58
+ assert Thing.saved.include?(thing), 'saved things should include thing'
59
+ thing.save
60
+ assert_equal(1, Thing.saved.select{|t| t == thing}.length)
61
+ end
62
+
63
+ def test_clear
64
+ test_find_or_initialize_by_name
65
+ @thing.save
66
+ assert_not_equal(0, Thing.count)
67
+ assert_not_equal([], Thing.saved)
68
+ Thing.clear_all
69
+ assert_equal(0, Thing.count)
70
+ assert_equal([], Thing.saved)
71
+ end
72
+
73
+ def test_find_or_initialize_by_other_method
74
+ thing = Thing.find_or_initialize_by_other_method(:something)
75
+ assert_nil(thing.name)
76
+ assert_equal('something', thing.other_method)
77
+ end
78
+
79
+ end
80
+
81
+ 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.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-19 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2013-01-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: active_support
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  description: Packages up code needed to pull data from YAML files when seeding, and
15
31
  adds a process log.
16
32
  email:
@@ -27,12 +43,17 @@ files:
27
43
  - lib/examples/seeds.rb
28
44
  - lib/dibber.rb
29
45
  - lib/dibber/version.rb
46
+ - lib/dibber/thing.rb
30
47
  - lib/dibber/process_log.rb
31
48
  - lib/dibber/seeder.rb
32
49
  - MIT-LICENSE
33
50
  - Rakefile
34
51
  - README.rdoc
52
+ - test/dibber/seeder_test.rb
35
53
  - test/dibber/process_log_test.rb
54
+ - test/dibber/seeds/empty.yml
55
+ - test/dibber/seeds/things.yml
56
+ - test/dibber/thing_test.rb
36
57
  homepage: https://github.com/reggieb/Dibber
37
58
  licenses: []
38
59
  post_install_message:
@@ -58,4 +79,8 @@ signing_key:
58
79
  specification_version: 3
59
80
  summary: Tool for seeding database from YAML.
60
81
  test_files:
82
+ - test/dibber/seeder_test.rb
61
83
  - test/dibber/process_log_test.rb
84
+ - test/dibber/seeds/empty.yml
85
+ - test/dibber/seeds/things.yml
86
+ - test/dibber/thing_test.rb