gatherable 1.2.0 → 2.0.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/app/controllers/gatherable/application_controller.rb +23 -9
- data/config/routes.rb +20 -7
- data/lib/gatherable/configuration.rb +19 -1
- data/lib/gatherable/version.rb +1 -1
- data/lib/generators/gatherable/gatherable_generator.rb +5 -3
- data/lib/generators/gatherable/templates/gatherable.rb +6 -6
- data/spec/controllers/gatherable/application_controller_spec.rb +248 -134
- data/spec/dummy/config/initializers/gatherable.rb +0 -8
- data/spec/dummy/log/test.log +91257 -0
- data/spec/lib/gatherable_spec.rb +8 -13
- data/spec/lib/generators/gatherable_generator_spec.rb +5 -3
- data/spec/support/test_config.rb +0 -8
- metadata +2 -3
- data/lib/generators/gatherable/templates/application_controller.rb +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4cc971a909ed605b6e2438d967017cb5e8b0197
|
4
|
+
data.tar.gz: 3ab989877d63570afb2b91cf194814468c76f263
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed5f8b4d444fdf3cadc0fee9150f45da62c555b518ce6a2849862bb8ddc5470e49eab0da94383b777f2ab3e614cc2f92c4eb6afc9f41bef7709cb24cef068c97
|
7
|
+
data.tar.gz: 0950e67aa43118895f8fbd53f0b64d8bebd1c13fd1c4f964808524392dc01c96f34fec8ac1b693c325c54446a9d1ee855d40d4f0a8cdd2c6322539343276c3c0
|
@@ -1,20 +1,21 @@
|
|
1
1
|
module Gatherable
|
2
2
|
class ApplicationController < ::ActionController::Base
|
3
|
-
before_action :
|
3
|
+
before_action :set_gatherable_id
|
4
|
+
before_action :authenticate
|
4
5
|
|
5
6
|
def index
|
6
|
-
render :json => model_class.where(
|
7
|
+
render :json => model_class.where(global_id => global_id_val), :status => :found
|
7
8
|
end
|
8
9
|
|
9
10
|
def show
|
10
|
-
render :json =>
|
11
|
+
render :json => model_class.find_by!(global_id => global_id_val, model_id => params[model_id]), :status => :found
|
11
12
|
rescue ActiveRecord::RecordNotFound => e
|
12
13
|
render :json => { :errors => e.message}, :status => :not_found
|
13
14
|
end
|
14
15
|
|
15
16
|
def create
|
16
17
|
if data_table.new_record_strategy == :update
|
17
|
-
model = model_class.find_or_initialize_by(
|
18
|
+
model = model_class.find_or_initialize_by(global_id => global_id_val)
|
18
19
|
model.update_attributes(model_params)
|
19
20
|
render :json => model, :status => :ok
|
20
21
|
else
|
@@ -44,11 +45,12 @@ module Gatherable
|
|
44
45
|
|
45
46
|
def authenticate
|
46
47
|
return unless Gatherable.config.auth_method == :session
|
47
|
-
|
48
|
+
return unless requires_global_id_param?
|
49
|
+
head :unauthorized unless params[global_id] == session[global_id]
|
48
50
|
end
|
49
51
|
|
50
52
|
def model_instance
|
51
|
-
model_class.find_by!(params.slice(model_id,
|
53
|
+
model_class.find_by!(params.slice(model_id, global_id_val))
|
52
54
|
end
|
53
55
|
|
54
56
|
def model_class
|
@@ -73,16 +75,28 @@ module Gatherable
|
|
73
75
|
|
74
76
|
def model_params
|
75
77
|
params.require(model_name_as_var).permit(
|
76
|
-
*model_class.column_names
|
77
|
-
).merge(
|
78
|
+
*model_class.column_names - [global_id]
|
79
|
+
).merge(global_id => global_id_val)
|
78
80
|
end
|
79
81
|
|
80
|
-
def
|
82
|
+
def global_id
|
81
83
|
Gatherable.config.global_identifier
|
82
84
|
end
|
83
85
|
|
84
86
|
def data_table
|
85
87
|
DataTable.find_by_name(model_name_as_var)
|
86
88
|
end
|
89
|
+
|
90
|
+
def set_gatherable_id
|
91
|
+
session[global_id] ||= SecureRandom.urlsafe_base64
|
92
|
+
end
|
93
|
+
|
94
|
+
def global_id_val
|
95
|
+
requires_global_id_param? ? params[global_id] : session[global_id]
|
96
|
+
end
|
97
|
+
|
98
|
+
def requires_global_id_param?
|
99
|
+
Gatherable.config.prefixed_resources.include? data_table.name
|
100
|
+
end
|
87
101
|
end
|
88
102
|
end
|
data/config/routes.rb
CHANGED
@@ -1,10 +1,23 @@
|
|
1
|
-
Gatherable::
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
class Gatherable::RouteDrawer
|
2
|
+
def self.draw
|
3
|
+
Gatherable::Engine.routes.draw do
|
4
|
+
Gatherable.config.data_tables.each do |data_table|
|
5
|
+
if Gatherable.config.prefixed_resources.include? data_table.name
|
6
|
+
scope :path => "/:#{Gatherable.config.global_identifier}" do
|
7
|
+
resources(data_table.name.to_s.pluralize.to_sym,
|
8
|
+
:only => data_table.allowed_controller_actions.map(&:to_sym),
|
9
|
+
:param => "#{data_table.name}_id"
|
10
|
+
)
|
11
|
+
end
|
12
|
+
else
|
13
|
+
resources(data_table.name.to_s.pluralize.to_sym,
|
14
|
+
:only => data_table.allowed_controller_actions.map(&:to_sym),
|
15
|
+
:param => "#{data_table.name}_id"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
8
19
|
end
|
9
20
|
end
|
10
21
|
end
|
22
|
+
|
23
|
+
Gatherable::RouteDrawer.draw
|
@@ -21,7 +21,25 @@ module Gatherable
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def auth_method
|
24
|
-
@auth_method
|
24
|
+
@auth_method || :session
|
25
|
+
end
|
26
|
+
|
27
|
+
def prefixed_resources
|
28
|
+
@prefixed_resources ||= []
|
29
|
+
end
|
30
|
+
|
31
|
+
def prefixed_resources=(resources)
|
32
|
+
all_table_names = DataTable.all.keys
|
33
|
+
@prefixed_resources = case resources
|
34
|
+
when String, Symbol, Array
|
35
|
+
Array(resources).map(&:to_sym) && all_table_names
|
36
|
+
when Hash
|
37
|
+
if resources.key?(:only)
|
38
|
+
Array(resources[:only]).map(&:to_sym) && all_table_names
|
39
|
+
elsif resources.key?(:except)
|
40
|
+
all_table_names - Array(resources[:except]).map(&:to_sym)
|
41
|
+
end
|
42
|
+
end
|
25
43
|
end
|
26
44
|
end
|
27
45
|
end
|
data/lib/gatherable/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rails/generators'
|
2
2
|
class GatherableGenerator < Rails::Generators::NamedBase
|
3
|
-
source_root File.expand_path('
|
3
|
+
source_root File.expand_path('../../../../', __FILE__)
|
4
4
|
def generate
|
5
5
|
send "generate_#{file_name}"
|
6
6
|
end
|
@@ -8,7 +8,8 @@ class GatherableGenerator < Rails::Generators::NamedBase
|
|
8
8
|
private
|
9
9
|
|
10
10
|
def generate_initializer
|
11
|
-
copy_file "gatherable
|
11
|
+
copy_file "lib/generators/gatherable/templates/gatherable.rb",
|
12
|
+
"config/initializers/gatherable.rb"
|
12
13
|
end
|
13
14
|
|
14
15
|
def generate_migrations
|
@@ -25,7 +26,8 @@ class GatherableGenerator < Rails::Generators::NamedBase
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def generate_controllers
|
28
|
-
copy_file '
|
29
|
+
copy_file 'app/controllers/gatherable/application_controller.rb',
|
30
|
+
'app/controllers/gatherable/application_controller.rb'
|
29
31
|
Gatherable.config.data_tables.each do |data_table|
|
30
32
|
ControllerWriter.new(data_table).write
|
31
33
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
Gatherable.configure do |c|
|
2
2
|
c.global_identifier = :gatherable_id
|
3
3
|
|
4
|
-
|
4
|
+
# c.data_point :data_point_name, :data_point_type, options - see README
|
5
5
|
c.data_point :price, :decimal
|
6
6
|
|
7
|
-
#c.data_table :table_name, { column_name: :column_type, column_name2: :column_type }, options - see README
|
7
|
+
# c.data_table :table_name, { column_name: :column_type, column_name2: :column_type }, options - see README
|
8
8
|
c.data_table :requested_loan_amount, { requested_loan_amount: :decimal, total_cost: :decimal, monthly_repayment_amount: :decimal }
|
9
9
|
|
10
|
-
#
|
11
|
-
#
|
10
|
+
# for both data tables and data points, you'll automatically get a primary key 'table_name_id',
|
11
|
+
# an indexed global identifier, and timestamps
|
12
12
|
|
13
|
-
#If want your db schema to be something besides 'gatherable', uncomment the line below
|
14
|
-
#c.schema_name = 'foo_bar'
|
13
|
+
# If want your db schema to be something besides 'gatherable', uncomment the line below
|
14
|
+
# c.schema_name = 'foo_bar'
|
15
15
|
end
|
@@ -1,64 +1,88 @@
|
|
1
1
|
require 'rails_helper'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
|
3
|
+
describe 'Gatherable::PricesController', :type => :request do
|
4
|
+
|
5
|
+
let(:data_table) { Gatherable.config.data_tables.first }
|
6
|
+
let(:model_name) { data_table.name }
|
7
|
+
let(:model_class) { data_table.classify }
|
8
|
+
let(:controller_class) { data_table.controllerify }
|
9
|
+
let(:global_id) { 'session_id123' }
|
10
|
+
let(:id) { 1 }
|
11
|
+
|
12
|
+
let(:params_prefix) { prefix.blank? ? { "session_id" => global_id } : {} }
|
13
|
+
|
14
|
+
let(:index) { get "/gatherable/#{prefix}#{model_name.to_s.pluralize}.json" }
|
15
|
+
|
16
|
+
let(:show) do
|
17
|
+
get "/gatherable/#{prefix}#{model_name.to_s.pluralize}/#{id}.json"
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:create) do
|
21
|
+
post "/gatherable/#{prefix}#{model_name.to_s.pluralize}.json", params
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:update) do
|
25
|
+
put "/gatherable/#{prefix}#{model_name.to_s.pluralize}/#{id}.json", params
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:destroy) do
|
29
|
+
delete "/gatherable/#{prefix}#{model_name.to_s.pluralize}/#{id}.json"
|
6
30
|
end
|
7
31
|
|
8
32
|
let(:json_response) { JSON.parse(response.body) }
|
9
|
-
let(:model_name) { :price }
|
10
|
-
let(:data_table) { DataTable.find_by_name(model_name) }
|
11
|
-
let(:model_class) { data_table.classify }
|
12
33
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
34
|
+
before do
|
35
|
+
allow(SecureRandom).to receive(:urlsafe_base64) { global_id }
|
36
|
+
allow(data_table).to receive(:allowed_controller_actions) { [:show, :index, :create, :update, :destroy] }
|
37
|
+
@controller = controller_class.new
|
38
|
+
end
|
17
39
|
|
40
|
+
shared_examples "#index" do
|
18
41
|
context 'successful request' do
|
19
|
-
let(:
|
20
|
-
let(:
|
42
|
+
let(:instance) { model_class.new(model_params) }
|
43
|
+
let(:model_params) { { "#{model_name}_id" => 0, model_name.to_s => "3.0"} }
|
21
44
|
|
22
45
|
before do
|
23
|
-
allow(model_class).to receive(:where) { [
|
46
|
+
allow(model_class).to receive(:where) { [instance] }
|
24
47
|
end
|
25
48
|
|
26
|
-
it 'returns a
|
27
|
-
|
49
|
+
it 'returns a 302 response code' do
|
50
|
+
index
|
28
51
|
expect(response.status).to eql 302
|
29
52
|
end
|
30
53
|
|
31
54
|
it 'returns a json array' do
|
32
|
-
|
33
|
-
expect(json_response).to
|
55
|
+
index
|
56
|
+
expect(json_response).to match([a_hash_including(model_params)])
|
34
57
|
end
|
35
58
|
end
|
36
59
|
|
37
60
|
context 'unsuccesful request' do
|
38
|
-
|
61
|
+
context 'no results found' do
|
62
|
+
it 'returns an empty json response' do
|
63
|
+
index
|
64
|
+
expect(json_response).to be_empty
|
65
|
+
end
|
66
|
+
end
|
39
67
|
end
|
40
68
|
end
|
41
69
|
|
42
|
-
|
43
|
-
let(:
|
70
|
+
shared_examples '#show' do
|
71
|
+
let(:instance) { model_class.new(model_params) }
|
72
|
+
let(:model_params) { { model_name.to_s => "3.0", "#{model_name}_id" => id} }
|
44
73
|
|
45
74
|
before do
|
46
|
-
allow(model_class).to receive(:find_by!).with(
|
47
|
-
allow(model_class).to receive(:find_by!).with(
|
48
|
-
end
|
49
|
-
|
50
|
-
def do_get(price_id)
|
51
|
-
get "/gatherable/session_id123/prices/#{price_id}.json"
|
75
|
+
allow(model_class).to receive(:find_by!).with("#{model_name}_id" => id.to_s, :session_id => global_id).and_return(instance)
|
76
|
+
allow(model_class).to receive(:find_by!).with("#{model_name}_id" => '0', :session_id => global_id).and_raise(ActiveRecord::RecordNotFound)
|
52
77
|
end
|
53
78
|
|
54
79
|
context 'record found' do
|
55
80
|
before do
|
56
|
-
|
81
|
+
show
|
57
82
|
end
|
58
83
|
|
59
84
|
it 'returns the record' do
|
60
|
-
expect(json_response).to
|
61
|
-
({"price_id"=>nil, "price"=>"3.0", "session_id" => nil, "created_at"=>nil})
|
85
|
+
expect(json_response).to include(model_params)
|
62
86
|
end
|
63
87
|
|
64
88
|
specify 'the response code is 302' do
|
@@ -67,8 +91,9 @@ describe 'Gatherable::PricesController' do
|
|
67
91
|
end
|
68
92
|
|
69
93
|
context 'record not found' do
|
94
|
+
let(:id) { 0 }
|
70
95
|
before do
|
71
|
-
|
96
|
+
show
|
72
97
|
end
|
73
98
|
|
74
99
|
specify 'the response code is 404' do
|
@@ -81,60 +106,58 @@ describe 'Gatherable::PricesController' do
|
|
81
106
|
end
|
82
107
|
end
|
83
108
|
|
84
|
-
|
85
|
-
def do_post(params)
|
86
|
-
post "/gatherable/session_id123/prices.json", params
|
87
|
-
end
|
109
|
+
shared_examples '#create' do
|
88
110
|
|
89
111
|
shared_examples 'successful object creation' do
|
112
|
+
let(:params) {{ model_name => model_params }}
|
90
113
|
before do
|
91
|
-
model_params.merge!('session_id' =>
|
114
|
+
model_params.merge!('session_id' => global_id)
|
92
115
|
end
|
93
116
|
|
94
117
|
it 'creates an object' do
|
95
118
|
expect(model_class).to receive(:create!).with(model_params)
|
96
|
-
|
119
|
+
create
|
97
120
|
end
|
98
121
|
|
99
122
|
it "contains all attributes of the model" do
|
100
|
-
|
123
|
+
create
|
101
124
|
model_class.column_names.each do |attr|
|
102
125
|
expect(json_response.keys).to include(attr)
|
103
126
|
end
|
104
127
|
end
|
105
128
|
|
106
129
|
it "returns the saved values of the created model" do
|
107
|
-
|
108
|
-
model_params.each do |(attr, val)|
|
130
|
+
create
|
131
|
+
model_params.stringify_keys.each do |(attr, val)|
|
109
132
|
expect(json_response[attr]).to eql val
|
110
133
|
end
|
111
134
|
end
|
112
135
|
|
113
136
|
it 'adds a timestamp to the record' do
|
114
|
-
|
137
|
+
create
|
115
138
|
expect(json_response['created_at']).to_not be_nil
|
116
139
|
end
|
117
140
|
|
118
141
|
specify 'the object created is valid' do
|
119
|
-
|
120
|
-
expect(
|
142
|
+
create
|
143
|
+
expect(instance).to be_valid
|
121
144
|
end
|
122
145
|
|
123
146
|
specify 'status is 201' do
|
124
|
-
|
147
|
+
create
|
125
148
|
expect(response.status).to eql 201
|
126
149
|
end
|
127
150
|
|
128
151
|
context 'new_record_strategy = :update' do
|
129
152
|
before do
|
130
|
-
allow(
|
153
|
+
allow(data_table).to receive(:new_record_strategy).and_return :update
|
131
154
|
end
|
132
155
|
|
133
156
|
context 'updating existing record' do
|
134
157
|
let!(:existing_record) { model_class.create(model_name => '76', :session_id => 'session_id123') }
|
135
158
|
|
136
159
|
it 'sets correct values' do
|
137
|
-
|
160
|
+
create
|
138
161
|
existing_record.reload
|
139
162
|
model_params.each do |(attr, val)|
|
140
163
|
expect(existing_record.send(attr).to_s).to eql val
|
@@ -142,126 +165,135 @@ describe 'Gatherable::PricesController' do
|
|
142
165
|
end
|
143
166
|
|
144
167
|
it 'does not create a new record' do
|
145
|
-
expect{
|
168
|
+
expect{create}.to_not change{model_class.count}
|
146
169
|
end
|
147
170
|
end
|
148
171
|
|
149
172
|
context 'creating new record' do
|
150
173
|
it 'creates a valid record' do
|
151
|
-
expect{
|
174
|
+
expect{create}.to change{model_class.count}.by 1
|
152
175
|
end
|
153
176
|
end
|
154
177
|
|
155
178
|
specify 'status is 200' do
|
156
|
-
|
179
|
+
create
|
157
180
|
expect(response.status).to eql 200
|
158
181
|
end
|
159
182
|
end
|
160
183
|
end
|
161
184
|
|
162
185
|
context 'correct param format' do
|
163
|
-
let(:model_params) { {
|
164
|
-
let(:
|
165
|
-
let(:price) { model_class.new(model_params.merge(:session_id => 'session_id123')) }
|
186
|
+
let(:model_params) { { model_name => "3.0"} }
|
187
|
+
let(:instance) { model_class.new(model_params) }
|
166
188
|
it_behaves_like 'successful object creation'
|
167
189
|
end
|
168
190
|
|
169
|
-
context 'auth_method set' do
|
170
|
-
let(:model_params) { { "price" => "3.0"} }
|
171
|
-
let(:passed_params) { {:price => model_params} }
|
172
|
-
let(:model_name) { :price }
|
173
|
-
context 'session identifier matches passed identifier' do
|
174
|
-
before do
|
175
|
-
allow(Gatherable.config).to receive(:auth_method) { :session }
|
176
|
-
session[:session_id] = 'session_id123'
|
177
|
-
allow_any_instance_of(@controller.class).to receive(:session) { session } #boo any_instance
|
178
|
-
end
|
179
|
-
let(:price) { model_class.new(model_params.merge(:session_id => 'session_id123')) }
|
180
|
-
it_behaves_like 'successful object creation'
|
181
|
-
end
|
182
|
-
|
183
|
-
context 'session identifier does not match passed identifier' do
|
184
|
-
before do
|
185
|
-
allow(Gatherable.config).to receive(:auth_method) { :session }
|
186
|
-
do_post(passed_params)
|
187
|
-
end
|
188
|
-
|
189
|
-
it 'returns an empty response body' do
|
190
|
-
expect(response.body).to be_empty
|
191
|
-
end
|
192
|
-
|
193
|
-
it 'gives an unauthorized response status' do
|
194
|
-
expect(response.status).to eql 401
|
195
|
-
end
|
196
|
-
|
197
|
-
it 'does not create an object' do
|
198
|
-
expect(model_class).to_not receive(:create!)
|
199
|
-
do_post(passed_params)
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
191
|
|
204
192
|
context 'incorrect param format' do
|
205
193
|
context 'required params not given' do
|
194
|
+
let(:params) { { :yolo => 'swag' } }
|
206
195
|
specify 'the response status is 422' do
|
207
|
-
|
196
|
+
create
|
208
197
|
expect(response.status).to eql 422
|
209
198
|
end
|
210
199
|
end
|
211
200
|
|
212
201
|
context 'required params + junk params given' do
|
213
|
-
let(:model_params) { {
|
202
|
+
let(:model_params) { { model_name => "3.0"} }
|
214
203
|
let(:junk_params) { { 'yolo' => 'swag' } }
|
215
|
-
let(:
|
216
|
-
let(:
|
204
|
+
let(:params) { { model_name => model_params.merge(junk_params)}.merge(junk_params) }
|
205
|
+
let(:instance) { model_class.new(model_params.merge(:session_id => 'session_id123')) }
|
217
206
|
it_behaves_like 'successful object creation'
|
218
207
|
end
|
219
208
|
end
|
220
209
|
end
|
221
210
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
211
|
+
shared_examples '#update' do
|
212
|
+
describe '#update' do
|
213
|
+
let(:model_params) { { model_name => '3.0', "#{model_name}_id" => id } }
|
214
|
+
let(:instance) { model_class.new(model_params) }
|
215
|
+
let(:params) { { model_name => { model_name => '4.0' } } }
|
226
216
|
|
227
|
-
|
228
|
-
|
229
|
-
|
217
|
+
context 'successful request' do
|
218
|
+
before do
|
219
|
+
instance.save!
|
220
|
+
update
|
221
|
+
end
|
230
222
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
223
|
+
it 'updates the record' do
|
224
|
+
expect(instance.reload.send(model_name.to_sym).to_s).to eql '4.0'
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'renders an updated version of the record' do
|
228
|
+
expect(json_response).to include( {model_name.to_s => '4.0'} )
|
229
|
+
end
|
235
230
|
end
|
236
231
|
|
237
|
-
|
238
|
-
|
232
|
+
context 'with invalid data' do
|
233
|
+
let(:params) { { model_name => Date.today } }
|
234
|
+
|
235
|
+
before do
|
236
|
+
allow(model_class).to receive(:find_by!).and_return(instance)
|
237
|
+
update
|
238
|
+
end
|
239
|
+
|
240
|
+
specify 'the response code is 422' do
|
241
|
+
expect(response.status).to eql 422
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'returns errors' do
|
245
|
+
expect(json_response).to have_key('errors')
|
246
|
+
end
|
239
247
|
end
|
240
248
|
|
241
|
-
|
242
|
-
|
249
|
+
context 'record not found' do
|
250
|
+
let(:id) { 0 }
|
251
|
+
let(:params) { {} }
|
252
|
+
before do
|
253
|
+
update
|
254
|
+
end
|
255
|
+
|
256
|
+
specify 'the response code is 404' do
|
257
|
+
expect(response.status).to eql 404
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'returns errors' do
|
261
|
+
expect(json_response).to eql({"errors"=>"Couldn't find Gatherable::#{model_name.to_s.classify}"})
|
262
|
+
end
|
243
263
|
end
|
244
264
|
end
|
265
|
+
end
|
245
266
|
|
246
|
-
|
267
|
+
shared_examples '#destroy' do
|
268
|
+
let(:model_params) { { model_name => '3.0' } }
|
269
|
+
let(:instance) { model_class.new(model_params.merge(:session_id => 'session_id123')) }
|
270
|
+
let(:id) { instance.reload.id }
|
247
271
|
|
272
|
+
context 'successful request' do
|
248
273
|
before do
|
249
|
-
|
250
|
-
|
274
|
+
instance.save!
|
275
|
+
id
|
276
|
+
destroy
|
251
277
|
end
|
252
278
|
|
253
|
-
|
254
|
-
expect(
|
279
|
+
it 'deletes the record' do
|
280
|
+
expect(model_class.where("#{model_name}_id" => id)).to be_empty
|
255
281
|
end
|
256
282
|
|
257
|
-
it '
|
258
|
-
expect(
|
283
|
+
it 'renders nothing' do
|
284
|
+
expect(response.body).to be_empty
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'has a successful response code' do
|
288
|
+
expect(response.status).to eql 204
|
259
289
|
end
|
260
290
|
end
|
261
291
|
|
262
292
|
context 'record not found' do
|
293
|
+
let(:id) { 0 }
|
294
|
+
|
263
295
|
before do
|
264
|
-
|
296
|
+
destroy
|
265
297
|
end
|
266
298
|
|
267
299
|
specify 'the response code is 404' do
|
@@ -269,46 +301,128 @@ describe 'Gatherable::PricesController' do
|
|
269
301
|
end
|
270
302
|
|
271
303
|
it 'returns errors' do
|
272
|
-
expect(json_response).to eql({"errors"=>"Couldn't find Gatherable
|
304
|
+
expect(json_response).to eql({"errors"=>"Couldn't find Gatherable::#{model_name.to_s.classify}"})
|
273
305
|
end
|
274
306
|
end
|
275
307
|
end
|
276
308
|
|
277
|
-
|
278
|
-
let(:
|
279
|
-
let(:bad_params) { { 'price' => 'free' } }
|
280
|
-
let(:model_params) { { 'price' => '3.0' } }
|
309
|
+
shared_examples 'auth failed' do
|
310
|
+
let(:prefix) { "#{global_id}123/" }
|
281
311
|
|
282
|
-
|
283
|
-
|
312
|
+
before do
|
313
|
+
allow(Gatherable.config).to receive(:auth_method) { :session }
|
314
|
+
allow_any_instance_of(@controller.class).to receive(:session) { {:session_id => global_id } }
|
315
|
+
perform_request.call
|
284
316
|
end
|
285
317
|
|
286
|
-
|
287
|
-
|
288
|
-
|
318
|
+
it 'returns an empty body' do
|
319
|
+
expect(response.body).to be_empty
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'returns a response status of unauthorized' do
|
323
|
+
expect(response.status).to eql 401
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
context 'unique identifier required in route' do
|
328
|
+
let(:prefix) { "#{global_id}/" }
|
329
|
+
|
330
|
+
before do
|
331
|
+
allow(Gatherable.config).to receive(:prefixed_resources) { [data_table.name] }
|
332
|
+
Gatherable::RouteDrawer.draw
|
333
|
+
end
|
334
|
+
|
335
|
+
it_behaves_like '#index' do
|
336
|
+
it_behaves_like 'auth failed' do
|
337
|
+
let(:perform_request) { Proc.new{index} }
|
289
338
|
end
|
339
|
+
end
|
290
340
|
|
291
|
-
|
292
|
-
|
293
|
-
|
341
|
+
it_behaves_like '#show' do
|
342
|
+
it_behaves_like 'auth failed' do
|
343
|
+
let(:perform_request) { Proc.new{index} }
|
294
344
|
end
|
345
|
+
end
|
295
346
|
|
296
|
-
|
297
|
-
|
347
|
+
it_behaves_like '#create' do
|
348
|
+
it_behaves_like 'auth failed' do
|
349
|
+
let(:perform_request) { Proc.new{ create } }
|
350
|
+
let(:params) { {} }
|
351
|
+
|
352
|
+
it 'does not create an object' do
|
353
|
+
expect{perform_request.call}.to_not change{model_class.count}
|
354
|
+
end
|
298
355
|
end
|
299
356
|
end
|
300
357
|
|
301
|
-
|
358
|
+
it_behaves_like '#update' do
|
359
|
+
it_behaves_like 'auth failed' do
|
360
|
+
let(:perform_request) { Proc.new{ update } }
|
361
|
+
let(:params) { {} }
|
362
|
+
let(:instance) { model_class.new(model_name => '3.0', :session_id => global_id) }
|
363
|
+
let!(:id) { instance.save!; instance.reload.id }
|
364
|
+
|
365
|
+
before do
|
366
|
+
allow(model_class).to receive(:find_by!) { instance }
|
367
|
+
end
|
368
|
+
|
369
|
+
it 'does not update the instance' do
|
370
|
+
perform_request.call
|
371
|
+
expect(instance).to eql instance.reload
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
it_behaves_like '#destroy' do
|
377
|
+
it_behaves_like 'auth failed' do
|
378
|
+
let(:perform_request) { Proc.new{ destroy } }
|
379
|
+
let(:instance) { model_class.new(model_name => '3.0', :session_id => global_id) }
|
380
|
+
let!(:id) { instance.save!; instance.reload.id }
|
381
|
+
|
382
|
+
before do
|
383
|
+
allow(model_class).to receive(:find_by!) { instance }
|
384
|
+
end
|
385
|
+
|
386
|
+
it 'does not delete the instance' do
|
387
|
+
expect{perform_request.call}.to_not change{instance.persisted?}
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
context 'unique identifier not required in route' do
|
394
|
+
let(:prefix) { '' }
|
395
|
+
|
396
|
+
before do
|
397
|
+
allow(Gatherable.config).to receive(:prefixed_resources) { [] }
|
398
|
+
Gatherable::RouteDrawer.draw
|
399
|
+
end
|
400
|
+
|
401
|
+
it_behaves_like '#index'
|
402
|
+
it_behaves_like '#show'
|
403
|
+
it_behaves_like '#create'
|
404
|
+
it_behaves_like '#update'
|
405
|
+
it_behaves_like '#destroy'
|
406
|
+
end
|
407
|
+
|
408
|
+
[:index, :show, :create, :update, :destroy].each do |disallowed_action|
|
409
|
+
context "#{disallowed_action} not allowed" do
|
410
|
+
let(:all_actions) { [:index, :show, :create, :update, :destroy] }
|
411
|
+
let(:prefix) { }
|
412
|
+
let(:params) { {} }
|
413
|
+
|
302
414
|
before do
|
303
|
-
|
415
|
+
allow(data_table).to receive(:allowed_controller_actions).and_return(all_actions - [disallowed_action])
|
416
|
+
Gatherable::RouteDrawer.draw
|
304
417
|
end
|
305
418
|
|
306
|
-
specify
|
307
|
-
expect(
|
419
|
+
specify "sending #{disallowed_action} raises error" do
|
420
|
+
expect{send(disallowed_action)}.to raise_error(ActionController::RoutingError)
|
308
421
|
end
|
309
422
|
|
310
|
-
|
311
|
-
|
423
|
+
after do
|
424
|
+
allow(data_table).to receive(:allowed_controller_actions) { all_actions }
|
425
|
+
Gatherable::RouteDrawer.draw
|
312
426
|
end
|
313
427
|
end
|
314
428
|
end
|