cathode 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.
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