sprig-reap 0.0.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +51 -0
- data/Rakefile +5 -0
- data/lib/sprig/reap/configuration.rb +61 -0
- data/lib/sprig/reap/model.rb +75 -0
- data/lib/sprig/reap/record.rb +59 -0
- data/lib/sprig/reap/seed_file.rb +52 -0
- data/lib/sprig/reap/tsortable_hash.rb +11 -0
- data/lib/sprig/reap/version.rb +5 -0
- data/lib/sprig/reap.rb +35 -0
- data/lib/tasks/reap.rake +9 -0
- data/spec/db/activerecord.db +0 -0
- data/spec/fixtures/models/comment.rb +5 -0
- data/spec/fixtures/models/post.rb +2 -0
- data/spec/fixtures/models/user.rb +3 -0
- data/spec/fixtures/yaml/comment_seeds.yml +7 -0
- data/spec/fixtures/yaml/post_seeds.yml +9 -0
- data/spec/fixtures/yaml/records_with_namespace.yml +7 -0
- data/spec/fixtures/yaml/records_without_namespace.yml +6 -0
- data/spec/fixtures/yaml/user_seeds.yml +7 -0
- data/spec/lib/sprig/reap/configuration_spec.rb +99 -0
- data/spec/lib/sprig/reap/model_spec.rb +120 -0
- data/spec/lib/sprig/reap/record_spec.rb +70 -0
- data/spec/lib/sprig/reap/seed_file_spec.rb +109 -0
- data/spec/lib/sprig/reap_spec.rb +55 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/support/file_setup.rb +10 -0
- data/spec/support/rails_stubs.rb +11 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d9274dc514b03b7804de43aba385e8cc68d954af
|
4
|
+
data.tar.gz: f9c7b62a38c72b9745ef5a982b7ae26fc43ced61
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d0f68d527c8ae07b07a1fb7b6e3f2874343f3b62f4f340383a2dd90c354914d13a821ce2898c6cc364cf8b3b7b4e805b208104465198498cb5e3ee97b750ef6c
|
7
|
+
data.tar.gz: 50f0b95641ecf1de92a336f302b6bd33657e7f7f15db17527ef888aaf7fd28f031a8d63ca60bbea01ae37fbf8eb7a3f33c2e1eb319bc454f1ba589fdfbe8a6a1
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 Viget
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Sprig::Reap
|
2
|
+
|
3
|
+
Automatic capture and output of your application's data state to Sprig-formatted seed files.
|
4
|
+
|
5
|
+
## Populate Seed Files from Database
|
6
|
+
|
7
|
+
Don't want to write Sprig seed files from scratch? Well, Sprig::Reap can create them for you!
|
8
|
+
|
9
|
+
Via a rake task:
|
10
|
+
```
|
11
|
+
rake db:seed:reap
|
12
|
+
```
|
13
|
+
Or from the Rails console:
|
14
|
+
```
|
15
|
+
Sprig::Reap.reap
|
16
|
+
```
|
17
|
+
|
18
|
+
By default, Sprig::Reap will create seed files (currently in `.yaml` only) for every model in your Rails
|
19
|
+
application. The seed files will be placed in a folder in `db/seeds` named after the current
|
20
|
+
`Rails.env`.
|
21
|
+
|
22
|
+
If any of the models in your application are using STI, Sprig::Reap will create a single seed file named
|
23
|
+
after the STI base model. STI sub-type records will all be written to that file.
|
24
|
+
|
25
|
+
### Additional Configuration
|
26
|
+
|
27
|
+
Don't like the defaults when reaping Sprig::Reap records? You may specify the environment (`db/seeds`
|
28
|
+
target folder) or models (`ActiveRecord::Base.subclasses`-only) you want seed files for.
|
29
|
+
|
30
|
+
```
|
31
|
+
# Rake Task
|
32
|
+
rake db:seed:reap ENV=integration MODELS=User,Post
|
33
|
+
|
34
|
+
# Rails Console
|
35
|
+
Sprig::Reap.reap(env: 'integration', models: [User, Post])
|
36
|
+
```
|
37
|
+
|
38
|
+
### Adding to Existing Seed Files (`.yaml` only)
|
39
|
+
|
40
|
+
Already have some seed files set up? No worries! Sprig::Reap will detect existing seed files and append
|
41
|
+
to them with the records from your database with no extra work needed. Sprig::Reap will automatically
|
42
|
+
assign unique `sprig_ids` so you won't have to deal with pesky duplicates.
|
43
|
+
|
44
|
+
NOTE: Sprig::Reap does not account for your application or database validations. If you reap seed files
|
45
|
+
from your database multiple times in a row without deleting the previous seed files or sprig
|
46
|
+
records, you'll end up with duplicate sprig records (but they'll all have unique `sprig_ids`). This
|
47
|
+
may cause validation issues when you seed your database.
|
48
|
+
|
49
|
+
## License
|
50
|
+
|
51
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module Sprig::Reap
|
2
|
+
class Configuration
|
3
|
+
VALID_CLASSES = ActiveRecord::Base.subclasses
|
4
|
+
|
5
|
+
def env
|
6
|
+
@env ||= Rails.env
|
7
|
+
end
|
8
|
+
|
9
|
+
def env=(given_env)
|
10
|
+
parse_valid_env_from given_env do |environment|
|
11
|
+
@env = environment
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def classes
|
16
|
+
@classes ||= VALID_CLASSES
|
17
|
+
end
|
18
|
+
|
19
|
+
def classes=(given_classes)
|
20
|
+
parse_valid_classes_from given_classes do |classes|
|
21
|
+
@classes = classes
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def parse_valid_env_from(input)
|
28
|
+
return if input.nil?
|
29
|
+
environment = input.strip.downcase
|
30
|
+
create_seeds_folder(environment)
|
31
|
+
yield environment
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_seeds_folder(env)
|
35
|
+
folder = Rails.root.join('db', 'seeds', env)
|
36
|
+
FileUtils.mkdir_p(folder) unless File.directory? folder
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_valid_classes_from(input)
|
40
|
+
return if input.nil?
|
41
|
+
|
42
|
+
classes = if input.is_a? String
|
43
|
+
input.split(',').map { |klass_string| klass_string.strip.classify.constantize }
|
44
|
+
else
|
45
|
+
input
|
46
|
+
end
|
47
|
+
|
48
|
+
validate_classes(classes)
|
49
|
+
|
50
|
+
yield classes
|
51
|
+
end
|
52
|
+
|
53
|
+
def validate_classes(classes)
|
54
|
+
classes.each do |klass|
|
55
|
+
unless VALID_CLASSES.include? klass
|
56
|
+
raise ArgumentError, "Cannot create a seed file for #{klass} because it is not a subclass of ActiveRecord::Base."
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Sprig::Reap
|
2
|
+
class Model
|
3
|
+
def self.all
|
4
|
+
@@all ||= begin
|
5
|
+
models = Sprig::Reap.classes.map { |klass| new(klass) }
|
6
|
+
|
7
|
+
tsorted_classes(models).map do |klass|
|
8
|
+
models.find { |model| model.klass == klass }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.find(klass, id)
|
14
|
+
all.find { |model| model.klass == klass }.find(id)
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :klass
|
18
|
+
attr_writer :existing_sprig_ids
|
19
|
+
|
20
|
+
def initialize(klass)
|
21
|
+
@klass = klass
|
22
|
+
end
|
23
|
+
|
24
|
+
def attributes
|
25
|
+
klass.column_names
|
26
|
+
end
|
27
|
+
|
28
|
+
def dependencies
|
29
|
+
@dependencies ||= klass.reflect_on_all_associations(:belongs_to).map do |association|
|
30
|
+
association.name.to_s.classify.constantize
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def existing_sprig_ids
|
35
|
+
@existing_sprig_ids ||= []
|
36
|
+
end
|
37
|
+
|
38
|
+
def generate_sprig_id
|
39
|
+
existing_sprig_ids.select { |i| i.is_a? Integer }.sort.last + 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def find(id)
|
43
|
+
records.find { |record| record.id == id }
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
klass.to_s
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_yaml(options = {})
|
51
|
+
namespace = options[:namespace]
|
52
|
+
formatted_records = records.map(&:to_hash)
|
53
|
+
|
54
|
+
yaml = if namespace
|
55
|
+
{ namespace => formatted_records }.to_yaml
|
56
|
+
else
|
57
|
+
formatted_records.to_yaml
|
58
|
+
end
|
59
|
+
|
60
|
+
yaml.gsub("---\n", '') # Remove annoying YAML separator
|
61
|
+
end
|
62
|
+
|
63
|
+
def records
|
64
|
+
@records ||= klass.all.map { |record| Record.new(record, self) }
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def self.tsorted_classes(models)
|
70
|
+
models.reduce(TsortableHash.new) do |hash, model|
|
71
|
+
hash.merge(model.klass => model.dependencies)
|
72
|
+
end.tsort
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Sprig::Reap
|
2
|
+
class Record
|
3
|
+
attr_reader :record, :model
|
4
|
+
attr_writer :sprig_id
|
5
|
+
|
6
|
+
def initialize(record, model)
|
7
|
+
@record = record
|
8
|
+
@model = model
|
9
|
+
end
|
10
|
+
|
11
|
+
def attributes
|
12
|
+
@attributes ||= Array.new.replace(model.attributes).tap do |attrs|
|
13
|
+
attrs[0] = 'sprig_id'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_hash
|
18
|
+
attributes.reduce(Hash.new) { |hash, attr| hash.merge(attr => send(attr)) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def sprig_id
|
22
|
+
@sprig_id ||= model.existing_sprig_ids.include?(record.id) ? model.generate_sprig_id : record.id
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def method_missing(method, *args, &block)
|
28
|
+
attr = model.attributes.find { |attr| attr == method.to_s }
|
29
|
+
|
30
|
+
if attr.nil?
|
31
|
+
super
|
32
|
+
elsif dependency_finder.match(attr)
|
33
|
+
klass = klass_for(attr)
|
34
|
+
id = record.send(attr)
|
35
|
+
sprig_id = Model.find(klass, id).sprig_id
|
36
|
+
|
37
|
+
sprig_record(klass, sprig_id)
|
38
|
+
else
|
39
|
+
record.send(attr)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def respond_to_missing?(method, include_private = false)
|
44
|
+
model.attributes.include?(method.to_s) || super
|
45
|
+
end
|
46
|
+
|
47
|
+
def dependency_finder
|
48
|
+
/_id/
|
49
|
+
end
|
50
|
+
|
51
|
+
def klass_for(attr)
|
52
|
+
attr.gsub(dependency_finder, '').classify.constantize
|
53
|
+
end
|
54
|
+
|
55
|
+
def sprig_record(klass, sprig_id)
|
56
|
+
"<%= sprig_record(#{klass}, #{sprig_id}).id %>"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Sprig::Reap
|
2
|
+
class SeedFile
|
3
|
+
DEFAULT_NAMESPACE = 'records'
|
4
|
+
|
5
|
+
attr_reader :model
|
6
|
+
|
7
|
+
def initialize(model)
|
8
|
+
raise ArgumentError, 'Must initialize with a Sprig::Reap::Model' unless model.is_a? Model
|
9
|
+
|
10
|
+
@model = model
|
11
|
+
end
|
12
|
+
|
13
|
+
def path
|
14
|
+
Rails.root.join('db', 'seeds', Sprig::Reap.env, "#{model.to_s.tableize.gsub('/', '_')}.yml")
|
15
|
+
end
|
16
|
+
|
17
|
+
def exists?
|
18
|
+
File.exists?(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def write
|
22
|
+
initialize_file do |file, namespace|
|
23
|
+
file.write model.to_yaml(:namespace => namespace)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def initialize_file
|
30
|
+
existing_file = exists?
|
31
|
+
access_type = existing_file ? 'a+' : 'w'
|
32
|
+
|
33
|
+
File.open(path, access_type) do |file|
|
34
|
+
namespace = DEFAULT_NAMESPACE
|
35
|
+
|
36
|
+
if existing_file
|
37
|
+
model.existing_sprig_ids = existing_sprig_ids(file.read)
|
38
|
+
namespace = nil
|
39
|
+
file.write("\n")
|
40
|
+
end
|
41
|
+
|
42
|
+
yield file, namespace
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def existing_sprig_ids(yaml)
|
47
|
+
YAML.load(yaml).fetch(DEFAULT_NAMESPACE).to_a.map do |record|
|
48
|
+
record.fetch('sprig_id')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/sprig/reap.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "sprig/reap/version"
|
2
|
+
|
3
|
+
module Sprig::Reap
|
4
|
+
autoload :TsortableHash, 'sprig/reap/tsortable_hash'
|
5
|
+
autoload :Railtie, 'sprig/reap/railtie'
|
6
|
+
autoload :Configuration, 'sprig/reap/configuration'
|
7
|
+
autoload :Model, 'sprig/reap/model'
|
8
|
+
autoload :Record, 'sprig/reap/record'
|
9
|
+
autoload :SeedFile, 'sprig/reap/seed_file'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def reap(options = {})
|
13
|
+
configure do |config|
|
14
|
+
config.env = options[:env] || options['ENV']
|
15
|
+
config.classes = options[:models] || options['MODELS']
|
16
|
+
end
|
17
|
+
|
18
|
+
Model.all.each { |model| SeedFile.new(model).write }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
cattr_reader :configuration
|
24
|
+
|
25
|
+
delegate :env, :classes, to: :configuration
|
26
|
+
|
27
|
+
def configuration
|
28
|
+
@@configuration ||= Configuration.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure
|
32
|
+
yield configuration
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/tasks/reap.rake
ADDED
Binary file
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sprig::Reap::Configuration do
|
4
|
+
subject { described_class.new }
|
5
|
+
|
6
|
+
before do
|
7
|
+
stub_rails_root
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#env" do
|
11
|
+
context "from a fresh configuration" do
|
12
|
+
its(:env) { should == Rails.env }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#env=" do
|
17
|
+
context "when given nil" do
|
18
|
+
it "does not change the env" do
|
19
|
+
subject.env = nil
|
20
|
+
|
21
|
+
subject.env.should_not == nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "given a non-nil value" do
|
26
|
+
let(:input) { ' ShaBOOSH' }
|
27
|
+
|
28
|
+
it "formats the given value and then sets the environment" do
|
29
|
+
subject.env = input
|
30
|
+
|
31
|
+
subject.env.should == 'shaboosh'
|
32
|
+
end
|
33
|
+
|
34
|
+
context "and the corresponding seeds folder does not yet exist" do
|
35
|
+
after do
|
36
|
+
FileUtils.remove_dir('./spec/fixtures/db/seeds/shaboosh')
|
37
|
+
end
|
38
|
+
|
39
|
+
it "creates the seeds folder" do
|
40
|
+
subject.env = input
|
41
|
+
|
42
|
+
File.directory?('./spec/fixtures/db/seeds/shaboosh').should == true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#classes" do
|
49
|
+
context "from a fresh configuration" do
|
50
|
+
its(:classes) { should == ActiveRecord::Base.subclasses }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#classes=" do
|
55
|
+
context "when given nil" do
|
56
|
+
it "does not set classes to nil" do
|
57
|
+
subject.classes = nil
|
58
|
+
|
59
|
+
subject.classes.should_not == nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when given an array of classes" do
|
64
|
+
context "where one or more classes are not subclasses of ActiveRecord::Base" do
|
65
|
+
it "raises an error" do
|
66
|
+
expect {
|
67
|
+
subject.classes = [Comment, Sprig::Reap::Model]
|
68
|
+
}.to raise_error ArgumentError, 'Cannot create a seed file for Sprig::Reap::Model because it is not a subclass of ActiveRecord::Base.'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "where all classes are subclasses of ActiveRecord::Base" do
|
73
|
+
it "sets classes to the given input" do
|
74
|
+
subject.classes = [Comment, Post]
|
75
|
+
|
76
|
+
subject.classes.should == [Comment, Post]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when given a string" do
|
82
|
+
context "where one or more classes are not subclasses of ActiveRecord::Base" do
|
83
|
+
it "raises an error" do
|
84
|
+
expect {
|
85
|
+
subject.classes = 'Sprig::Reap::Model'
|
86
|
+
}.to raise_error ArgumentError, 'Cannot create a seed file for Sprig::Reap::Model because it is not a subclass of ActiveRecord::Base.'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "where all classes are subclasses of ActiveRecord::Base" do
|
91
|
+
it "sets classes to the parsed input" do
|
92
|
+
subject.classes = ' comment, post'
|
93
|
+
|
94
|
+
subject.classes.should == [Comment, Post]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sprig::Reap::Model do
|
4
|
+
describe ".all" do
|
5
|
+
let(:all_models) do
|
6
|
+
[
|
7
|
+
described_class.new(Post),
|
8
|
+
described_class.new(Comment),
|
9
|
+
described_class.new(User)
|
10
|
+
]
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
Sprig::Reap.stub(:classes).and_return([Comment, Post, User])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns an dependency-sorted array of Sprig::Reap::Models" do
|
18
|
+
described_class.all.all? { |model| model.is_a? Sprig::Reap::Model }.should == true
|
19
|
+
described_class.all.map(&:klass).should == all_models.map(&:klass)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe ".find" do
|
24
|
+
let!(:user) { User.create(:first_name => 'Bo', :last_name => 'Janglez') }
|
25
|
+
let!(:post1) { Post.create }
|
26
|
+
let!(:post2) { Post.create }
|
27
|
+
let!(:comment1) { Comment.create(:post => post1) }
|
28
|
+
let!(:comment2) { Comment.create(:post => post2) }
|
29
|
+
|
30
|
+
subject { described_class }
|
31
|
+
|
32
|
+
it "returns the Sprig::Reap::Record for the given class and id" do
|
33
|
+
subject.find(User, 1).record.should == user
|
34
|
+
subject.find(Post, 1).record.should == post1
|
35
|
+
subject.find(Post, 2).record.should == post2
|
36
|
+
subject.find(Comment, 1).record.should == comment1
|
37
|
+
subject.find(Comment, 2).record.should == comment2
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#attributes" do
|
42
|
+
subject { described_class.new(User) }
|
43
|
+
|
44
|
+
its(:attributes) { should == User.column_names }
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#dependencies" do
|
48
|
+
subject { described_class.new(Comment) }
|
49
|
+
|
50
|
+
its(:dependencies) { should == [Post] }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#find" do
|
54
|
+
let!(:post1) { Post.create }
|
55
|
+
let!(:post2) { Post.create }
|
56
|
+
|
57
|
+
subject { described_class.new(Post) }
|
58
|
+
|
59
|
+
it "returns the Sprig::Reap::Record with the given id" do
|
60
|
+
reap_record = subject.find(2)
|
61
|
+
reap_record.should be_an_instance_of Sprig::Reap::Record
|
62
|
+
reap_record.record.should == post2
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#generate_sprig_id" do
|
67
|
+
subject { described_class.new(Comment) }
|
68
|
+
|
69
|
+
context "when the existing sprig_ids are all integers" do
|
70
|
+
before do
|
71
|
+
subject.existing_sprig_ids = [5, 20, 8]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns an integer-type sprig_id that is not taken" do
|
75
|
+
subject.generate_sprig_id.should == 21
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when the existing sprig ids contain non-integer values" do
|
80
|
+
before do
|
81
|
+
subject.existing_sprig_ids = [1, 5, 'l_2', 'l_10', 'such_sprigs', 10.9]
|
82
|
+
end
|
83
|
+
it "returns an integer-type sprig_id that is not taken" do
|
84
|
+
subject.generate_sprig_id.should == 6
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#to_s" do
|
90
|
+
subject { described_class.new(Comment) }
|
91
|
+
|
92
|
+
its(:to_s) { should == "Comment" }
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#to_yaml" do
|
96
|
+
let!(:user) { User.create(:first_name => 'Bo', :last_name => 'Janglez') }
|
97
|
+
let!(:post1) { Post.create }
|
98
|
+
let!(:post2) { Post.create }
|
99
|
+
let!(:comment1) { Comment.create(:post => post1) }
|
100
|
+
let!(:comment2) { Comment.create(:post => post2) }
|
101
|
+
|
102
|
+
subject { described_class.new(Comment) }
|
103
|
+
|
104
|
+
context "when passed a value for the namespace" do
|
105
|
+
it "returns the correct yaml" do
|
106
|
+
subject.to_yaml(:namespace => 'records').should == yaml_from_file('records_with_namespace.yml')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when no namespace is given" do
|
111
|
+
it "returns the correct yaml" do
|
112
|
+
subject.to_yaml.should == yaml_from_file('records_without_namespace.yml')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def yaml_from_file(basename)
|
118
|
+
File.read('spec/fixtures/yaml/' + basename)
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Very; end
|
4
|
+
|
5
|
+
describe Sprig::Reap::Record do
|
6
|
+
let(:record) { double('ActiveRecord::Base Instance') }
|
7
|
+
let(:model) { double('Sprig::Reap::Model') }
|
8
|
+
let(:reap_record) { double('Sprig::Reap::Record for class Very', :sprig_id => 5) }
|
9
|
+
let(:sprig_record) { "<%= sprig_record(Very, 5).id %>" }
|
10
|
+
|
11
|
+
subject { described_class.new(record, model) }
|
12
|
+
|
13
|
+
before do
|
14
|
+
attrs = {
|
15
|
+
'id' => 0,
|
16
|
+
'such' => 1,
|
17
|
+
'wow' => 2,
|
18
|
+
'very_id' => 3
|
19
|
+
}
|
20
|
+
|
21
|
+
attrs.each_pair do |attr, val|
|
22
|
+
record.stub(attr).and_return(val)
|
23
|
+
end
|
24
|
+
|
25
|
+
model.stub(:attributes).and_return(attrs.keys)
|
26
|
+
model.stub(:existing_sprig_ids).and_return([])
|
27
|
+
|
28
|
+
Sprig::Reap::Model.stub(:find).and_return(reap_record)
|
29
|
+
end
|
30
|
+
|
31
|
+
its(:id) { should == 0 }
|
32
|
+
its(:such) { should == 1 }
|
33
|
+
its(:wow) { should == 2 }
|
34
|
+
its(:very_id) { should == sprig_record }
|
35
|
+
|
36
|
+
describe "#attributes" do
|
37
|
+
it "returns an array of attributes from the given model with sprig_id swapped out for id" do
|
38
|
+
subject.attributes.should == %w(
|
39
|
+
sprig_id
|
40
|
+
such
|
41
|
+
wow
|
42
|
+
very_id
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#to_hash" do
|
48
|
+
it "returns its attributes and their values in a hash" do
|
49
|
+
subject.to_hash.should == {
|
50
|
+
'sprig_id' => 0,
|
51
|
+
'such' => 1,
|
52
|
+
'wow' => 2,
|
53
|
+
'very_id' => sprig_record
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#sprig_id" do
|
59
|
+
its(:sprig_id) { should == record.id }
|
60
|
+
|
61
|
+
context "when an existing seed record has a sprig_id equal to the record's id" do
|
62
|
+
before do
|
63
|
+
model.stub(:existing_sprig_ids).and_return([record.id])
|
64
|
+
model.stub(:generate_sprig_id).and_return(25)
|
65
|
+
end
|
66
|
+
|
67
|
+
its(:sprig_id) { should == 25 }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sprig::Reap::SeedFile do
|
4
|
+
let(:model) { Sprig::Reap::Model.new(Comment) }
|
5
|
+
|
6
|
+
subject { described_class.new(model) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
stub_rails_root
|
10
|
+
Sprig::Reap.stub(:env).and_return('dreamland')
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
context "given a non-Sprig::Reap::Model" do
|
15
|
+
it "raises an error" do
|
16
|
+
expect {
|
17
|
+
described_class.new(User)
|
18
|
+
}.to raise_error ArgumentError, 'Must initialize with a Sprig::Reap::Model'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#path" do
|
24
|
+
around do |example|
|
25
|
+
setup_seed_folder('./spec/fixtures/db/seeds/dreamland', &example)
|
26
|
+
end
|
27
|
+
|
28
|
+
its(:path) { should == Rails.root.join('db', 'seeds', 'dreamland', 'comments.yml') }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#exists?" do
|
32
|
+
subject { described_class.new(model) }
|
33
|
+
|
34
|
+
around do |example|
|
35
|
+
setup_seed_folder('./spec/fixtures/db/seeds/dreamland', &example)
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when the seed file already exists" do
|
39
|
+
before do
|
40
|
+
File.stub(:exists?).with(subject.path).and_return(true)
|
41
|
+
end
|
42
|
+
|
43
|
+
its(:exists?) { should == true }
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when the seed file does not exist" do
|
47
|
+
its(:exists?) { should == false }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#write" do
|
52
|
+
let!(:user) { User.create(:first_name => 'Bo', :last_name => 'Janglez') }
|
53
|
+
let!(:post1) { Post.create }
|
54
|
+
let!(:post2) { Post.create }
|
55
|
+
let!(:comment1) { Comment.create(:post => post1) }
|
56
|
+
let!(:comment2) { Comment.create(:post => post2) }
|
57
|
+
|
58
|
+
around do |example|
|
59
|
+
setup_seed_folder('./spec/fixtures/db/seeds/dreamland', &example)
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when the seed file already exists" do
|
63
|
+
before do
|
64
|
+
yaml = File.read('./spec/fixtures/yaml/comment_seeds.yml')
|
65
|
+
File.open(subject.path, 'w') { |file| file.write(yaml) }
|
66
|
+
end
|
67
|
+
|
68
|
+
it "pulls out the existing sprig ids and stores them on the given model" do
|
69
|
+
model.should_receive(:existing_sprig_ids=).with([10, 20])
|
70
|
+
|
71
|
+
subject.write
|
72
|
+
end
|
73
|
+
|
74
|
+
it "grabs the yaml for the given model without a namespace" do
|
75
|
+
model.should_receive(:to_yaml).with(:namespace => nil)
|
76
|
+
|
77
|
+
subject.write
|
78
|
+
end
|
79
|
+
|
80
|
+
it "populates the file" do
|
81
|
+
starting_size = File.size(subject.path)
|
82
|
+
|
83
|
+
subject.write
|
84
|
+
|
85
|
+
File.size?(subject.path).should > starting_size
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when the seed file does not yet exist" do
|
90
|
+
it "does not pass any existing sprig ids to the given model" do
|
91
|
+
model.should_not_receive(:existing_sprig_ids=)
|
92
|
+
|
93
|
+
subject.write
|
94
|
+
end
|
95
|
+
|
96
|
+
it "grabs the yaml for the given model with the 'records' namespace" do
|
97
|
+
model.should_receive(:to_yaml).with(:namespace => 'records')
|
98
|
+
|
99
|
+
subject.write
|
100
|
+
end
|
101
|
+
|
102
|
+
it "populates the file" do
|
103
|
+
subject.write
|
104
|
+
|
105
|
+
File.size?(subject.path).should > 0
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sprig::Reap do
|
4
|
+
describe ".reap" do
|
5
|
+
let(:seed_file) { double('Sprig::Reap::SeedFile', :write => 'such seeds') }
|
6
|
+
|
7
|
+
before do
|
8
|
+
stub_rails_root
|
9
|
+
stub_rails_env
|
10
|
+
Sprig::Reap::SeedFile.stub(:new).and_return(seed_file)
|
11
|
+
end
|
12
|
+
|
13
|
+
around do |example|
|
14
|
+
setup_seed_folder('./spec/fixtures/db/seeds/dreamland', &example)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "generates a seed file for each class" do
|
18
|
+
seed_file.should_receive(:write).exactly(3).times
|
19
|
+
|
20
|
+
subject.reap
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when passed an environment in the options hash" do
|
24
|
+
context "in :env" do
|
25
|
+
it "sets the environment" do
|
26
|
+
subject.reap(:env => 'dreamland')
|
27
|
+
subject.env.should == 'dreamland'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "in 'ENV'" do
|
32
|
+
it "sets the environment" do
|
33
|
+
subject.reap('ENV' => ' Dreamland')
|
34
|
+
subject.env.should == 'dreamland'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when passed a set of classes in the options hash" do
|
40
|
+
context "in :classes" do
|
41
|
+
it "sets the classes" do
|
42
|
+
subject.reap(:models => [User, Post])
|
43
|
+
subject.classes.should == [User, Post]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "sets the classes" do
|
48
|
+
it "passes the value to its configuration" do
|
49
|
+
subject.reap('MODELS' => 'User, Post')
|
50
|
+
subject.classes.should == [User, Post]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
ENV["RAILS_ENV"] ||= 'test'
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
require "active_record"
|
5
|
+
require "database_cleaner"
|
6
|
+
require "pry"
|
7
|
+
require "generator_spec"
|
8
|
+
|
9
|
+
require "sprig/reap"
|
10
|
+
|
11
|
+
%w(
|
12
|
+
/fixtures/models/*rb
|
13
|
+
/support/**/*.rb
|
14
|
+
).each do |file_set|
|
15
|
+
Dir[File.dirname(__FILE__) + file_set].each { |file| require file }
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.include RailsStubs
|
20
|
+
config.include FileSetup
|
21
|
+
|
22
|
+
config.before(:suite) do
|
23
|
+
DatabaseCleaner.strategy = :transaction
|
24
|
+
DatabaseCleaner.clean_with(:truncation)
|
25
|
+
end
|
26
|
+
|
27
|
+
config.before(:each) do
|
28
|
+
DatabaseCleaner.start
|
29
|
+
end
|
30
|
+
|
31
|
+
config.after(:each) do
|
32
|
+
DatabaseCleaner.clean
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Database
|
37
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "spec/db/activerecord.db")
|
38
|
+
|
39
|
+
User.connection.execute "DROP TABLE IF EXISTS users;"
|
40
|
+
User.connection.execute "CREATE TABLE users (id INTEGER PRIMARY KEY , first_name VARCHAR(255), last_name VARCHAR(255), type VARCHAR(255));"
|
41
|
+
|
42
|
+
Post.connection.execute "DROP TABLE IF EXISTS posts;"
|
43
|
+
Post.connection.execute "CREATE TABLE posts (id INTEGER PRIMARY KEY , title VARCHAR(255), content VARCHAR(255), published BOOLEAN , user_id INTEGER);"
|
44
|
+
|
45
|
+
Comment.connection.execute "DROP TABLE IF EXISTS comments;"
|
46
|
+
Comment.connection.execute "CREATE TABLE comments (id INTEGER PRIMARY KEY , post_id INTEGER, body VARCHAR(255));"
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module RailsStubs
|
2
|
+
# Setup fake `Rails.root`
|
3
|
+
def stub_rails_root(path='./spec/fixtures')
|
4
|
+
Rails.stub(:root).and_return(Pathname.new(path))
|
5
|
+
end
|
6
|
+
|
7
|
+
# Setup fake `Rails.env`
|
8
|
+
def stub_rails_env(env='development')
|
9
|
+
Rails.stub(:env).and_return(env)
|
10
|
+
end
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sprig-reap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Stenberg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.3.8
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.3.8
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.14.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.14.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: database_cleaner
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.2.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.2.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: generator_spec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Sprig-Reap is a gem that allows you to output your application's data
|
98
|
+
state to seed files.
|
99
|
+
email:
|
100
|
+
- ryan.stenberg@viget.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- lib/sprig/reap/configuration.rb
|
106
|
+
- lib/sprig/reap/model.rb
|
107
|
+
- lib/sprig/reap/record.rb
|
108
|
+
- lib/sprig/reap/seed_file.rb
|
109
|
+
- lib/sprig/reap/tsortable_hash.rb
|
110
|
+
- lib/sprig/reap/version.rb
|
111
|
+
- lib/sprig/reap.rb
|
112
|
+
- lib/tasks/reap.rake
|
113
|
+
- MIT-LICENSE
|
114
|
+
- Rakefile
|
115
|
+
- README.md
|
116
|
+
- spec/db/activerecord.db
|
117
|
+
- spec/fixtures/models/comment.rb
|
118
|
+
- spec/fixtures/models/post.rb
|
119
|
+
- spec/fixtures/models/user.rb
|
120
|
+
- spec/fixtures/yaml/comment_seeds.yml
|
121
|
+
- spec/fixtures/yaml/post_seeds.yml
|
122
|
+
- spec/fixtures/yaml/records_with_namespace.yml
|
123
|
+
- spec/fixtures/yaml/records_without_namespace.yml
|
124
|
+
- spec/fixtures/yaml/user_seeds.yml
|
125
|
+
- spec/lib/sprig/reap/configuration_spec.rb
|
126
|
+
- spec/lib/sprig/reap/model_spec.rb
|
127
|
+
- spec/lib/sprig/reap/record_spec.rb
|
128
|
+
- spec/lib/sprig/reap/seed_file_spec.rb
|
129
|
+
- spec/lib/sprig/reap_spec.rb
|
130
|
+
- spec/spec_helper.rb
|
131
|
+
- spec/support/file_setup.rb
|
132
|
+
- spec/support/rails_stubs.rb
|
133
|
+
homepage: http://www.github.com/vigetlabs/sprig-reap
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
metadata: {}
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 2.0.3
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: Automatic seed file generation for Rails apps using Sprig.
|
157
|
+
test_files:
|
158
|
+
- spec/db/activerecord.db
|
159
|
+
- spec/fixtures/models/comment.rb
|
160
|
+
- spec/fixtures/models/post.rb
|
161
|
+
- spec/fixtures/models/user.rb
|
162
|
+
- spec/fixtures/yaml/comment_seeds.yml
|
163
|
+
- spec/fixtures/yaml/post_seeds.yml
|
164
|
+
- spec/fixtures/yaml/records_with_namespace.yml
|
165
|
+
- spec/fixtures/yaml/records_without_namespace.yml
|
166
|
+
- spec/fixtures/yaml/user_seeds.yml
|
167
|
+
- spec/lib/sprig/reap/configuration_spec.rb
|
168
|
+
- spec/lib/sprig/reap/model_spec.rb
|
169
|
+
- spec/lib/sprig/reap/record_spec.rb
|
170
|
+
- spec/lib/sprig/reap/seed_file_spec.rb
|
171
|
+
- spec/lib/sprig/reap_spec.rb
|
172
|
+
- spec/spec_helper.rb
|
173
|
+
- spec/support/file_setup.rb
|
174
|
+
- spec/support/rails_stubs.rb
|