datapathy 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +7 -0
- data/.rspec +3 -0
- data/Gemfile +6 -0
- data/LICENSE +20 -0
- data/README.mkd +19 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/benchmarks/attributes.rb +67 -0
- data/benchmarks/initialize.rb +106 -0
- data/benchmarks/query.rb +34 -0
- data/datapathy.gemspec +31 -0
- data/lib/datapathy.rb +37 -0
- data/lib/datapathy/adapters/http_adapter.rb +121 -0
- data/lib/datapathy/collection.rb +123 -0
- data/lib/datapathy/config.rb +0 -0
- data/lib/datapathy/log_subscriber.rb +28 -0
- data/lib/datapathy/model.rb +142 -0
- data/lib/datapathy/model/crud.rb +61 -0
- data/lib/datapathy/model/dynamic_finders.rb +89 -0
- data/lib/datapathy/models/service.rb +6 -0
- data/lib/datapathy/query.rb +141 -0
- data/lib/datapathy/railtie.rb +48 -0
- data/profile/initialize.calltree +62 -0
- data/profile/initialize.rb +28 -0
- data/spec/adapter_api_spec.rb +146 -0
- data/spec/create_spec.rb +71 -0
- data/spec/crud_spec.rb +130 -0
- data/spec/datapathy_spec.rb +20 -0
- data/spec/delete_spec.rb +52 -0
- data/spec/find_by_spec.rb +24 -0
- data/spec/find_or_create_spec.rb +38 -0
- data/spec/integration/service_spec.rb +22 -0
- data/spec/query_spec.rb +89 -0
- data/spec/read_spec.rb +67 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/datapathy_test_app.rb +33 -0
- data/spec/support/matchers.rb +30 -0
- data/spec/support/models.rb +25 -0
- data/spec/update_spec.rb +55 -0
- data/spec/validations_spec.rb +31 -0
- metadata +235 -0
data/spec/crud_spec.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "CRUD API" do
|
4
|
+
before do
|
5
|
+
@record_foo = {:id => new_uuid, :title => "Foo", :text => "foo"}
|
6
|
+
@record_bar = {:id => new_uuid, :title => "Bar", :text => "bar"}
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
test_adapter.clear!
|
11
|
+
end
|
12
|
+
|
13
|
+
share_as :ACollection do
|
14
|
+
it { @result.should be_a(Datapathy::Collection) }
|
15
|
+
it { @result.first.should be_an(Article) }
|
16
|
+
end
|
17
|
+
|
18
|
+
share_as :AnArticle do
|
19
|
+
it { @result.should be_an(Article) }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "New" do
|
23
|
+
|
24
|
+
share_as :NewCollection do
|
25
|
+
it_should_behave_like ACollection
|
26
|
+
it { @result.first.should be_new_record }
|
27
|
+
end
|
28
|
+
|
29
|
+
share_as :NewArticle do
|
30
|
+
it_should_behave_like AnArticle
|
31
|
+
it { @result.should be_new_record }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "Model.new()" do
|
35
|
+
before do
|
36
|
+
@result = Article.new()
|
37
|
+
end
|
38
|
+
it_should_behave_like NewArticle
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "Model.new({})" do
|
42
|
+
before do
|
43
|
+
@result = Article.new(@record_foo)
|
44
|
+
end
|
45
|
+
it_should_behave_like NewArticle
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "Model.new({}, {})" do
|
49
|
+
before do
|
50
|
+
@result = Article.new(@record_foo, @record_bar)
|
51
|
+
end
|
52
|
+
it_should_behave_like NewCollection
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "collection.new()" do
|
56
|
+
before do
|
57
|
+
@result = Article.all.new()
|
58
|
+
end
|
59
|
+
it_should_behave_like NewArticle
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "collection.new({})" do
|
63
|
+
before do
|
64
|
+
@result = Article.all.new(@record_foo)
|
65
|
+
end
|
66
|
+
it_should_behave_like NewArticle
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "collection.new({}, {})" do
|
70
|
+
before do
|
71
|
+
@result = Article.all.new(@record_foo, @record_bar)
|
72
|
+
end
|
73
|
+
it_should_behave_like NewCollection
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "Create" do
|
79
|
+
|
80
|
+
share_as :CreatedCollection do
|
81
|
+
it { @result.first.should_not be_new_record }
|
82
|
+
it_should_behave_like ACollection
|
83
|
+
end
|
84
|
+
|
85
|
+
share_as :CreatedArticle do
|
86
|
+
it { @result.should_not be_new_record }
|
87
|
+
it_should_behave_like AnArticle
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "Model.create({})" do
|
91
|
+
before { @result = Article.create(@record_foo) }
|
92
|
+
it_should_behave_like CreatedArticle
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "Model.create({}, {})" do
|
96
|
+
before { @result = Article.create(@record_foo, @record_bar) }
|
97
|
+
it_should_behave_like CreatedCollection
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "collection.create({})" do
|
101
|
+
before do
|
102
|
+
@result = Article.all.create(@record_foo)
|
103
|
+
end
|
104
|
+
it_should_behave_like CreatedArticle
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "collection.create({}, {})" do
|
108
|
+
before do
|
109
|
+
@result = Article.all.create(@record_foo, @record_bar)
|
110
|
+
end
|
111
|
+
it_should_behave_like CreatedCollection
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "existing_collection.create" do
|
115
|
+
describe "one" do
|
116
|
+
before do
|
117
|
+
@result = Datapathy::Collection.new(Article, @record_foo).create
|
118
|
+
end
|
119
|
+
it_should_behave_like CreatedArticle
|
120
|
+
end
|
121
|
+
describe "many" do
|
122
|
+
before do
|
123
|
+
@result = Datapathy::Collection.new(Article, @record_foo, @record_bar).create
|
124
|
+
end
|
125
|
+
it_should_behave_like CreatedCollection
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
class MyModel
|
4
|
+
include Datapathy::Model
|
5
|
+
|
6
|
+
persists :id
|
7
|
+
persists :name
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "Datapathy" do
|
11
|
+
|
12
|
+
def uuid
|
13
|
+
UUIDTools::UUID.random_create.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should have attributes' do
|
17
|
+
MyModel.persisted_attributes.should == [:id, :name]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/spec/delete_spec.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'deleteing models' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@record_a = @record = {:id => new_uuid, :title => "Datapathy is amazing!", :text => "It really is!"}
|
7
|
+
@record_b = {:id => new_uuid, :title => "Datapathy is awesome!", :text => "Try it today!"}
|
8
|
+
@record_c = {:id => new_uuid, :title => "Datapathy is awesome!", :text => "Title is same, but text is different"}
|
9
|
+
|
10
|
+
@records = [@record_a, @record_b, @record_c]
|
11
|
+
@records.each do |record|
|
12
|
+
test_adapter.datastore[Article][record[:id]] = record
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
test_adapter.clear!
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'one at a time' do
|
21
|
+
before do
|
22
|
+
Article[@record[:id]].delete
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should remove the record' do
|
26
|
+
lambda {
|
27
|
+
Article[@record[:id]]
|
28
|
+
}.should raise_error(Datapathy::RecordNotFound)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should not delete other records' do
|
32
|
+
Article[@record_b[:id]].should_not be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'in bulk' do
|
37
|
+
before do
|
38
|
+
Article.delete { |a| a.title == @record_b[:title] }
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should remove the record(s)' do
|
42
|
+
Article.select { |a| a.title == @record_b[:title] }.should be_empty
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should not remove other records' do
|
46
|
+
Article.detect { |a| a.id == @record[:id] }.should_not be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Model.find_by_foo" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@article = Article.create(:id => new_uuid,
|
7
|
+
:title => "FooBar",
|
8
|
+
:text => "Original text")
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should find one' do
|
12
|
+
article = Article.find_by_title("FooBar")
|
13
|
+
|
14
|
+
article.text.should == "Original text"
|
15
|
+
end
|
16
|
+
|
17
|
+
after do
|
18
|
+
test_adapter.clear!
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Model.find_or_create_by_foo" do
|
4
|
+
|
5
|
+
describe "record exists" do
|
6
|
+
before do
|
7
|
+
@article = Article.create(:id => new_uuid,
|
8
|
+
:title => "FooBar",
|
9
|
+
:text => "Original text")
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should find it' do
|
13
|
+
article = Article.find_or_create_by_title(:title => "FooBar",
|
14
|
+
:text => "New text")
|
15
|
+
|
16
|
+
article.text.should_not == "New text"
|
17
|
+
article.text.should == "Original text"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "record missing" do
|
22
|
+
|
23
|
+
it 'should create it' do
|
24
|
+
article = Article.find_or_create_by_title(:title => "FooBar",
|
25
|
+
:text => "New text")
|
26
|
+
|
27
|
+
article.text.should == "New text"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
after do
|
33
|
+
test_adapter.clear!
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "top-level service" do
|
4
|
+
before do
|
5
|
+
Datapathy.configure do |config|
|
6
|
+
config.services_uri = "http://datapathy.dev/"
|
7
|
+
end
|
8
|
+
|
9
|
+
Artifice.activate_with(DatapathyTestApp)
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
Artifice.deactivate
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should work" do
|
17
|
+
services = Service.all
|
18
|
+
services.size.should == 2
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
data/spec/query_spec.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'active_support/core_ext/array/wrap'
|
4
|
+
|
5
|
+
require 'active_support/core_ext/numeric/time'
|
6
|
+
require 'active_support/core_ext/object/acts_like'
|
7
|
+
require 'active_support/core_ext/time/acts_like'
|
8
|
+
require 'active_support/core_ext/time/calculations'
|
9
|
+
|
10
|
+
describe 'querying models' do
|
11
|
+
|
12
|
+
before do
|
13
|
+
@record_a = @record = {:id => new_uuid, :title => "Datapathy is amazing!", :text => "It really is!", :published_at => 2.days.ago }
|
14
|
+
@record_b = {:id => new_uuid, :title => "Datapathy is awesome!", :text => "Try it today!", :published_at => 1.day.ago }
|
15
|
+
@record_c = {:id => new_uuid, :title => "Datapathy is awesome!", :text => "Title is same, but text is different", :published_at => 1.minute.ago }
|
16
|
+
|
17
|
+
@records = [@record_a, @record_b, @record_c]
|
18
|
+
@records.each do |record|
|
19
|
+
test_adapter.datastore[Article][record[:id]] = record
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
test_adapter.clear!
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Matchers.define :include_records do |*expected_records|
|
28
|
+
match do |matched_records|
|
29
|
+
@expected_records = expected_records
|
30
|
+
matched_keys = matched_records.map { |r| r.id }
|
31
|
+
expected_keys = expected_records.map { |r| r[:id] }
|
32
|
+
expected_keys.all? { |key| matched_keys.include?(key) }
|
33
|
+
end
|
34
|
+
failure_message_for_should do |matched_records|
|
35
|
+
"Expected #{matched_records.to_a.inspect} to include all of #{@expected_records.inspect}"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '(&blk)' do
|
41
|
+
|
42
|
+
it 'should match ==' do
|
43
|
+
Article.select { |a| a.title == "Datapathy is awesome!" }.
|
44
|
+
should include_records(@record_b, @record_c)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should match chained selects' do
|
48
|
+
Article.select { |a| a.title == "Datapathy is awesome!" }.
|
49
|
+
select { |a| a.text == "Try it today!" }.
|
50
|
+
should include_records(@record_b)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should match >' do
|
54
|
+
Article.select { |a| a.published_at > 1.day.ago }.
|
55
|
+
should include_records(@record_c)
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'limit' do
|
59
|
+
|
60
|
+
it 'should limit records' do
|
61
|
+
pending
|
62
|
+
Article.select { |a| limit 2 }.
|
63
|
+
should include_records(@record_a, @record_b)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '{hash}' do
|
72
|
+
|
73
|
+
before do
|
74
|
+
@articles = Article.select(:title => @record_b[:title])
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should retrieve all matching records' do
|
78
|
+
@articles.should have(2).items
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should retrieve the correct records' do
|
82
|
+
@articles.map { |a| a.id }.should include(@record_b[:id])
|
83
|
+
@articles.map { |a| a.id }.should include(@record_c[:id])
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
data/spec/read_spec.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'reading models' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@record_a = @record = {:id => new_uuid, :title => "Datapathy is amazing!", :text => "It really is!"}
|
7
|
+
@record_b = {:id => new_uuid, :title => "Datapathy is awesome!", :text => "Try it today!"}
|
8
|
+
@record_c = {:id => new_uuid, :title => "Datapathy is awesome!", :text => "Title is same, but text is different"}
|
9
|
+
|
10
|
+
@records = [@record_a, @record_b, @record_c]
|
11
|
+
@records.each do |record|
|
12
|
+
test_adapter.datastore[Article][record[:id]] = record
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
test_adapter.clear!
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'Model.all' do
|
21
|
+
before do
|
22
|
+
@articles = Article.all
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should retrive all records' do
|
26
|
+
@articles.should have(@records.size).items
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'Model.[]' do
|
31
|
+
before do
|
32
|
+
@article = Article[@record[:id]]
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should retrive it by key' do
|
36
|
+
@article.should_not be_nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should load the attributes' do
|
40
|
+
[:id, :title, :text].each do |atr|
|
41
|
+
@article.send(atr).should eql(@record[atr])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should raise an exception if the record is not found' do
|
46
|
+
lambda {
|
47
|
+
@article = Article[new_uuid]
|
48
|
+
}.should raise_error(Datapathy::RecordNotFound)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'Model.detect' do
|
53
|
+
before do
|
54
|
+
@article = Article.detect { |a| a.title == @record_b[:title] }
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should retrieve only one record' do
|
58
|
+
@article.should be_a(Article)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should retrieve the correct record' do
|
62
|
+
@article.title.should eql(@record_b[:title])
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|