intermodal 0.0.1 → 0.4.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 +7 -0
- data/.gitignore +8 -0
- data/Gemfile +4 -0
- data/LICENSE +1 -1
- data/README +6 -4
- data/Rakefile +6 -0
- data/intermodal.gemspec +51 -0
- data/lib/generators/intermodal_generator.rb +8 -0
- data/lib/intermodal.rb +122 -0
- data/lib/intermodal/api.rb +246 -0
- data/lib/intermodal/api/configuration.rb +40 -0
- data/lib/intermodal/api/railties.rb +21 -0
- data/lib/intermodal/concerns/acceptors/named_resource.rb +12 -0
- data/lib/intermodal/concerns/acceptors/resource.rb +12 -0
- data/lib/intermodal/concerns/controllers/accountability.rb +17 -0
- data/lib/intermodal/concerns/controllers/anonymous.rb +24 -0
- data/lib/intermodal/concerns/controllers/authenticatable.rb +24 -0
- data/lib/intermodal/concerns/controllers/paginated_collection.rb +25 -0
- data/lib/intermodal/concerns/controllers/presentation.rb +17 -0
- data/lib/intermodal/concerns/controllers/resource.rb +51 -0
- data/lib/intermodal/concerns/controllers/resource_linking.rb +58 -0
- data/lib/intermodal/concerns/let.rb +21 -0
- data/lib/intermodal/concerns/models/access_credential.rb +28 -0
- data/lib/intermodal/concerns/models/account.rb +16 -0
- data/lib/intermodal/concerns/models/accountability.rb +47 -0
- data/lib/intermodal/concerns/models/db_access_token.rb +29 -0
- data/lib/intermodal/concerns/models/has_parent_resource.rb +45 -0
- data/lib/intermodal/concerns/models/presentation.rb +25 -0
- data/lib/intermodal/concerns/models/redis_access_token.rb +60 -0
- data/lib/intermodal/concerns/models/resource_linking.rb +126 -0
- data/lib/intermodal/concerns/models/sanitize_html.rb +35 -0
- data/lib/intermodal/concerns/presenters/named_resource.rb +12 -0
- data/lib/intermodal/concerns/presenters/resource.rb +14 -0
- data/lib/intermodal/concerns/rails/rails_3_stack.rb +42 -0
- data/lib/intermodal/concerns/rails/rails_4_stack.rb +17 -0
- data/lib/intermodal/concerns/rails/use_warden.rb +21 -0
- data/lib/intermodal/config.rb +15 -0
- data/lib/intermodal/configuration.rb +11 -0
- data/lib/intermodal/controllers/api_controller.rb +26 -0
- data/lib/intermodal/controllers/linking_resource_controller.rb +8 -0
- data/lib/intermodal/controllers/nested_resource_controller.rb +18 -0
- data/lib/intermodal/controllers/resource_controller.rb +11 -0
- data/lib/intermodal/dsl/controllers.rb +125 -0
- data/lib/intermodal/dsl/mapping.rb +79 -0
- data/lib/intermodal/dsl/presentation_helpers.rb +107 -0
- data/lib/intermodal/mapping/acceptor.rb +2 -2
- data/lib/intermodal/mapping/mapper.rb +39 -13
- data/lib/intermodal/mapping/presenter.rb +12 -6
- data/lib/intermodal/proxies/linking_resources.rb +58 -0
- data/lib/intermodal/proxies/will_paginate.rb +85 -0
- data/lib/intermodal/rack/auth.rb +29 -0
- data/lib/intermodal/rack/dummy_store.rb +24 -0
- data/lib/intermodal/rack/rescue.rb +82 -0
- data/lib/intermodal/responders/linking_resource_responder.rb +21 -0
- data/lib/intermodal/responders/resource_responder.rb +64 -0
- data/lib/intermodal/rspec/acceptors.rb +79 -0
- data/lib/intermodal/rspec/models/accountability.rb +114 -0
- data/lib/intermodal/rspec/models/has_parent_resource.rb +132 -0
- data/lib/intermodal/rspec/models/resource_linking.rb +234 -0
- data/lib/intermodal/rspec/models/sanitization.rb +84 -0
- data/lib/intermodal/rspec/presenters.rb +92 -0
- data/lib/intermodal/rspec/requests/authenticated_requests.rb +17 -0
- data/lib/intermodal/rspec/requests/linked_resources.rb +180 -0
- data/lib/intermodal/rspec/requests/paginated_collection.rb +60 -0
- data/lib/intermodal/rspec/requests/rack.rb +142 -0
- data/lib/intermodal/rspec/requests/request_validations.rb +36 -0
- data/lib/intermodal/rspec/requests/resources.rb +275 -0
- data/lib/intermodal/rspec/requests/rfc2616_status_codes.rb +51 -0
- data/lib/intermodal/rspec/validators.rb +86 -0
- data/lib/intermodal/validators/account_validator.rb +27 -0
- data/lib/intermodal/validators/different_account_validator.rb +27 -0
- data/lib/intermodal/version.rb +3 -0
- data/spec/mapping/acceptors_spec.rb +142 -0
- data/spec/mapping/presenters_spec.rb +186 -0
- data/spec/models/accountability_spec.rb +13 -0
- data/spec/models/has_parent_resource_spec.rb +18 -0
- data/spec/models/resource_linking_spec.rb +21 -0
- data/spec/proxies/will_paginate_spec.rb +163 -0
- data/spec/rack/auth_spec.rb +51 -0
- data/spec/requests/linked_resources.rb +37 -0
- data/spec/requests/nested_resources_spec.rb +54 -0
- data/spec/requests/resources_spec.rb +50 -0
- data/spec/spec_helper.rb +53 -0
- data/spec/support/api.rb +50 -0
- data/spec/support/app/class_builder.rb +41 -0
- data/spec/support/app/db/adapter_helper.rb +53 -0
- data/spec/support/app/db/authentication_schema_helper.rb +62 -0
- data/spec/support/app/db/migration_helper.rb +44 -0
- data/spec/support/app/schema.rb +101 -0
- data/spec/support/application.rb +23 -0
- data/spec/support/blueprints.rb +41 -0
- data/spec/support/epiphyte.rb +29 -0
- metadata +393 -52
- data/lib/intermodal/base.rb +0 -13
- data/lib/intermodal/declare_controllers.rb +0 -102
- data/lib/intermodal/mapping.rb +0 -4
- data/lib/intermodal/mapping/dsl.rb +0 -76
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'active_model/validator'
|
|
2
|
+
|
|
3
|
+
module Intermodal
|
|
4
|
+
module Validators
|
|
5
|
+
# Validates the associated resource is owned by the same account
|
|
6
|
+
# Examples:
|
|
7
|
+
#
|
|
8
|
+
# validates parent_id, account: true
|
|
9
|
+
# validates parent_id, account: { through: association }
|
|
10
|
+
#
|
|
11
|
+
class AccountValidator < ActiveModel::EachValidator
|
|
12
|
+
def validate_each(record, attribute, value)
|
|
13
|
+
return if value.nil?
|
|
14
|
+
association_name = options[:through] || attribute.to_s.gsub(/_id/, '')
|
|
15
|
+
return if record.send(association_name).account_id == record.account_id
|
|
16
|
+
record.errors[attribute] << message
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def message
|
|
20
|
+
options[:message] || 'must belong to the same account'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
AccountValidator = Intermodal::Validators::AccountValidator unless defined? AccountValidator
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'active_model/validator'
|
|
2
|
+
|
|
3
|
+
module Intermodal
|
|
4
|
+
module Validators
|
|
5
|
+
# Validates the associated resource is owned by a different account
|
|
6
|
+
# Examples:
|
|
7
|
+
#
|
|
8
|
+
# validates parent_id, different_account: true
|
|
9
|
+
# validates parent_id, different_account: { through: association }
|
|
10
|
+
#
|
|
11
|
+
class DifferentAccountValidator < ActiveModel::EachValidator
|
|
12
|
+
def validate_each(record, attribute, value)
|
|
13
|
+
return if value.nil?
|
|
14
|
+
association_name = options[:through] || attribute.to_s.gsub(/_id/, '')
|
|
15
|
+
return if record.send(association_name).account_id != record.account_id
|
|
16
|
+
record.errors[attribute] << message
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def message
|
|
20
|
+
options[:message] || 'must belong to a different account'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
DifferentAccountValidator = Intermodal::Validators::DifferentAccountValidator unless defined? DifferentAccountValidator
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Intermodal::Mapping::Acceptor do
|
|
4
|
+
include SpecHelpers::ClassBuilder
|
|
5
|
+
|
|
6
|
+
describe '.call' do
|
|
7
|
+
subject { acceptor.call(params) }
|
|
8
|
+
|
|
9
|
+
context 'with pass-through mappings' do
|
|
10
|
+
let(:acceptor) do
|
|
11
|
+
define_class :TestAcceptor, Intermodal::Mapping::Acceptor do
|
|
12
|
+
accepts :acceptable_field
|
|
13
|
+
accepts :optional_field
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
let(:value) { 'Accepted Field' }
|
|
18
|
+
let(:params) { { :acceptable_field => value, :unacceptable_field => true } }
|
|
19
|
+
|
|
20
|
+
it 'should accept explicitly whitelisted fields' do
|
|
21
|
+
should include(:acceptable_field)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'should pass through value without transformation' do
|
|
25
|
+
subject[:acceptable_field].should eql(value)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should not accept undeclared fields' do
|
|
29
|
+
should_not include(:unacceptable_field)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context 'without optional field in params' do
|
|
33
|
+
# Since we pass the output of an acceptor directly into
|
|
34
|
+
# the active record #create or #update_attributes, we want
|
|
35
|
+
# the hash to look like:
|
|
36
|
+
#
|
|
37
|
+
# { :acceptable_fields => 'Something' }
|
|
38
|
+
#
|
|
39
|
+
# rather than
|
|
40
|
+
#
|
|
41
|
+
# { :acceptable_field => 'Something', :optional_field => nil }
|
|
42
|
+
#
|
|
43
|
+
# Doing so will update the resource and null out the fields that
|
|
44
|
+
# have not been passed through params.
|
|
45
|
+
it 'should not include the optional field' do
|
|
46
|
+
should_not include(:optional_field)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'with optional field in params' do
|
|
51
|
+
let(:params) { { :acceptable_field => value, :optional_field => value } }
|
|
52
|
+
|
|
53
|
+
it 'should include the optional field' do
|
|
54
|
+
should include(:optional_field)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'should pass through value without transformation' do
|
|
58
|
+
subject[:optional_field].should eql(value)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'with pass-through alias mappings' do
|
|
64
|
+
let(:acceptor) do
|
|
65
|
+
define_class :TestAcceptor, Intermodal::Mapping::Acceptor do
|
|
66
|
+
accepts :name, :with => :full_name
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
let(:value) { 'Henry Deacon' }
|
|
71
|
+
let(:params) { { :full_name => value } }
|
|
72
|
+
|
|
73
|
+
it 'should present explicitly whitelisted fields' do
|
|
74
|
+
should include(:name)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'should pass through value without transformation' do
|
|
78
|
+
subject[:name].should eql(params[:full_name])
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'should not present undeclared fields' do
|
|
82
|
+
should_not include(:full_name)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context 'with nested mappings' do
|
|
87
|
+
let(:acceptor) do
|
|
88
|
+
define_class :TestAcceptor, Intermodal::Mapping::Acceptor do
|
|
89
|
+
# Use this to create nested parameters from flattened parameters
|
|
90
|
+
accepts :name, :with => [ :first_name, :last_name ]
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
let(:first_name) { 'Henry' }
|
|
95
|
+
let(:last_name) { 'Deacon' }
|
|
96
|
+
let(:params) { { :first_name => first_name, :last_name => last_name } }
|
|
97
|
+
|
|
98
|
+
it 'should merge fields into a single hash of fields' do
|
|
99
|
+
should include(:name)
|
|
100
|
+
subject[:name].should include(:first_name)
|
|
101
|
+
subject[:name].should include(:last_name)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'should merge fields without transforming its value' do
|
|
105
|
+
subject[:name][:first_name].should eql(first_name)
|
|
106
|
+
subject[:name][:last_name].should eql(last_name)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Unless you've explicitly declared the merged fields, it should
|
|
110
|
+
# not include it.
|
|
111
|
+
it 'should not accept merged fields' do
|
|
112
|
+
should_not include(:first_name)
|
|
113
|
+
should_not include(:last_name)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'with arbitrary mappings' do
|
|
118
|
+
let(:acceptor) do
|
|
119
|
+
define_class :TestAcceptor, Intermodal::Mapping::Acceptor do
|
|
120
|
+
# This lets you use aribrary functions to map out accepted fields.
|
|
121
|
+
# Beware! For many use-cases, declaring these in the model works better.
|
|
122
|
+
# Beware! Do not use functions with side-effects
|
|
123
|
+
accepts :phone_number, :with => lambda { |o| o[:phone_number].gsub(/[^0-9]/, '') }
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
let(:value) { '555-555-5555' }
|
|
128
|
+
let(:params) { { :phone_number => value } }
|
|
129
|
+
|
|
130
|
+
it 'should accept an arbitrary mapping' do
|
|
131
|
+
should include(:phone_number)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'should transform the value' do
|
|
135
|
+
subject[:phone_number].should_not eql(value)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
pending 'with scoped acceptor'
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Intermodal::Mapping::Presenter do
|
|
4
|
+
include SpecHelpers::ClassBuilder
|
|
5
|
+
include SpecHelpers::Application
|
|
6
|
+
|
|
7
|
+
describe '.call' do
|
|
8
|
+
subject { presenter.call(resource) }
|
|
9
|
+
let(:resource) { item }
|
|
10
|
+
|
|
11
|
+
context 'with pass-through mappings' do
|
|
12
|
+
let(:presenter) do
|
|
13
|
+
define_class :TestPresenter, Intermodal::Mapping::Presenter do
|
|
14
|
+
presents :name
|
|
15
|
+
presents :description
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'should present explicitly whitelisted fields' do
|
|
20
|
+
should include(:name)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should pass through value without transformation' do
|
|
24
|
+
subject[:name].should eql(resource.name)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should present all declared fields regardless of value' do
|
|
28
|
+
should include(:description)
|
|
29
|
+
subject[:description].should be_nil
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context 'with pass-through alias mappings' do
|
|
34
|
+
let(:presenter) do
|
|
35
|
+
define_class :TestPresenter, Intermodal::Mapping::Presenter do
|
|
36
|
+
presents :full_name, :with => :name
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'should present explicitly whitelisted fields' do
|
|
41
|
+
should include(:full_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'should pass through value without transformation' do
|
|
45
|
+
subject[:full_name].should eql(resource.name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'should not present undeclared fields' do
|
|
49
|
+
should_not include(:name)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'with nested mappings' do
|
|
54
|
+
let(:presenter) do
|
|
55
|
+
define_class :TestPresenter, Intermodal::Mapping::Presenter do
|
|
56
|
+
|
|
57
|
+
# Use this to create nested presentation
|
|
58
|
+
presents :metadata, :with => [ :name, :description ]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
let(:resource) { Item.make(:name => name, :description => description) }
|
|
63
|
+
let(:name) { 'Weird Eureka Thing' }
|
|
64
|
+
let(:description) { 'Makes Eureka Go Boom!' }
|
|
65
|
+
|
|
66
|
+
it 'should merge fields into a single hash of fields' do
|
|
67
|
+
should include(:metadata)
|
|
68
|
+
subject[:metadata].should include(:name)
|
|
69
|
+
subject[:metadata].should include(:description)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should merge fields without transforming its value' do
|
|
73
|
+
subject[:metadata][:name].should eql(name)
|
|
74
|
+
subject[:metadata][:description].should eql(description)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Unless you've explicitly declared the merged fields, it should
|
|
78
|
+
# not present it.
|
|
79
|
+
it 'should not present undeclared fields' do
|
|
80
|
+
should_not include(:name)
|
|
81
|
+
should_not include(:description)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
pending 'with always_nest_collection'
|
|
86
|
+
context 'with arbitrary mappings' do
|
|
87
|
+
let(:presenter) do
|
|
88
|
+
define_class :TestPresenter, Intermodal::Mapping::Presenter do
|
|
89
|
+
# This lets you use aribrary functions to map out accepted fields.
|
|
90
|
+
# Beware! For many use-cases, declaring these in the model works better.
|
|
91
|
+
# Beware! Do not use functions with side-effects
|
|
92
|
+
presents :name, :with => lambda { |o| o[:name].upcase }
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'should accept an arbitrary mapping' do
|
|
97
|
+
should include(:name)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'should transform the value' do
|
|
101
|
+
subject[:name].should_not eql(resource.name)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
context 'when scoping' do
|
|
106
|
+
subject { presenter.call(resource, :scope => scope) }
|
|
107
|
+
|
|
108
|
+
context 'without scope declaration' do
|
|
109
|
+
let(:scope) { :default }
|
|
110
|
+
let(:presenter) do
|
|
111
|
+
define_class :TestPresenter, Intermodal::Mapping::Presenter do
|
|
112
|
+
presents :name
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'should default to :default scope' do
|
|
117
|
+
should include(:name)
|
|
118
|
+
subject[:name].should eql(resource.name)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context 'with mixed scopes' do
|
|
123
|
+
let(:scope) { :default }
|
|
124
|
+
let(:presenter) do
|
|
125
|
+
define_class :TestPresenter, Intermodal::Mapping::Presenter do
|
|
126
|
+
presents :name
|
|
127
|
+
presents :description, :scope => :details
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
let(:resource) { Item.make(:name => name, :description => description) }
|
|
132
|
+
let(:name) { 'Weird Eureka Thing' }
|
|
133
|
+
let(:description) { 'Makes Eureka Go Boom!' }
|
|
134
|
+
|
|
135
|
+
it 'should default to :default scope' do
|
|
136
|
+
should include(:name)
|
|
137
|
+
subject[:name].should eql(resource.name)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'should not present attributes outside of scope' do
|
|
141
|
+
should_not include(:description)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
context 'when called with non-default scope' do
|
|
145
|
+
let(:scope) { :details }
|
|
146
|
+
|
|
147
|
+
it 'should include non-overlapping attributes from default scope' do
|
|
148
|
+
should include(:name)
|
|
149
|
+
subject[:name].should eql(resource.name)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it 'should present attributes from non-default scope' do
|
|
153
|
+
should include(:description)
|
|
154
|
+
subject[:description].should eql(resource.description)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context 'with overlapping scopes' do
|
|
160
|
+
let(:scope) { :default }
|
|
161
|
+
let(:presenter) do
|
|
162
|
+
define_class :TestPresenter, Intermodal::Mapping::Presenter do
|
|
163
|
+
presents :name
|
|
164
|
+
presents :name, :with => lambda { |o| 'boo!' }, :scope => :details
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'should default to :default scope' do
|
|
169
|
+
should include(:name)
|
|
170
|
+
subject[:name].should eql(resource.name)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
context 'when called with non-default scope' do
|
|
174
|
+
let(:scope) { :details }
|
|
175
|
+
|
|
176
|
+
it 'should present attributes from non-default scope' do
|
|
177
|
+
should include(:name)
|
|
178
|
+
subject[:name].should_not eql(resource.name)
|
|
179
|
+
subject[:name].should eql('boo!')
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Intermodal::Models::Accountability do
|
|
4
|
+
context 'when implemented as a resource' do
|
|
5
|
+
include SpecHelpers::Application
|
|
6
|
+
include Intermodal::RSpec::Accountability
|
|
7
|
+
|
|
8
|
+
subject { item }
|
|
9
|
+
implements_get_interface
|
|
10
|
+
|
|
11
|
+
pending 'should belong to account model'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Intermodal::Models::HasParentResource do
|
|
4
|
+
context 'when implemented as a resource' do
|
|
5
|
+
include SpecHelpers::Application
|
|
6
|
+
include Intermodal::RSpec::HasParentResource
|
|
7
|
+
|
|
8
|
+
subject { part }
|
|
9
|
+
let(:parent_resource_name) { :item }
|
|
10
|
+
let(:different_parent) { Item.make!(:account => account) }
|
|
11
|
+
let(:parent_with_different_account) { Item.make!(:account => different_account) }
|
|
12
|
+
let(:different_account) { Account.make! }
|
|
13
|
+
|
|
14
|
+
implements_get_interface_for_nested_resource
|
|
15
|
+
|
|
16
|
+
pending 'should belong to parent model'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Intermodal::Models::ResourceLinking do
|
|
4
|
+
context 'when implemented as a resource' do
|
|
5
|
+
include SpecHelpers::Application
|
|
6
|
+
include Intermodal::RSpec::ResourceLinking
|
|
7
|
+
|
|
8
|
+
subject { sku }
|
|
9
|
+
|
|
10
|
+
let(:model) { Sku }
|
|
11
|
+
let(:skus) { item.vendors << vendors }
|
|
12
|
+
|
|
13
|
+
# Protip: sku, item, and vendors can be defined in a global helper, such as SpecHelpers::Application
|
|
14
|
+
let(:sku) { Sku.create(:item => item, :vendor => vendor) }
|
|
15
|
+
let(:item) { Item.make!(:account => account) }
|
|
16
|
+
let(:vendor) { Vendor.make!(:account => account) }
|
|
17
|
+
let(:vendors) { (1..3).map { Vendor.make!(:account => account) } }
|
|
18
|
+
|
|
19
|
+
concerned_with_resource_linking :item, :vendor, :skip_association_examples => true, :skip_validation_examples => true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Intermodal::Proxies::WillPaginate::Collection do
|
|
4
|
+
include Intermodal::RSpec::Resources
|
|
5
|
+
include SpecHelpers::Application
|
|
6
|
+
include SpecHelpers::API
|
|
7
|
+
|
|
8
|
+
let(:api_class) do
|
|
9
|
+
define_class :Api, Rails::Engine do
|
|
10
|
+
include Intermodal::API
|
|
11
|
+
include SpecHelpers::Epiphyte
|
|
12
|
+
|
|
13
|
+
map_data do
|
|
14
|
+
presentation_for :item do
|
|
15
|
+
presents :id
|
|
16
|
+
presents :name
|
|
17
|
+
presents :description
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
controllers do
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
routes.draw do
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe '#as_json' do
|
|
30
|
+
before(:each) { api_class.load_presentations! }
|
|
31
|
+
subject { presented_collection }
|
|
32
|
+
|
|
33
|
+
let(:presenter) { api_class.presenters[:item] }
|
|
34
|
+
let(:collection) { Item.make!(3, :account => account) }
|
|
35
|
+
let(:paginated_collection) { collection; Item.paginate :page => 1 }
|
|
36
|
+
let(:presented_collection) { paginated_collection.as_json presenter_options }
|
|
37
|
+
|
|
38
|
+
let(:collection_ids) { collection.map(&:id) }
|
|
39
|
+
|
|
40
|
+
let(:_ids) { ->(r) { r[:id] } }
|
|
41
|
+
let(:presented_collection_ids) { presented_collection[:collection].map(&_ids) }
|
|
42
|
+
|
|
43
|
+
context 'with presenter default options' do
|
|
44
|
+
let(:presenter_options) { { :presenter => presenter } }
|
|
45
|
+
|
|
46
|
+
it 'should present page' do
|
|
47
|
+
subject[:page].should_not be_nil
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'should present per_page' do
|
|
51
|
+
subject[:per_page].should_not be_nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'should present total_pages' do
|
|
55
|
+
subject[:total_pages].should_not be_nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'should present total_entries' do
|
|
59
|
+
subject[:total_entries].should_not be_nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'should present collection' do
|
|
63
|
+
subject[:collection].should_not be_nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should present collection of resources' do
|
|
67
|
+
presented_collection_ids.should eql(collection_ids)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context 'with root option' do
|
|
72
|
+
let(:presenter_options) { { :presenter => presenter, :root => root } }
|
|
73
|
+
let(:root) { :node }
|
|
74
|
+
let(:presented_collection_ids) { presented_collection[root].map(&_ids) }
|
|
75
|
+
|
|
76
|
+
it 'should present page' do
|
|
77
|
+
subject[:page].should_not be_nil
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'should present per_page' do
|
|
81
|
+
subject[:per_page].should_not be_nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'should present total_pages' do
|
|
85
|
+
subject[:total_pages].should_not be_nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'should present total_entries' do
|
|
89
|
+
subject[:total_entries].should_not be_nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'should present collection' do
|
|
93
|
+
subject[root].should_not be_nil
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'should present collection of resources' do
|
|
97
|
+
presented_collection_ids.should eql(collection_ids)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context 'with always_nest_collections option' do
|
|
102
|
+
let(:presenter_options) { { :presenter => presenter, :always_nest_collections => true } }
|
|
103
|
+
let(:presented_collection_ids) { presented_collection[:collection].map(&_ids) }
|
|
104
|
+
let(:_ids) { ->(r) { r['item'][:id] } }
|
|
105
|
+
|
|
106
|
+
it 'should present page' do
|
|
107
|
+
subject[:page].should_not be_nil
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'should present per_page' do
|
|
111
|
+
subject[:per_page].should_not be_nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'should present total_pages' do
|
|
115
|
+
subject[:total_pages].should_not be_nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'should present total_entries' do
|
|
119
|
+
subject[:total_entries].should_not be_nil
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'should present collection' do
|
|
123
|
+
subject[:collection].should_not be_nil
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'should present collection of resources' do
|
|
127
|
+
presented_collection_ids.should eql(collection_ids)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
context 'with always_nest_collections and root option' do
|
|
132
|
+
let(:presenter_options) { { :presenter => presenter, :root => root, :always_nest_collections => true } }
|
|
133
|
+
let(:root) { :nodes }
|
|
134
|
+
let(:element_name) { root.to_s.singularize }
|
|
135
|
+
let(:presented_collection_ids) { presented_collection[root].map(&_ids) }
|
|
136
|
+
let(:_ids) { ->(r) { r[element_name][:id] } }
|
|
137
|
+
|
|
138
|
+
it 'should present page' do
|
|
139
|
+
subject[:page].should_not be_nil
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'should present per_page' do
|
|
143
|
+
subject[:per_page].should_not be_nil
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it 'should present total_pages' do
|
|
147
|
+
subject[:total_pages].should_not be_nil
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'should present total_entries' do
|
|
151
|
+
subject[:total_entries].should_not be_nil
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'should present collection' do
|
|
155
|
+
subject[root].should_not be_nil
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it 'should present collection of resources' do
|
|
159
|
+
presented_collection_ids.should eql(collection_ids)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|