sprig 0.1.6 → 0.3.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 +5 -5
- data/README.md +61 -10
- data/lib/generators/sprig/install_generator.rb +5 -1
- data/lib/sprig.rb +21 -0
- data/lib/sprig/configuration.rb +19 -2
- data/lib/sprig/directive.rb +3 -3
- data/lib/sprig/helpers.rb +15 -3
- data/lib/sprig/planter.rb +1 -1
- data/lib/sprig/process_notifier.rb +4 -4
- data/lib/sprig/seed/attribute.rb +27 -3
- data/lib/sprig/seed/entry.rb +8 -4
- data/lib/sprig/seed/factory.rb +1 -1
- data/lib/sprig/source.rb +10 -1
- data/lib/sprig/version.rb +8 -1
- data/spec/adapters/active_record.rb +34 -0
- data/spec/adapters/mongoid.rb +19 -0
- data/spec/adapters/mongoid.yml +12 -0
- data/spec/feature/configurations_spec.rb +5 -5
- data/spec/fixtures/models/{comment.rb → active_record/comment.rb} +0 -0
- data/spec/fixtures/models/{post.rb → active_record/post.rb} +0 -0
- data/spec/fixtures/models/{tag.rb → active_record/tag.rb} +0 -0
- data/spec/fixtures/models/{user.rb → active_record/user.rb} +0 -0
- data/spec/fixtures/models/mongoid/comment.rb +9 -0
- data/spec/fixtures/models/mongoid/post.rb +18 -0
- data/spec/fixtures/models/mongoid/tag.rb +7 -0
- data/spec/fixtures/models/mongoid/user.rb +9 -0
- data/spec/fixtures/seeds/shared/comments.yml +4 -0
- data/spec/fixtures/seeds/shared/files/cat.png +0 -0
- data/spec/fixtures/seeds/shared/invalid_users.yml +4 -0
- data/spec/fixtures/seeds/shared/legacy_posts.yml +4 -0
- data/spec/fixtures/seeds/shared/posts.csv +2 -0
- data/spec/fixtures/seeds/shared/posts.json +1 -0
- data/spec/fixtures/seeds/shared/posts.md +5 -0
- data/spec/fixtures/seeds/shared/posts.yml +4 -0
- data/spec/fixtures/seeds/shared/posts_delete_existing_by.yml +7 -0
- data/spec/fixtures/seeds/shared/posts_find_existing_by_missing.yml +7 -0
- data/spec/fixtures/seeds/shared/posts_find_existing_by_multiple.yml +8 -0
- data/spec/fixtures/seeds/shared/posts_find_existing_by_single.yml +7 -0
- data/spec/fixtures/seeds/shared/posts_missing_dependency.yml +5 -0
- data/spec/fixtures/seeds/shared/posts_missing_record.yml +5 -0
- data/spec/fixtures/seeds/shared/posts_partially_dynamic_value.yml +4 -0
- data/spec/fixtures/seeds/shared/posts_with_cyclic_dependencies.yml +4 -0
- data/spec/fixtures/seeds/shared/posts_with_files.yml +5 -0
- data/spec/fixtures/seeds/shared/posts_with_habtm.yml +7 -0
- data/spec/fixtures/seeds/shared/tags.yml +5 -0
- data/spec/fixtures/seeds/test/posts_partially_dynamic_value.yml +4 -0
- data/spec/lib/generators/sprig/install_generator_spec.rb +6 -2
- data/spec/lib/sprig/configuration_spec.rb +6 -6
- data/spec/lib/sprig/directive_list_spec.rb +4 -4
- data/spec/lib/sprig/directive_spec.rb +21 -11
- data/spec/lib/sprig/null_record_spec.rb +2 -2
- data/spec/lib/sprig/parser/base_spec.rb +1 -1
- data/spec/lib/sprig/process_notifier_spec.rb +5 -3
- data/spec/lib/sprig/seed/entry_spec.rb +3 -3
- data/spec/lib/sprig/seed/record_spec.rb +3 -3
- data/spec/lib/sprig/source_spec.rb +2 -2
- data/spec/lib/sprig_spec.rb +59 -8
- data/spec/spec_helper.rb +35 -31
- data/spec/sprig_shared_spec.rb +467 -0
- data/spec/sprig_spec.rb +105 -34
- data/spec/support/helpers/logger_mock.rb +2 -1
- metadata +167 -87
- data/lib/sprig/data.rb +0 -6
- data/spec/db/activerecord.db +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Sprig::NullRecord do
|
3
|
+
RSpec.describe Sprig::NullRecord do
|
4
4
|
let(:error_msg) { 'Something bad happened.' }
|
5
5
|
subject { described_class.new(error_msg) }
|
6
6
|
|
@@ -14,7 +14,7 @@ describe Sprig::NullRecord do
|
|
14
14
|
|
15
15
|
describe "#method_missing" do
|
16
16
|
it "returns nil for undefined method calls" do
|
17
|
-
subject.enhance_your_calm.
|
17
|
+
expect(subject.enhance_your_calm).to eq(nil)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Sprig::ProcessNotifier do
|
3
|
+
RSpec.describe Sprig::ProcessNotifier do
|
4
4
|
it_behaves_like "a logging entity" do
|
5
5
|
subject { described_class.new }
|
6
6
|
end
|
@@ -79,10 +79,12 @@ describe Sprig::ProcessNotifier do
|
|
79
79
|
end
|
80
80
|
|
81
81
|
describe "#in_progress" do
|
82
|
+
let(:seed) { Sprig::Seed::Entry.new(Post, { title: "Hello World!", content: "Stuff", sprig_id: 1 }, {}) }
|
83
|
+
|
82
84
|
it "logs an in-progress message" do
|
83
|
-
log_should_receive(:debug, with: "Planting
|
85
|
+
log_should_receive(:debug, with: "Planting Post with sprig_id 1")
|
84
86
|
|
85
|
-
subject.in_progress
|
87
|
+
subject.in_progress(seed)
|
86
88
|
end
|
87
89
|
end
|
88
90
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Sprig::Seed::Entry do
|
3
|
+
RSpec.describe Sprig::Seed::Entry do
|
4
4
|
describe ".success_log_text" do
|
5
5
|
context "on a new record" do
|
6
6
|
it "indicates the record was 'saved'" do
|
7
7
|
subject = described_class.new(Post, { title: "Hello World!", content: "Stuff", sprig_id: 1 }, {})
|
8
8
|
subject.save_record
|
9
9
|
|
10
|
-
subject.success_log_text.
|
10
|
+
expect(subject.success_log_text).to eq("Saved")
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -24,7 +24,7 @@ describe Sprig::Seed::Entry do
|
|
24
24
|
subject = described_class.new(Post, { title: "Existing title", content: "Existing content", sprig_id: 1 }, { find_existing_by: [:title] })
|
25
25
|
subject.save_record
|
26
26
|
|
27
|
-
subject.success_log_text.
|
27
|
+
expect(subject.success_log_text).to eq("Updated")
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Sprig::Seed::Record do
|
3
|
+
RSpec.describe Sprig::Seed::Record do
|
4
4
|
describe ".existing?" do
|
5
5
|
let!(:existing) do
|
6
6
|
Post.create(
|
@@ -13,13 +13,13 @@ describe Sprig::Seed::Record do
|
|
13
13
|
it "returns true if the record has already been saved to the database" do
|
14
14
|
subject = described_class.new_or_existing(Post, { title: "Existing title" }, { title: "Existing title" })
|
15
15
|
|
16
|
-
subject.existing
|
16
|
+
expect(subject.existing?).to eq(true)
|
17
17
|
end
|
18
18
|
|
19
19
|
it "returns false if the record is new" do
|
20
20
|
subject = described_class.new_or_existing(Post, { title: "New title" }, { title: "New title" })
|
21
21
|
|
22
|
-
subject.existing
|
22
|
+
expect(subject.existing?).to eq(false)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Sprig::NullRecord do
|
3
|
+
RSpec.describe Sprig::NullRecord do
|
4
4
|
let(:error_msg) { 'Something bad happened.' }
|
5
5
|
subject { described_class.new(error_msg) }
|
6
6
|
|
@@ -14,7 +14,7 @@ describe Sprig::NullRecord do
|
|
14
14
|
|
15
15
|
describe "#method_missing" do
|
16
16
|
it "returns nil for undefined method calls" do
|
17
|
-
subject.enhance_your_calm.
|
17
|
+
expect(subject.enhance_your_calm).to eq(nil)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/spec/lib/sprig_spec.rb
CHANGED
@@ -1,16 +1,67 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Sprig do
|
3
|
+
RSpec.describe Sprig do
|
4
4
|
let(:configuration) { double('Configuration') }
|
5
5
|
|
6
6
|
before do
|
7
|
-
Sprig::Configuration.
|
7
|
+
allow(Sprig::Configuration).to receive(:new).and_return(configuration)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.adapter' do
|
11
|
+
it { expect(described_class).to respond_to(:adapter).with(0).arguments }
|
12
|
+
|
13
|
+
it { expect(described_class.adapter).not_to be nil }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.adapter=' do
|
17
|
+
let(:value) { :mongo_mapper }
|
18
|
+
|
19
|
+
around(:each) do |example|
|
20
|
+
previous_value = described_class.adapter
|
21
|
+
|
22
|
+
example.run
|
23
|
+
|
24
|
+
described_class.adapter = previous_value
|
25
|
+
end
|
26
|
+
|
27
|
+
it { expect(described_class).to respond_to(:adapter=).with(1).argument }
|
28
|
+
|
29
|
+
it 'changes the value' do
|
30
|
+
expect { described_class.adapter = value }.to change(described_class, :adapter).to(value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.adapter_model_class' do
|
35
|
+
let(:expected_class) do
|
36
|
+
case Sprig.adapter
|
37
|
+
when :active_record
|
38
|
+
ActiveRecord::Base
|
39
|
+
when :mongoid
|
40
|
+
Mongoid::Document
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
before(:each) { described_class.instance_variable_set(:@adapter_model_class, nil) }
|
45
|
+
|
46
|
+
it { expect(described_class).to respond_to(:adapter_model_class).with(0).arguments }
|
47
|
+
|
48
|
+
it { expect(described_class.adapter_model_class).to be expected_class }
|
49
|
+
|
50
|
+
describe 'with an unrecognized adapter' do
|
51
|
+
let(:value) { :mongo_mapper }
|
52
|
+
|
53
|
+
it 'raises an error' do
|
54
|
+
allow(described_class).to receive(:adapter).and_return(value)
|
55
|
+
|
56
|
+
expect { described_class.adapter_model_class }.to raise_error(/unknown model class/i)
|
57
|
+
end
|
58
|
+
end
|
8
59
|
end
|
9
60
|
|
10
61
|
describe ".configuration" do
|
11
62
|
context "when there is not yet a Configuration instance" do
|
12
63
|
it "returns a new Configuration instance" do
|
13
|
-
described_class.configuration.
|
64
|
+
expect(described_class.configuration).to eq(configuration)
|
14
65
|
end
|
15
66
|
end
|
16
67
|
|
@@ -21,9 +72,9 @@ describe Sprig do
|
|
21
72
|
|
22
73
|
it "returns the existing Configuration instance" do
|
23
74
|
new_configuration = double('Configuration')
|
24
|
-
Sprig::Configuration.
|
75
|
+
allow(Sprig::Configuration).to receive(:new).and_return(new_configuration)
|
25
76
|
|
26
|
-
described_class.configuration.
|
77
|
+
expect(described_class.configuration).to eq(configuration)
|
27
78
|
end
|
28
79
|
end
|
29
80
|
end
|
@@ -36,16 +87,16 @@ describe Sprig do
|
|
36
87
|
it "clears the existing configuration" do
|
37
88
|
described_class.reset_configuration
|
38
89
|
new_configuration = double('Configuration')
|
39
|
-
Sprig::Configuration.
|
90
|
+
allow(Sprig::Configuration).to receive(:new).and_return(new_configuration)
|
40
91
|
|
41
|
-
described_class.configuration.
|
92
|
+
expect(described_class.configuration).to eq(new_configuration)
|
42
93
|
end
|
43
94
|
end
|
44
95
|
|
45
96
|
describe ".configure" do
|
46
97
|
it "yields the configuration" do
|
47
98
|
described_class.configure do |config|
|
48
|
-
config.
|
99
|
+
expect(config).to eq(configuration)
|
49
100
|
end
|
50
101
|
end
|
51
102
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,8 +7,6 @@ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
|
7
7
|
SimpleCov.start "rails"
|
8
8
|
|
9
9
|
require "rails"
|
10
|
-
require "active_record"
|
11
|
-
require "database_cleaner"
|
12
10
|
require "webmock"
|
13
11
|
require "vcr"
|
14
12
|
require "pry"
|
@@ -17,25 +15,21 @@ require "generator_spec"
|
|
17
15
|
require "sprig"
|
18
16
|
include Sprig::Helpers
|
19
17
|
|
20
|
-
Dir[File.dirname(__FILE__) + '/fixtures/models/*.rb'].each {|file| require file }
|
21
18
|
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|file| require file}
|
22
19
|
|
23
20
|
RSpec.configure do |c|
|
24
21
|
c.include ColoredText
|
25
22
|
c.include LoggerMock
|
26
23
|
|
27
|
-
c.
|
28
|
-
|
29
|
-
|
30
|
-
end
|
24
|
+
c.disable_monkey_patching!
|
25
|
+
|
26
|
+
c.order = :random
|
31
27
|
|
32
|
-
c.
|
33
|
-
|
28
|
+
c.mock_with :rspec do |mocks|
|
29
|
+
mocks.verify_partial_doubles = true
|
34
30
|
end
|
35
31
|
|
36
32
|
c.after(:each) do
|
37
|
-
DatabaseCleaner.clean
|
38
|
-
|
39
33
|
Sprig.reset_configuration
|
40
34
|
end
|
41
35
|
end
|
@@ -46,51 +40,61 @@ VCR.configure do |c|
|
|
46
40
|
c.hook_into :webmock
|
47
41
|
end
|
48
42
|
|
49
|
-
#
|
50
|
-
|
43
|
+
# ActiveRecord (via SQlite3)
|
44
|
+
begin
|
45
|
+
require 'active_record'
|
46
|
+
require 'sqlite3'
|
51
47
|
|
52
|
-
|
53
|
-
|
48
|
+
Sprig.adapter = :active_record
|
49
|
+
rescue LoadError; end
|
54
50
|
|
55
|
-
|
56
|
-
|
51
|
+
# Mongoid
|
52
|
+
begin
|
53
|
+
require 'mongoid'
|
57
54
|
|
58
|
-
|
59
|
-
|
55
|
+
Sprig.adapter = :mongoid
|
56
|
+
rescue LoadError; end
|
60
57
|
|
61
|
-
|
62
|
-
|
58
|
+
# Require model files.
|
59
|
+
Dir[File.dirname(__FILE__) + "/fixtures/models/#{Sprig.adapter}/*.rb"].each {|file| require file}
|
63
60
|
|
64
|
-
|
65
|
-
Tag.connection.execute "CREATE TABLE posts_tags (id INTEGER PRIMARY KEY , post_id INTEGER, tag_id INTEGER);"
|
61
|
+
require "adapters/#{Sprig.adapter}.rb"
|
66
62
|
|
67
63
|
# Helpers
|
68
64
|
#
|
69
65
|
# Setup fake `Rails.root`
|
70
66
|
def stub_rails_root(path='./spec/fixtures')
|
71
|
-
Rails.
|
67
|
+
allow(Rails).to receive(:root).and_return(Pathname.new(path))
|
72
68
|
end
|
73
69
|
|
74
70
|
# Setup fake `Rails.env`
|
75
71
|
def stub_rails_env(env='development')
|
76
|
-
Rails.
|
72
|
+
allow(Rails).to receive(:env).and_return(env)
|
77
73
|
end
|
78
74
|
|
79
75
|
# Copy and Remove Seed files around a spec
|
80
|
-
def load_seeds(*files)
|
76
|
+
def load_seeds(*files, &block)
|
81
77
|
env = Rails.env
|
78
|
+
prepare_seeds(env, *files, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Copy and Remove shared seed files around a spec
|
82
|
+
def load_shared_seeds(*files, &block)
|
83
|
+
prepare_seeds('shared', *files, &block)
|
84
|
+
end
|
82
85
|
|
83
|
-
|
86
|
+
def prepare_seeds(directory, *files, &block)
|
87
|
+
`cp -R ./spec/fixtures/seeds/#{directory}/files ./spec/fixtures/db/seeds/#{directory}`
|
84
88
|
|
85
89
|
files.each do |file|
|
86
|
-
`cp ./spec/fixtures/seeds/#{
|
90
|
+
`cp ./spec/fixtures/seeds/#{directory}/#{file} ./spec/fixtures/db/seeds/#{directory}`
|
87
91
|
end
|
88
92
|
|
89
|
-
|
93
|
+
block.call
|
90
94
|
|
91
|
-
`rm -R ./spec/fixtures/db/seeds/#{
|
95
|
+
`rm -R ./spec/fixtures/db/seeds/#{directory}/files`
|
92
96
|
|
93
97
|
files.each do |file|
|
94
|
-
`rm ./spec/fixtures/db/seeds/#{
|
98
|
+
`rm ./spec/fixtures/db/seeds/#{directory}/#{file}`
|
95
99
|
end
|
96
100
|
end
|
@@ -0,0 +1,467 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
RSpec.describe "Seeding an application with shared seeds" do
|
5
|
+
let(:missing_record_error) do
|
6
|
+
if defined?(ActiveRecord) && Post < ActiveRecord::Base
|
7
|
+
ActiveRecord::RecordNotFound
|
8
|
+
elsif defined?(Mongoid) && Post < Mongoid::Document
|
9
|
+
Mongoid::Errors::DocumentNotFound
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
stub_rails_root
|
15
|
+
end
|
16
|
+
|
17
|
+
context "with a yaml file" do
|
18
|
+
around do |example|
|
19
|
+
load_shared_seeds('posts.yml', &example)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "seeds the db" do
|
23
|
+
sprig_shared [Post]
|
24
|
+
|
25
|
+
expect(Post.count).to eq(1)
|
26
|
+
expect(Post.pluck(:title)).to eq(['Yaml title'])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with a csv file" do
|
31
|
+
around do |example|
|
32
|
+
load_shared_seeds('posts.csv', &example)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "seeds the db" do
|
36
|
+
sprig_shared [Post]
|
37
|
+
|
38
|
+
expect(Post.count).to eq(1)
|
39
|
+
expect(Post.pluck(:title)).to eq(['Csv title'])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with a json file" do
|
44
|
+
around do |example|
|
45
|
+
load_shared_seeds('posts.json', &example)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "seeds the db" do
|
49
|
+
sprig_shared [Post]
|
50
|
+
|
51
|
+
expect(Post.count).to eq(1)
|
52
|
+
expect(Post.pluck(:title)).to eq(['Json title'])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "with a partially-dynamic value" do
|
57
|
+
around do |example|
|
58
|
+
load_shared_seeds('posts_partially_dynamic_value.yml', &example)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "seeds the db with the full value" do
|
62
|
+
sprig_shared [
|
63
|
+
{
|
64
|
+
:class => Post,
|
65
|
+
:source => open('spec/fixtures/seeds/shared/posts_partially_dynamic_value.yml')
|
66
|
+
}
|
67
|
+
]
|
68
|
+
|
69
|
+
expect(Post.count).to eq(1)
|
70
|
+
expect(Post.pluck(:title)).to eq(['Partially Dynamic Title'])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "with a symlinked file" do
|
75
|
+
around do |example|
|
76
|
+
`ln -s ./spec/fixtures/seeds/shared/posts.yml ./spec/fixtures/db/seeds/shared/`
|
77
|
+
example.call
|
78
|
+
`rm ./spec/fixtures/db/seeds/shared/posts.yml`
|
79
|
+
end
|
80
|
+
|
81
|
+
it "seeds the db" do
|
82
|
+
sprig_shared [Post]
|
83
|
+
|
84
|
+
expect(Post.count).to eq(1)
|
85
|
+
expect(Post.pluck(:title)).to eq(['Yaml title'])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "with a google spreadsheet" do
|
90
|
+
it "seeds the db", :vcr => { :cassette_name => 'google_spreadsheet_json_posts' } do
|
91
|
+
sprig_shared [
|
92
|
+
{
|
93
|
+
:class => Post,
|
94
|
+
:parser => Sprig::Parser::GoogleSpreadsheetJson,
|
95
|
+
:source => open('https://spreadsheets.google.com/feeds/list/0AjVLPMnHm86rdDVHQ2dCUS03RTN5ZUtVNzVOYVBwT0E/1/public/values?alt=json'),
|
96
|
+
}
|
97
|
+
]
|
98
|
+
|
99
|
+
expect(Post.count).to eq(1)
|
100
|
+
expect(Post.pluck(:title)).to eq(['Google spreadsheet json title'])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "with an invalid custom parser" do
|
105
|
+
around do |example|
|
106
|
+
load_shared_seeds('posts.yml', &example)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "fails with an argument error" do
|
110
|
+
expect {
|
111
|
+
sprig_shared [
|
112
|
+
{
|
113
|
+
:class => Post,
|
114
|
+
:source => open('spec/fixtures/seeds/shared/posts.yml'),
|
115
|
+
:parser => Object # Not a valid parser
|
116
|
+
}
|
117
|
+
]
|
118
|
+
}.to raise_error(ArgumentError, 'Parsers must define #parse.')
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "with a custom source" do
|
123
|
+
around do |example|
|
124
|
+
load_shared_seeds('legacy_posts.yml', &example)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "seeds" do
|
128
|
+
sprig_shared [
|
129
|
+
{
|
130
|
+
:class => Post,
|
131
|
+
:source => open('spec/fixtures/seeds/shared/legacy_posts.yml')
|
132
|
+
}
|
133
|
+
]
|
134
|
+
|
135
|
+
expect(Post.count).to eq(1)
|
136
|
+
expect(Post.pluck(:title)).to eq(['Legacy yaml title'])
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "with a custom source that cannot be parsed by native parsers" do
|
141
|
+
around do |example|
|
142
|
+
load_shared_seeds('posts.md', &example)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "fails with an unparsable file error" do
|
146
|
+
expect {
|
147
|
+
sprig_shared [
|
148
|
+
{
|
149
|
+
:class => Post,
|
150
|
+
:source => open('spec/fixtures/seeds/shared/posts.md')
|
151
|
+
}
|
152
|
+
]
|
153
|
+
}.to raise_error(Sprig::Source::ParserDeterminer::UnparsableFileError)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context "with an invalid custom source" do
|
158
|
+
it "fails with an argument error" do
|
159
|
+
expect {
|
160
|
+
sprig_shared [ { :class => Post, :source => 42 } ]
|
161
|
+
}.to raise_error(ArgumentError, 'Data sources must act like an IO.')
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context "with multiple file relationships" do
|
166
|
+
around do |example|
|
167
|
+
load_shared_seeds('posts.yml', 'comments.yml', &example)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "seeds the db" do
|
171
|
+
sprig_shared [Post, Comment]
|
172
|
+
|
173
|
+
expect(Post.count).to eq(1)
|
174
|
+
expect(Comment.count).to eq(1)
|
175
|
+
expect(Comment.first.post).to eq(Post.first)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "with missing seed files" do
|
180
|
+
it "raises a missing file error" do
|
181
|
+
expect {
|
182
|
+
sprig_shared [Post]
|
183
|
+
}.to raise_error(Sprig::Source::SourceDeterminer::FileNotFoundError)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "with a relationship to an undefined record" do
|
188
|
+
around do |example|
|
189
|
+
load_shared_seeds('posts.yml', 'posts_missing_dependency.yml', &example)
|
190
|
+
end
|
191
|
+
|
192
|
+
it "raises a helpful error message" do
|
193
|
+
expect {
|
194
|
+
sprig_shared [
|
195
|
+
{
|
196
|
+
:class => Post,
|
197
|
+
:source => open('spec/fixtures/seeds/shared/posts_missing_dependency.yml')
|
198
|
+
}
|
199
|
+
]
|
200
|
+
}.to raise_error(
|
201
|
+
Sprig::DependencySorter::MissingDependencyError,
|
202
|
+
"Undefined reference to 'sprig_record(Comment, 42)'"
|
203
|
+
)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "with a relationship to a record that didn't save" do
|
208
|
+
around do |example|
|
209
|
+
load_shared_seeds('invalid_users.yml', 'posts_missing_record.yml', &example)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "does not error, but carries on with the seeding" do
|
213
|
+
expect {
|
214
|
+
sprig_shared [
|
215
|
+
{
|
216
|
+
:class => Post,
|
217
|
+
:source => open('spec/fixtures/seeds/shared/posts_missing_record.yml')
|
218
|
+
},
|
219
|
+
{
|
220
|
+
:class => User,
|
221
|
+
:source => open('spec/fixtures/seeds/shared/invalid_users.yml')
|
222
|
+
}
|
223
|
+
]
|
224
|
+
}.to_not raise_error
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context "with multiple files for a class" do
|
229
|
+
around do |example|
|
230
|
+
load_shared_seeds('posts.yml', 'legacy_posts.yml', &example)
|
231
|
+
end
|
232
|
+
|
233
|
+
it "seeds the db" do
|
234
|
+
sprig_shared [
|
235
|
+
Post,
|
236
|
+
{
|
237
|
+
:class => Post,
|
238
|
+
:source => open('spec/fixtures/seeds/shared/legacy_posts.yml')
|
239
|
+
}
|
240
|
+
]
|
241
|
+
|
242
|
+
expect(Post.count).to eq(2)
|
243
|
+
expect(Post.pluck(:title)).to eq(['Yaml title', 'Legacy yaml title'])
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context "with files defined as attributes" do
|
248
|
+
around do |example|
|
249
|
+
load_shared_seeds('posts_with_files.yml', &example)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "seeds the db" do
|
253
|
+
sprig_shared [
|
254
|
+
{
|
255
|
+
:class => Post,
|
256
|
+
:source => open('spec/fixtures/seeds/shared/posts_with_files.yml')
|
257
|
+
}
|
258
|
+
]
|
259
|
+
|
260
|
+
expect(Post.count).to eq(1)
|
261
|
+
expect(Post.pluck(:photo)).to eq(['cat.png'])
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context "with has_and_belongs_to_many relationships" do
|
266
|
+
around do |example|
|
267
|
+
load_shared_seeds('posts_with_habtm.yml', 'tags.yml', &example)
|
268
|
+
end
|
269
|
+
|
270
|
+
it "saves the habtm relationships" do
|
271
|
+
sprig_shared [
|
272
|
+
Tag,
|
273
|
+
{
|
274
|
+
:class => Post,
|
275
|
+
:source => open('spec/fixtures/seeds/shared/posts_with_habtm.yml')
|
276
|
+
}
|
277
|
+
]
|
278
|
+
|
279
|
+
expect(Post.first.tags.map(&:name)).to eq(['Botany', 'Biology'])
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context "with cyclic dependencies" do
|
284
|
+
around do |example|
|
285
|
+
load_shared_seeds('comments.yml', 'posts_with_cyclic_dependencies.yml', &example)
|
286
|
+
end
|
287
|
+
|
288
|
+
it "raises an cyclic dependency error" do
|
289
|
+
expect {
|
290
|
+
sprig_shared [
|
291
|
+
{
|
292
|
+
:class => Post,
|
293
|
+
:source => open('spec/fixtures/seeds/shared/posts_with_cyclic_dependencies.yml')
|
294
|
+
},
|
295
|
+
Comment
|
296
|
+
]
|
297
|
+
}.to raise_error(Sprig::DependencySorter::CircularDependencyError)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context "with a malformed directive" do
|
302
|
+
let(:expected_error_message) { "Sprig::Directive must be instantiated with a(n) #{Sprig.adapter_model_class} class or a Hash with :class defined" }
|
303
|
+
|
304
|
+
context "including a class that is not a subclass of AR" do
|
305
|
+
it "raises an argument error" do
|
306
|
+
expect {
|
307
|
+
sprig_shared [
|
308
|
+
Object
|
309
|
+
]
|
310
|
+
}.to raise_error(ArgumentError, expected_error_message)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context "including a non-class, non-hash" do
|
315
|
+
it "raises an argument error" do
|
316
|
+
expect {
|
317
|
+
sprig_shared [
|
318
|
+
42
|
319
|
+
]
|
320
|
+
}.to raise_error(ArgumentError, expected_error_message)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
|
326
|
+
context "with custom seed options" do
|
327
|
+
context "using delete_existing_by" do
|
328
|
+
around do |example|
|
329
|
+
load_shared_seeds('posts_delete_existing_by.yml', &example)
|
330
|
+
end
|
331
|
+
|
332
|
+
context "with an existing record" do
|
333
|
+
let!(:existing_match) do
|
334
|
+
Post.create(
|
335
|
+
:title => "Such Title",
|
336
|
+
:content => "Old Content")
|
337
|
+
end
|
338
|
+
|
339
|
+
let!(:existing_nonmatch) do
|
340
|
+
Post.create(
|
341
|
+
:title => "Wow Title",
|
342
|
+
:content => "Much Content")
|
343
|
+
end
|
344
|
+
|
345
|
+
it "replaces only the matching existing record" do
|
346
|
+
sprig_shared [
|
347
|
+
{
|
348
|
+
:class => Post,
|
349
|
+
:source => open("spec/fixtures/seeds/shared/posts_delete_existing_by.yml")
|
350
|
+
}
|
351
|
+
]
|
352
|
+
|
353
|
+
expect(Post.count).to eq(2)
|
354
|
+
|
355
|
+
expect {
|
356
|
+
existing_match.reload
|
357
|
+
}.to raise_error(missing_record_error)
|
358
|
+
|
359
|
+
expect {
|
360
|
+
existing_nonmatch.reload
|
361
|
+
}.to_not raise_error
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
context "using find_existing_by" do
|
367
|
+
context "with a missing attribute" do
|
368
|
+
around do |example|
|
369
|
+
load_shared_seeds('posts_find_existing_by_missing.yml', &example)
|
370
|
+
end
|
371
|
+
|
372
|
+
it "raises a missing attribute error" do
|
373
|
+
expect {
|
374
|
+
sprig_shared [
|
375
|
+
{
|
376
|
+
:class => Post,
|
377
|
+
:source => open("spec/fixtures/seeds/shared/posts_find_existing_by_missing.yml")
|
378
|
+
}
|
379
|
+
]
|
380
|
+
}.to raise_error(Sprig::Seed::AttributeCollection::AttributeNotFoundError, "Attribute 'unicorn' is not present.")
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
context "with a single attribute" do
|
385
|
+
around do |example|
|
386
|
+
load_shared_seeds('posts.yml', 'posts_find_existing_by_single.yml', &example)
|
387
|
+
end
|
388
|
+
|
389
|
+
context "with an existing record" do
|
390
|
+
let!(:existing) do
|
391
|
+
Post.create(
|
392
|
+
:title => "Existing title",
|
393
|
+
:content => "Existing content")
|
394
|
+
end
|
395
|
+
|
396
|
+
it "updates the existing record" do
|
397
|
+
sprig_shared [
|
398
|
+
{
|
399
|
+
:class => Post,
|
400
|
+
:source => open("spec/fixtures/seeds/shared/posts_find_existing_by_single.yml")
|
401
|
+
}
|
402
|
+
]
|
403
|
+
|
404
|
+
expect(Post.count).to eq(1)
|
405
|
+
expect(existing.reload.content).to eq("Updated content")
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
context "with multiple attributes" do
|
411
|
+
around do |example|
|
412
|
+
load_shared_seeds('posts.yml', 'posts_find_existing_by_multiple.yml', &example)
|
413
|
+
end
|
414
|
+
|
415
|
+
context "with an existing record" do
|
416
|
+
let!(:existing) do
|
417
|
+
Post.create(
|
418
|
+
:title => "Existing title",
|
419
|
+
:content => "Existing content",
|
420
|
+
:published => false
|
421
|
+
)
|
422
|
+
end
|
423
|
+
|
424
|
+
it "updates the existing record" do
|
425
|
+
sprig_shared [
|
426
|
+
{
|
427
|
+
:class => Post,
|
428
|
+
:source => open("spec/fixtures/seeds/shared/posts_find_existing_by_multiple.yml")
|
429
|
+
}
|
430
|
+
]
|
431
|
+
|
432
|
+
expect(Post.count).to eq(1)
|
433
|
+
expect(existing.reload.published).to eq(true)
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
context "defined within the directive" do
|
440
|
+
let!(:existing) do
|
441
|
+
Post.create(
|
442
|
+
:title => "Yaml title",
|
443
|
+
:content => "Existing content")
|
444
|
+
end
|
445
|
+
|
446
|
+
around do |example|
|
447
|
+
load_shared_seeds('posts.yml', &example)
|
448
|
+
end
|
449
|
+
|
450
|
+
it "respects the directive option" do
|
451
|
+
sprig_shared [
|
452
|
+
{
|
453
|
+
:class => Post,
|
454
|
+
:source => open("spec/fixtures/seeds/shared/posts.yml"),
|
455
|
+
:delete_existing_by => :title
|
456
|
+
}
|
457
|
+
]
|
458
|
+
|
459
|
+
expect(Post.count).to eq(1)
|
460
|
+
|
461
|
+
expect {
|
462
|
+
existing.reload
|
463
|
+
}.to raise_error(missing_record_error)
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|