cathode 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +236 -0
  4. data/Rakefile +26 -0
  5. data/app/assets/javascripts/cathode/application.js +13 -0
  6. data/app/assets/stylesheets/cathode/application.css +13 -0
  7. data/app/controllers/cathode/base_controller.rb +47 -0
  8. data/app/helpers/cathode/application_helper.rb +4 -0
  9. data/app/views/layouts/cathode/application.html.erb +14 -0
  10. data/config/routes.rb +2 -0
  11. data/lib/cathode.rb +14 -0
  12. data/lib/cathode/_version.rb +3 -0
  13. data/lib/cathode/action.rb +82 -0
  14. data/lib/cathode/base.rb +28 -0
  15. data/lib/cathode/engine.rb +5 -0
  16. data/lib/cathode/exceptions.rb +3 -0
  17. data/lib/cathode/request.rb +15 -0
  18. data/lib/cathode/resource.rb +40 -0
  19. data/lib/cathode/version.rb +49 -0
  20. data/lib/tasks/cathode_tasks.rake +4 -0
  21. data/spec/dummy/README.rdoc +28 -0
  22. data/spec/dummy/Rakefile +6 -0
  23. data/spec/dummy/app/api/dummy_api.rb +4 -0
  24. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  25. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  26. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  27. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  28. data/spec/dummy/app/models/product.rb +2 -0
  29. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  30. data/spec/dummy/bin/bundle +3 -0
  31. data/spec/dummy/bin/rails +4 -0
  32. data/spec/dummy/bin/rake +4 -0
  33. data/spec/dummy/config.ru +4 -0
  34. data/spec/dummy/config/application.rb +28 -0
  35. data/spec/dummy/config/boot.rb +5 -0
  36. data/spec/dummy/config/database.yml +25 -0
  37. data/spec/dummy/config/environment.rb +5 -0
  38. data/spec/dummy/config/environments/development.rb +29 -0
  39. data/spec/dummy/config/environments/production.rb +80 -0
  40. data/spec/dummy/config/environments/test.rb +36 -0
  41. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  42. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  43. data/spec/dummy/config/initializers/inflections.rb +16 -0
  44. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  45. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  46. data/spec/dummy/config/initializers/session_store.rb +3 -0
  47. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  48. data/spec/dummy/config/locales/en.yml +23 -0
  49. data/spec/dummy/config/routes.rb +3 -0
  50. data/spec/dummy/db/development.sqlite3 +0 -0
  51. data/spec/dummy/db/migrate/20140404222551_create_products.rb +10 -0
  52. data/spec/dummy/db/schema.rb +23 -0
  53. data/spec/dummy/db/test.sqlite3 +0 -0
  54. data/spec/dummy/log/development.log +312 -0
  55. data/spec/dummy/log/test.log +12708 -0
  56. data/spec/dummy/public/404.html +58 -0
  57. data/spec/dummy/public/422.html +58 -0
  58. data/spec/dummy/public/500.html +57 -0
  59. data/spec/dummy/public/favicon.ico +0 -0
  60. data/spec/dummy/spec/factories/products.rb +8 -0
  61. data/spec/integration/api_spec.rb +88 -0
  62. data/spec/lib/action_spec.rb +140 -0
  63. data/spec/lib/base_spec.rb +28 -0
  64. data/spec/lib/request_spec.rb +5 -0
  65. data/spec/lib/resources_spec.rb +78 -0
  66. data/spec/lib/versioning_spec.rb +104 -0
  67. data/spec/spec_helper.rb +30 -0
  68. data/spec/support/factories/products.rb +3 -0
  69. data/spec/support/helpers.rb +9 -0
  70. metadata +259 -0
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style>
6
+ body {
7
+ background-color: #EFEFEF;
8
+ color: #2E2F30;
9
+ text-align: center;
10
+ font-family: arial, sans-serif;
11
+ }
12
+
13
+ div.dialog {
14
+ width: 25em;
15
+ margin: 4em auto 0 auto;
16
+ border: 1px solid #CCC;
17
+ border-right-color: #999;
18
+ border-left-color: #999;
19
+ border-bottom-color: #BBB;
20
+ border-top: #B00100 solid 4px;
21
+ border-top-left-radius: 9px;
22
+ border-top-right-radius: 9px;
23
+ background-color: white;
24
+ padding: 7px 4em 0 4em;
25
+ }
26
+
27
+ h1 {
28
+ font-size: 100%;
29
+ color: #730E15;
30
+ line-height: 1.5em;
31
+ }
32
+
33
+ body > p {
34
+ width: 33em;
35
+ margin: 0 auto 1em;
36
+ padding: 1em 0;
37
+ background-color: #F7F7F7;
38
+ border: 1px solid #CCC;
39
+ border-right-color: #999;
40
+ border-bottom-color: #999;
41
+ border-bottom-left-radius: 4px;
42
+ border-bottom-right-radius: 4px;
43
+ border-top-color: #DADADA;
44
+ color: #666;
45
+ box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
46
+ }
47
+ </style>
48
+ </head>
49
+
50
+ <body>
51
+ <!-- This file lives in public/404.html -->
52
+ <div class="dialog">
53
+ <h1>The page you were looking for doesn't exist.</h1>
54
+ <p>You may have mistyped the address or the page may have moved.</p>
55
+ </div>
56
+ <p>If you are the application owner check the logs for more information.</p>
57
+ </body>
58
+ </html>
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style>
6
+ body {
7
+ background-color: #EFEFEF;
8
+ color: #2E2F30;
9
+ text-align: center;
10
+ font-family: arial, sans-serif;
11
+ }
12
+
13
+ div.dialog {
14
+ width: 25em;
15
+ margin: 4em auto 0 auto;
16
+ border: 1px solid #CCC;
17
+ border-right-color: #999;
18
+ border-left-color: #999;
19
+ border-bottom-color: #BBB;
20
+ border-top: #B00100 solid 4px;
21
+ border-top-left-radius: 9px;
22
+ border-top-right-radius: 9px;
23
+ background-color: white;
24
+ padding: 7px 4em 0 4em;
25
+ }
26
+
27
+ h1 {
28
+ font-size: 100%;
29
+ color: #730E15;
30
+ line-height: 1.5em;
31
+ }
32
+
33
+ body > p {
34
+ width: 33em;
35
+ margin: 0 auto 1em;
36
+ padding: 1em 0;
37
+ background-color: #F7F7F7;
38
+ border: 1px solid #CCC;
39
+ border-right-color: #999;
40
+ border-bottom-color: #999;
41
+ border-bottom-left-radius: 4px;
42
+ border-bottom-right-radius: 4px;
43
+ border-top-color: #DADADA;
44
+ color: #666;
45
+ box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
46
+ }
47
+ </style>
48
+ </head>
49
+
50
+ <body>
51
+ <!-- This file lives in public/422.html -->
52
+ <div class="dialog">
53
+ <h1>The change you wanted was rejected.</h1>
54
+ <p>Maybe you tried to change something you didn't have access to.</p>
55
+ </div>
56
+ <p>If you are the application owner check the logs for more information.</p>
57
+ </body>
58
+ </html>
@@ -0,0 +1,57 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style>
6
+ body {
7
+ background-color: #EFEFEF;
8
+ color: #2E2F30;
9
+ text-align: center;
10
+ font-family: arial, sans-serif;
11
+ }
12
+
13
+ div.dialog {
14
+ width: 25em;
15
+ margin: 4em auto 0 auto;
16
+ border: 1px solid #CCC;
17
+ border-right-color: #999;
18
+ border-left-color: #999;
19
+ border-bottom-color: #BBB;
20
+ border-top: #B00100 solid 4px;
21
+ border-top-left-radius: 9px;
22
+ border-top-right-radius: 9px;
23
+ background-color: white;
24
+ padding: 7px 4em 0 4em;
25
+ }
26
+
27
+ h1 {
28
+ font-size: 100%;
29
+ color: #730E15;
30
+ line-height: 1.5em;
31
+ }
32
+
33
+ body > p {
34
+ width: 33em;
35
+ margin: 0 auto 1em;
36
+ padding: 1em 0;
37
+ background-color: #F7F7F7;
38
+ border: 1px solid #CCC;
39
+ border-right-color: #999;
40
+ border-bottom-color: #999;
41
+ border-bottom-left-radius: 4px;
42
+ border-bottom-right-radius: 4px;
43
+ border-top-color: #DADADA;
44
+ color: #666;
45
+ box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
46
+ }
47
+ </style>
48
+ </head>
49
+
50
+ <body>
51
+ <!-- This file lives in public/500.html -->
52
+ <div class="dialog">
53
+ <h1>We're sorry, but something went wrong.</h1>
54
+ </div>
55
+ <p>If you are the application owner check the logs for more information.</p>
56
+ </body>
57
+ </html>
File without changes
@@ -0,0 +1,8 @@
1
+ # Read about factories at https://github.com/thoughtbot/factory_girl
2
+
3
+ FactoryGirl.define do
4
+ factory :product do
5
+ title "MyString"
6
+ cost 1
7
+ end
8
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ def make_request(method, path, params = nil, version = '1.0.0')
4
+ send(method, path, params, { 'Accept-Version' => version })
5
+ end
6
+
7
+ describe 'API' do
8
+ context 'with the default API (all actions)' do
9
+ before(:all) do
10
+ use_api do
11
+ version 1.5 do
12
+ resource :products, actions: [:all]
13
+ end
14
+ end
15
+ end
16
+
17
+ let!(:products) { create_list(:product, 5) }
18
+
19
+ describe 'GET #index' do
20
+ subject { make_request :get, 'api/products' }
21
+
22
+ it 'responds with all records' do
23
+ subject
24
+ expect(response.body).to eq(products.to_json)
25
+ end
26
+ end
27
+
28
+ describe 'GET #show' do
29
+ subject { make_request :get, 'api/products/1', nil, '1.5' }
30
+
31
+ it 'responds with the record' do
32
+ subject
33
+ expect(response.body).to eq(products.first.to_json)
34
+ end
35
+ end
36
+
37
+ describe 'POST #create' do
38
+ subject { make_request :post, 'api/products', product: { title: 'hello', cost: 1900 } }
39
+
40
+ it 'responds with the new record' do
41
+ subject
42
+ expect(response.body).to eq(Product.new(title: 'hello', cost: 1900).to_json)
43
+ end
44
+ end
45
+
46
+ describe 'DELETE #destroy' do
47
+ subject { make_request :delete, 'api/products/1' }
48
+
49
+ it 'responds with success' do
50
+ expect(subject).to eq(200)
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'with an access filter' do
56
+ subject { make_request :get, 'api/products/1' }
57
+
58
+ let!(:products) { create_list(:product, 5) }
59
+
60
+ context 'when inaccessible' do
61
+ before(:all) do
62
+ use_api do
63
+ resource :products do
64
+ action(:show) { access_filter { false } }
65
+ end
66
+ end
67
+ end
68
+
69
+ it 'responds with unauthorized' do
70
+ expect(subject).to eq(401)
71
+ end
72
+ end
73
+
74
+ context 'when accessible' do
75
+ before(:all) do
76
+ use_api do
77
+ resource :products do
78
+ action(:show) { access_filter { true } }
79
+ end
80
+ end
81
+ end
82
+
83
+ it 'responds with success' do
84
+ expect(subject).to eq(200)
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cathode::Action do
4
+ describe '.create' do
5
+ subject { Cathode::Action.create(action, :products) }
6
+
7
+ context 'with :index' do
8
+ let(:action) { :index }
9
+
10
+ it 'creates a IndexAction' do
11
+ expect(subject.class).to eq(Cathode::IndexAction)
12
+ end
13
+ end
14
+
15
+ context 'with :show' do
16
+ let(:action) { :show }
17
+
18
+ it 'creates a ShowAction' do
19
+ expect(subject.class).to eq(Cathode::ShowAction)
20
+ end
21
+ end
22
+
23
+ context 'with :create' do
24
+ let(:action) { :create }
25
+
26
+ it 'creates a CreateAction' do
27
+ expect(subject.class).to eq(Cathode::CreateAction)
28
+ end
29
+ end
30
+
31
+ context 'with :update' do
32
+ let(:action) { :update }
33
+
34
+ it 'creates an UpdateAction' do
35
+ expect(subject.class).to eq(Cathode::UpdateAction)
36
+ end
37
+ end
38
+
39
+ context 'with :destroy' do
40
+ let(:action) { :destroy }
41
+
42
+ it 'creates a DestroyAction' do
43
+ expect(subject.class).to eq(Cathode::DestroyAction)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#perform' do
49
+ let!(:products) { create_list(:product, 5) }
50
+
51
+ subject { Cathode::Action.create(action, :products).perform(params) }
52
+
53
+ context ':index' do
54
+ let(:action) { :index }
55
+ let(:params) { {} }
56
+
57
+ it 'sets status as ok' do
58
+ expect(subject[:status]).to eq(:ok)
59
+ end
60
+
61
+ it 'sets body as all resource records' do
62
+ expect(subject[:body]).to eq(Product.all)
63
+ end
64
+ end
65
+
66
+ context ':show' do
67
+ let(:action) { :show }
68
+ let(:params) { { :id => 3 } }
69
+
70
+ subject { Cathode::Action.create(action, :products, &block).perform(params) }
71
+
72
+ context 'with access filter' do
73
+ context 'when accessible' do
74
+ let(:block) { proc { access_filter(&proc { true }) } }
75
+
76
+ it 'sets status as ok' do
77
+ expect(subject[:status]).to eq(:ok)
78
+ end
79
+
80
+ it 'sets body as the record' do
81
+ expect(subject[:body]).to eq(products[2])
82
+ end
83
+ end
84
+
85
+ context 'when inaccessible' do
86
+ let(:block) { proc { access_filter(&proc { false }) } }
87
+
88
+ it 'sets status as unauthorized' do
89
+ expect(subject[:status]).to eq(:unauthorized)
90
+ end
91
+
92
+ it 'sets body as nil' do
93
+ expect(subject[:body]).to be_nil
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ context ':create' do
100
+ let(:action) { :create }
101
+ let(:params) { { :title => 'cool product' } }
102
+
103
+ it 'sets status as ok' do
104
+ expect(subject[:status]).to eq(:ok)
105
+ end
106
+
107
+ it 'sets body as the new record' do
108
+ expect(subject[:body].title).to eq('cool product')
109
+ end
110
+ end
111
+
112
+ context ':update' do
113
+ let(:action) { :update }
114
+ let(:params) { { :id => product.id, :title => 'cooler product' } }
115
+ let(:product) { create(:product, title: 'cool product') }
116
+
117
+ it 'sets status as ok' do
118
+ expect(subject[:status]).to eq(:ok)
119
+ end
120
+
121
+ it 'sets body as the updated record' do
122
+ expect(subject[:body].title).to eq('cooler product')
123
+ end
124
+ end
125
+
126
+ context ':destroy' do
127
+ let(:action) { :destroy }
128
+ let(:params) { { :id => product.id } }
129
+ let!(:product) { create(:product) }
130
+
131
+ it 'sets status as ok' do
132
+ expect(subject[:status]).to eq(:ok)
133
+ end
134
+
135
+ it 'removes the record' do
136
+ expect { subject }.to change { Product.count }.by(-1)
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cathode::Base do
4
+ describe '#version' do
5
+ subject { Cathode::Base.version 1.5 do
6
+ resource :products
7
+ end }
8
+
9
+ it 'creates a new version' do
10
+ expect(subject.version).to eq('1.5.0')
11
+ end
12
+
13
+ it 'contains the resources' do
14
+ expect(subject.resources.keys).to eq([:products])
15
+ end
16
+ end
17
+
18
+ describe '#resource' do
19
+ context 'with resource name' do
20
+ subject { Cathode::Base.resource(:products) }
21
+
22
+ it 'initializes version 1.0.0' do
23
+ subject
24
+ expect(Cathode::Version.all['1.0.0'].resources[:products]).to_not be_nil
25
+ end
26
+ end
27
+ end
28
+ end