cathode 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +346 -125
- data/Rakefile +1 -0
- data/app/controllers/cathode/base_controller.rb +28 -45
- data/app/models/cathode/token.rb +21 -0
- data/config/routes.rb +16 -0
- data/db/migrate/20140425164100_create_cathode_tokens.rb +11 -0
- data/lib/cathode.rb +0 -13
- data/lib/cathode/_version.rb +2 -1
- data/lib/cathode/action.rb +197 -39
- data/lib/cathode/action_dsl.rb +60 -0
- data/lib/cathode/base.rb +81 -12
- data/lib/cathode/create_request.rb +21 -0
- data/lib/cathode/custom_request.rb +5 -0
- data/lib/cathode/debug.rb +25 -0
- data/lib/cathode/destroy_request.rb +13 -0
- data/lib/cathode/engine.rb +9 -0
- data/lib/cathode/exceptions.rb +20 -0
- data/lib/cathode/index_request.rb +40 -0
- data/lib/cathode/object_collection.rb +49 -0
- data/lib/cathode/query.rb +24 -0
- data/lib/cathode/railtie.rb +21 -0
- data/lib/cathode/request.rb +139 -7
- data/lib/cathode/resource.rb +50 -19
- data/lib/cathode/resource_dsl.rb +46 -0
- data/lib/cathode/show_request.rb +13 -0
- data/lib/cathode/update_request.rb +26 -0
- data/lib/cathode/version.rb +112 -23
- data/lib/tasks/cathode_tasks.rake +5 -4
- data/spec/dummy/app/api/api.rb +0 -0
- data/spec/dummy/app/models/payment.rb +3 -0
- data/spec/dummy/app/models/product.rb +1 -0
- data/spec/dummy/app/models/sale.rb +5 -0
- data/spec/dummy/app/models/salesperson.rb +3 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20140409183635_create_sales.rb +11 -0
- data/spec/dummy/db/migrate/20140423172419_create_salespeople.rb +11 -0
- data/spec/dummy/db/migrate/20140424181343_create_payments.rb +10 -0
- data/spec/dummy/db/schema.rb +31 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +1167 -0
- data/spec/dummy/log/test.log +180602 -0
- data/spec/dummy/spec/factories/payments.rb +8 -0
- data/spec/dummy/spec/factories/products.rb +1 -1
- data/spec/dummy/spec/factories/sales.rb +9 -0
- data/spec/dummy/spec/factories/salespeople.rb +7 -0
- data/spec/dummy/spec/requests/requests_spec.rb +434 -0
- data/spec/lib/cathode/action_spec.rb +136 -0
- data/spec/lib/cathode/base_spec.rb +34 -0
- data/spec/lib/cathode/create_request_spec.rb +40 -0
- data/spec/lib/cathode/custom_request_spec.rb +31 -0
- data/spec/lib/cathode/debug_spec.rb +25 -0
- data/spec/lib/cathode/destroy_request_spec.rb +28 -0
- data/spec/lib/cathode/index_request_spec.rb +62 -0
- data/spec/lib/cathode/object_collection_spec.rb +66 -0
- data/spec/lib/cathode/query_spec.rb +28 -0
- data/spec/lib/cathode/request_spec.rb +58 -0
- data/spec/lib/cathode/resource_spec.rb +482 -0
- data/spec/lib/cathode/show_request_spec.rb +23 -0
- data/spec/lib/cathode/update_request_spec.rb +41 -0
- data/spec/lib/cathode/version_spec.rb +416 -0
- data/spec/models/cathode/token_spec.rb +62 -0
- data/spec/spec_helper.rb +8 -2
- data/spec/support/factories/payments.rb +3 -0
- data/spec/support/factories/sale.rb +3 -0
- data/spec/support/factories/salespeople.rb +3 -0
- data/spec/support/factories/token.rb +3 -0
- data/spec/support/helpers.rb +13 -2
- metadata +192 -47
- data/app/helpers/cathode/application_helper.rb +0 -4
- data/spec/dummy/app/api/dummy_api.rb +0 -4
- data/spec/integration/api_spec.rb +0 -88
- data/spec/lib/action_spec.rb +0 -140
- data/spec/lib/base_spec.rb +0 -28
- data/spec/lib/request_spec.rb +0 -5
- data/spec/lib/resources_spec.rb +0 -78
- data/spec/lib/versioning_spec.rb +0 -104
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::Action do
|
4
|
+
describe '.create' do
|
5
|
+
subject { Cathode::Action.create(action, Cathode::Resource.new(:products), try(:params) || {}, &block) }
|
6
|
+
|
7
|
+
context 'with a default action' do
|
8
|
+
let(:action) { :index }
|
9
|
+
|
10
|
+
context 'with an override' do
|
11
|
+
let(:block) { proc { override { Product.last } } }
|
12
|
+
|
13
|
+
it 'sets the override block' do
|
14
|
+
expect(subject.override_block.call).to eq(Product.last)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with a replacement' do
|
19
|
+
let(:block) { proc { replace { Product.last } } }
|
20
|
+
|
21
|
+
it 'sets the replacement as the action block' do
|
22
|
+
expect(subject.action_block.call).to eq(Product.last)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with a custom action' do
|
28
|
+
let(:action) { :custom }
|
29
|
+
let(:block) { proc { Product.last } }
|
30
|
+
|
31
|
+
context 'with method' do
|
32
|
+
let(:params) { { method: :get } }
|
33
|
+
|
34
|
+
it 'creates a CustomAction' do
|
35
|
+
expect(subject.class).to eq(Cathode::CustomAction)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'sets the block as the action block' do
|
39
|
+
expect(subject.action_block.call).to eq(Product.last)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'sets the HTTP method' do
|
43
|
+
expect(subject.http_method).to eq(:get)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'without method' do
|
48
|
+
let(:params) { {} }
|
49
|
+
|
50
|
+
it 'raises an error' do
|
51
|
+
expect { subject }.to raise_error(
|
52
|
+
Cathode::RequestMethodMissingError,
|
53
|
+
"You must specify an HTTP method (get, put, post, delete) for action `custom'"
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with :index' do
|
60
|
+
let(:action) { :index }
|
61
|
+
let(:block) { nil }
|
62
|
+
|
63
|
+
it 'creates an IndexAction' do
|
64
|
+
expect(subject.class).to eq(Cathode::IndexAction)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'with :show' do
|
69
|
+
let(:action) { :show }
|
70
|
+
let(:block) { nil }
|
71
|
+
|
72
|
+
it 'creates a ShowAction' do
|
73
|
+
expect(subject.class).to eq(Cathode::ShowAction)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with :create' do
|
78
|
+
let(:action) { :create }
|
79
|
+
|
80
|
+
context 'when attributes specified' do
|
81
|
+
let(:block) do
|
82
|
+
proc { attributes { params.require(:product) } }
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'creates a CreateAction' do
|
86
|
+
expect(subject.after_resource_initialized.class).to eq(Cathode::CreateAction)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when attributes not specified' do
|
91
|
+
let(:block) { nil }
|
92
|
+
|
93
|
+
it 'raises an error' do
|
94
|
+
expect { subject.after_resource_initialized }.to raise_error(
|
95
|
+
Cathode::UnknownAttributesError,
|
96
|
+
"An attributes block was not specified for `create' action on resource `products'"
|
97
|
+
)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'with :update' do
|
103
|
+
let(:action) { :update }
|
104
|
+
|
105
|
+
context 'when attributes specified' do
|
106
|
+
let(:block) do
|
107
|
+
proc { attributes { params.require(:product) } }
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'creates an UpdateAction' do
|
111
|
+
expect(subject.after_resource_initialized.class).to eq(Cathode::UpdateAction)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'when attributes not specified' do
|
116
|
+
let(:block) { nil }
|
117
|
+
|
118
|
+
it 'raises an error' do
|
119
|
+
expect { subject.after_resource_initialized }.to raise_error(
|
120
|
+
Cathode::UnknownAttributesError,
|
121
|
+
"An attributes block was not specified for `update' action on resource `products'"
|
122
|
+
)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'with :destroy' do
|
128
|
+
let(:action) { :destroy }
|
129
|
+
let(:block) { nil }
|
130
|
+
|
131
|
+
it 'creates a DestroyAction' do
|
132
|
+
expect(subject.class).to eq(Cathode::DestroyAction)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::Base do
|
4
|
+
describe '#version' do
|
5
|
+
subject do
|
6
|
+
Cathode::Base.version 1.5 do
|
7
|
+
resources :products
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'creates a new version' do
|
12
|
+
expect(subject.version).to eq('1.5.0')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'contains the resources' do
|
16
|
+
expect(subject._resources.names).to eq([:products])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#define' do
|
21
|
+
context 'with resource name' do
|
22
|
+
subject do
|
23
|
+
Cathode::Base.define do
|
24
|
+
resources :products
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'initializes version 1.0.0' do
|
29
|
+
subject
|
30
|
+
expect(Cathode::Version.find('1.0.0')._resources.find(:products)).to_not be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::CreateRequest do
|
4
|
+
subject do
|
5
|
+
Cathode::CreateRequest.new(context_stub(params: ActionController::Parameters.new(params.merge(controller: 'products', action: 'create'))))
|
6
|
+
end
|
7
|
+
before do
|
8
|
+
use_api do
|
9
|
+
resources :products, actions: [:create] do
|
10
|
+
attributes do
|
11
|
+
params.require(:product).permit(:title)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with valid attributes' do
|
18
|
+
let(:params) { { product: { title: 'cool product' } } }
|
19
|
+
|
20
|
+
it 'sets status as ok' do
|
21
|
+
expect(subject._status).to eq(:ok)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sets body as the new record' do
|
25
|
+
expect(subject._body.title).to eq('cool product')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with invalid attributes' do
|
30
|
+
let(:params) { { title: 'cool product' } }
|
31
|
+
|
32
|
+
it 'sets status as bad request' do
|
33
|
+
expect(subject._status).to eq(:bad_request)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'sets body as error message' do
|
37
|
+
expect(subject._body).to eq('param is missing or the value is empty: product')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::CustomRequest do
|
4
|
+
subject do
|
5
|
+
Cathode::CustomRequest.new(context_stub(
|
6
|
+
params: ActionController::Parameters.new(params.merge(controller: 'products', action: 'custom')),
|
7
|
+
path: 'products/custom'
|
8
|
+
))
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
use_api do
|
13
|
+
resources :products do
|
14
|
+
get :custom do
|
15
|
+
body Product.last
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
let!(:products) { create_list(:product, 3) }
|
22
|
+
let(:params) { {} }
|
23
|
+
|
24
|
+
it 'sets status as ok' do
|
25
|
+
expect(subject._status).to eq(:ok)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'sets body' do
|
29
|
+
expect(subject._body).to eq(Product.last)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::Debug do
|
4
|
+
before do
|
5
|
+
use_api do
|
6
|
+
resources :products, actions: [:index]
|
7
|
+
version 2 do
|
8
|
+
resources :sales, actions: :all do
|
9
|
+
attributes do
|
10
|
+
params.require(:sale)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '.info' do
|
18
|
+
subject { Cathode::Debug.info }
|
19
|
+
|
20
|
+
it 'returns the info' do
|
21
|
+
puts subject
|
22
|
+
# expect(subject).to eq("Version 1.0.0\n\tproducts")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::DestroyRequest do
|
4
|
+
subject do
|
5
|
+
Cathode::DestroyRequest.new(context_stub(params: ActionController::Parameters.new(params.merge(controller: 'products', action: 'destroy'))))
|
6
|
+
end
|
7
|
+
before do
|
8
|
+
use_api do
|
9
|
+
resources :products, actions: [:destroy]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:action) { 'destroy' }
|
14
|
+
let(:params) { { id: product.id } }
|
15
|
+
let!(:product) { create(:product) }
|
16
|
+
|
17
|
+
it 'sets status as ok' do
|
18
|
+
expect(subject._status).to eq(:ok)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'sets body as empty' do
|
22
|
+
expect(subject._body).to be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'removes the record' do
|
26
|
+
expect { subject }.to change { Product.count }.by(-1)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::IndexRequest do
|
4
|
+
subject do
|
5
|
+
Cathode::IndexRequest.new(context_stub(params: ActionController::Parameters.new(params.merge(controller: resource, action: 'index'))))
|
6
|
+
end
|
7
|
+
let!(:products) { create_list(:product, 5) }
|
8
|
+
before do
|
9
|
+
use_api do
|
10
|
+
resources :products do
|
11
|
+
action :index do
|
12
|
+
allows :paging
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
resources :sales, actions: [:index]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'with no params' do
|
21
|
+
let(:params) { {} }
|
22
|
+
let(:resource) { 'products' }
|
23
|
+
let(:block) { nil }
|
24
|
+
|
25
|
+
it 'sets status as ok' do
|
26
|
+
expect(subject._status).to eq(:ok)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'sets body as all resource records' do
|
30
|
+
expect(subject._body).to eq(Product.all)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with paging' do
|
35
|
+
let(:params) { { page: 2, per_page: 2 } }
|
36
|
+
|
37
|
+
context 'when allowed' do
|
38
|
+
let(:resource) { 'products' }
|
39
|
+
|
40
|
+
it 'sets status as ok' do
|
41
|
+
expect(subject._status).to eq(:ok)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'sets body as the paged results' do
|
45
|
+
expect(subject._body).to eq(products[2..3])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when not allowed' do
|
50
|
+
let(:resource) { 'sales' }
|
51
|
+
let!(:sales) { create_list(:sale, 5) }
|
52
|
+
|
53
|
+
it 'sets status as ok' do
|
54
|
+
expect(subject._status).to eq(:ok)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'sets body as all records' do
|
58
|
+
expect(subject._body).to eq(sales)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::ObjectCollection do
|
4
|
+
let(:collection) { Cathode::ObjectCollection.new }
|
5
|
+
let(:obj_struct) { Struct.new(:name) }
|
6
|
+
let(:battery) { obj_struct.new(:battery) }
|
7
|
+
let(:charger) { obj_struct.new(:charger) }
|
8
|
+
before do
|
9
|
+
collection << battery
|
10
|
+
collection << charger
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#find' do
|
14
|
+
subject { collection.find(:battery) }
|
15
|
+
|
16
|
+
it 'returns the item with the matching name' do
|
17
|
+
expect(subject).to eq(battery)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#add' do
|
22
|
+
subject { collection.add(items) }
|
23
|
+
let(:cord) { obj_struct.new(:cord) }
|
24
|
+
let(:connector) { obj_struct.new(:connector) }
|
25
|
+
|
26
|
+
context 'with single item' do
|
27
|
+
let(:items) { cord }
|
28
|
+
|
29
|
+
it 'adds the item to the objects' do
|
30
|
+
expect(subject.objects).to match_array([battery, charger, cord])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with an array of items' do
|
35
|
+
let(:items) { [cord, connector] }
|
36
|
+
|
37
|
+
it 'adds the items to the objects' do
|
38
|
+
expect(subject.objects).to match_array([battery, charger, cord, connector])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#delete' do
|
44
|
+
subject { collection.delete(:battery) }
|
45
|
+
|
46
|
+
it 'deletes the object from the collection' do
|
47
|
+
expect(subject.objects).to match_array([charger])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#names' do
|
52
|
+
subject { collection.names }
|
53
|
+
|
54
|
+
it 'returns the objects mapped to their names' do
|
55
|
+
expect(subject).to match_array([:battery, :charger])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'array methods' do
|
60
|
+
subject { collection.each { |i| i } }
|
61
|
+
|
62
|
+
it 'delegates to the object array' do
|
63
|
+
expect(subject).to match_array([battery, charger])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cathode::Query do
|
4
|
+
describe '.new' do
|
5
|
+
subject { Cathode::Query.new(Product, query) }
|
6
|
+
let!(:product1) { create(:product, cost: 500) }
|
7
|
+
let!(:product2) { create(:product, cost: 700) }
|
8
|
+
let!(:product3) { create(:product, cost: 1000) }
|
9
|
+
|
10
|
+
describe 'where' do
|
11
|
+
context 'explicit' do
|
12
|
+
let(:query) { 'where cost > 500' }
|
13
|
+
|
14
|
+
it 'returns the records' do
|
15
|
+
expect(subject.results).to match_array([product2, product3])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'implicit' do
|
20
|
+
let(:query) { 'cost > 500' }
|
21
|
+
|
22
|
+
it 'returns the records' do
|
23
|
+
expect(subject.results).to match_array([product2, product3])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|