praxis 0.22.pre.1 → 2.0.pre.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +5 -20
  3. data/CHANGELOG.md +328 -323
  4. data/lib/praxis.rb +13 -9
  5. data/lib/praxis/action_definition.rb +8 -10
  6. data/lib/praxis/action_definition/headers_dsl_compiler.rb +1 -1
  7. data/lib/praxis/api_definition.rb +27 -44
  8. data/lib/praxis/api_general_info.rb +2 -3
  9. data/lib/praxis/application.rb +15 -142
  10. data/lib/praxis/bootloader.rb +1 -2
  11. data/lib/praxis/bootloader_stages/environment.rb +13 -0
  12. data/lib/praxis/config.rb +1 -1
  13. data/lib/praxis/controller.rb +0 -2
  14. data/lib/praxis/dispatcher.rb +4 -6
  15. data/lib/praxis/docs/generator.rb +8 -18
  16. data/lib/praxis/docs/link_builder.rb +1 -1
  17. data/lib/praxis/error_handler.rb +5 -5
  18. data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +1 -1
  19. data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +1 -1
  20. data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +125 -0
  21. data/lib/praxis/extensions/field_selection.rb +1 -12
  22. data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +28 -34
  23. data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +35 -39
  24. data/lib/praxis/extensions/rendering.rb +1 -1
  25. data/lib/praxis/file_group.rb +1 -1
  26. data/lib/praxis/handlers/xml.rb +1 -1
  27. data/lib/praxis/mapper/active_model_compat.rb +98 -0
  28. data/lib/praxis/mapper/resource.rb +242 -0
  29. data/lib/praxis/mapper/selector_generator.rb +154 -0
  30. data/lib/praxis/mapper/sequel_compat.rb +76 -0
  31. data/lib/praxis/media_type_identifier.rb +2 -1
  32. data/lib/praxis/middleware_app.rb +13 -15
  33. data/lib/praxis/multipart/part.rb +3 -5
  34. data/lib/praxis/notifications.rb +1 -1
  35. data/lib/praxis/plugins/mapper_plugin.rb +64 -0
  36. data/lib/praxis/request.rb +14 -7
  37. data/lib/praxis/request_stages/response.rb +2 -3
  38. data/lib/praxis/resource_definition.rb +15 -19
  39. data/lib/praxis/response.rb +6 -5
  40. data/lib/praxis/response_definition.rb +5 -7
  41. data/lib/praxis/response_template.rb +3 -4
  42. data/lib/praxis/responses/http.rb +36 -0
  43. data/lib/praxis/responses/internal_server_error.rb +12 -3
  44. data/lib/praxis/responses/multipart_ok.rb +11 -4
  45. data/lib/praxis/responses/validation_error.rb +10 -1
  46. data/lib/praxis/route.rb +1 -1
  47. data/lib/praxis/router.rb +3 -3
  48. data/lib/praxis/routing_config.rb +1 -1
  49. data/lib/praxis/tasks/api_docs.rb +2 -10
  50. data/lib/praxis/tasks/routes.rb +0 -1
  51. data/lib/praxis/trait.rb +1 -1
  52. data/lib/praxis/types/media_type_common.rb +2 -2
  53. data/lib/praxis/types/multipart.rb +1 -1
  54. data/lib/praxis/types/multipart_array.rb +2 -2
  55. data/lib/praxis/types/multipart_array/part_definition.rb +1 -1
  56. data/lib/praxis/version.rb +1 -1
  57. data/praxis.gemspec +11 -9
  58. data/spec/functional_spec.rb +0 -1
  59. data/spec/praxis/action_definition_spec.rb +16 -27
  60. data/spec/praxis/api_definition_spec.rb +8 -13
  61. data/spec/praxis/api_general_info_spec.rb +8 -3
  62. data/spec/praxis/application_spec.rb +8 -14
  63. data/spec/praxis/collection_spec.rb +3 -2
  64. data/spec/praxis/config_spec.rb +2 -2
  65. data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +106 -0
  66. data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +147 -0
  67. data/spec/praxis/extensions/field_selection/support/spec_resources_active_model.rb +130 -0
  68. data/spec/praxis/extensions/field_selection/support/spec_resources_sequel.rb +106 -0
  69. data/spec/praxis/handlers/xml_spec.rb +2 -2
  70. data/spec/praxis/mapper/resource_spec.rb +169 -0
  71. data/spec/praxis/mapper/selector_generator_spec.rb +325 -0
  72. data/spec/praxis/media_type_spec.rb +0 -10
  73. data/spec/praxis/middleware_app_spec.rb +16 -10
  74. data/spec/praxis/request_spec.rb +7 -17
  75. data/spec/praxis/request_stages/action_spec.rb +8 -1
  76. data/spec/praxis/request_stages/validate_spec.rb +1 -1
  77. data/spec/praxis/resource_definition_spec.rb +10 -12
  78. data/spec/praxis/response_definition_spec.rb +12 -26
  79. data/spec/praxis/response_spec.rb +6 -13
  80. data/spec/praxis/responses/internal_server_error_spec.rb +5 -2
  81. data/spec/praxis/router_spec.rb +5 -9
  82. data/spec/spec_app/app/controllers/instances.rb +1 -1
  83. data/spec/spec_app/config.ru +6 -1
  84. data/spec/spec_app/config/environment.rb +3 -21
  85. data/spec/spec_helper.rb +13 -17
  86. data/spec/support/be_deep_equal_matcher.rb +39 -0
  87. data/spec/support/spec_resources.rb +124 -0
  88. metadata +74 -53
  89. data/lib/praxis/extensions/attribute_filtering.rb +0 -28
  90. data/lib/praxis/extensions/attribute_filtering/query_builder.rb +0 -39
  91. data/lib/praxis/extensions/mapper_selectors.rb +0 -16
  92. data/lib/praxis/media_type_collection.rb +0 -127
  93. data/lib/praxis/plugins/praxis_mapper_plugin.rb +0 -246
  94. data/spec/praxis/media_type_collection_spec.rb +0 -157
  95. data/spec/praxis/plugins/praxis_mapper_plugin_spec.rb +0 -142
  96. data/spec/spec_app/app/models/person.rb +0 -3
@@ -1,157 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Praxis::MediaTypeCollection do
4
-
5
- subject!(:media_type_collection) do
6
- silence_warnings do
7
- klass = Class.new(Praxis::MediaTypeCollection) do
8
- member_type VolumeSnapshot
9
- description 'A container for a collection of Volumes'
10
- display_name 'Volumes Collection'
11
-
12
- attributes do
13
- attribute :name, String, regexp: /snapshots-(\w+)/
14
- attribute :size, Integer
15
- attribute :href, String
16
- end
17
-
18
- view :link do
19
- attribute :name
20
- attribute :size
21
- attribute :href
22
- end
23
-
24
- member_view :default, using: :default
25
- end
26
-
27
- klass.finalize!
28
- klass
29
- end
30
- end
31
-
32
- context '.member_type' do
33
- its(:member_type){ should be(VolumeSnapshot) }
34
- its(:member_attribute){ should be_kind_of(Attributor::Attribute) }
35
- its('member_attribute.type'){ should be(VolumeSnapshot) }
36
- end
37
-
38
- context '.load' do
39
- context 'with a hash' do
40
- let(:snapshots_data) { {name: 'snapshots', href: '/bob/snapshots' } }
41
- subject(:snapshots) { media_type_collection.load(snapshots_data) }
42
-
43
- its(:name) { should eq(snapshots_data[:name]) }
44
- its(:href) { should eq(snapshots_data[:href]) }
45
-
46
- it 'has no members set' do
47
- expect(snapshots.to_a).to eq([])
48
- end
49
- end
50
-
51
-
52
- context 'loading an array' do
53
- let(:snapshots_data) do
54
- [{id: 1, name: 'snapshot-1'},
55
- {id: 2, name: 'snapshot-2'}]
56
- end
57
-
58
- let(:snapshots) { media_type_collection.load(snapshots_data) }
59
- subject(:members) { snapshots.to_a }
60
-
61
- it 'sets the collection members' do
62
- expect(members).to have(2).items
63
-
64
- expect(members[0].id).to eq(1)
65
- expect(members[0].name).to eq('snapshot-1')
66
- expect(members[1].id).to eq(2)
67
- expect(members[1].name).to eq('snapshot-2')
68
- end
69
-
70
- it 'has no attributes set' do
71
- expect(snapshots.name).to be(nil)
72
- expect(snapshots.size).to be(nil)
73
- expect(snapshots.href).to be(nil)
74
- end
75
-
76
- end
77
- end
78
-
79
- context '#render' do
80
- context 'for standard views' do
81
- let(:snapshots_data) { {name: 'snapshots', href: '/bob/snapshots' } }
82
- let(:snapshots) { media_type_collection.load(snapshots_data) }
83
- subject(:output) { snapshots.render(view: :link) }
84
-
85
- its([:name]) { should eq(snapshots.name)}
86
- its([:size]) { should eq(snapshots.size)}
87
- its([:href]) { should eq(snapshots.href)}
88
- end
89
-
90
- context 'for members' do
91
- let(:snapshots_data) do
92
- [{id: 1, name: 'snapshot-1'},
93
- {id: 2, name: 'snapshot-2'}]
94
- end
95
-
96
- let(:snapshots) { media_type_collection.load(snapshots_data) }
97
-
98
- subject(:output) { media_type_collection.dump(snapshots, view: :default) }
99
-
100
- it { should eq(snapshots.collect(&:render)) }
101
- end
102
-
103
- end
104
-
105
- context '#validate' do
106
-
107
-
108
- context 'with a hash' do
109
- let(:snapshots_data) { {name: 'snapshots-1', href: '/bob/snapshots' } }
110
- subject(:snapshots) { media_type_collection.load(snapshots_data) }
111
-
112
-
113
- it 'validates' do
114
- expect(snapshots.validate).to be_empty
115
- end
116
-
117
- context 'with invalid attributes' do
118
- let(:snapshots_data) { {name: 'notsnapshots', href: '/bob/snapshots' } }
119
- it 'returns the error' do
120
- expect(snapshots.validate).to have(1).item
121
- expect(snapshots.validate[0]).to match(/value \(notsnapshots\) does not match regexp/)
122
- end
123
- end
124
- end
125
-
126
- context 'for an array' do
127
- let(:snapshots_data) do
128
- [{id: 1, name: 'snapshot-1'},
129
- {id: 2, name: 'snapshot-2'}]
130
- end
131
-
132
- subject(:snapshots) { media_type_collection.load(snapshots_data) }
133
-
134
- it 'validates' do
135
- expect(snapshots.validate).to be_empty
136
- end
137
-
138
- context 'with invalid members' do
139
- let(:snapshots_data) do
140
- [{id: 1, name: 'invalid-1'},
141
- {id: 2, name: 'snapshot-2'}]
142
- end
143
-
144
- it 'returns the error' do
145
- expect(snapshots.validate).to have(1).item
146
- expect(snapshots.validate[0]).to match(/value \(invalid-1\) does not match regexp/)
147
- end
148
- end
149
- end
150
- end
151
-
152
- context '#describe' do
153
- subject(:described) { media_type_collection.describe }
154
- its([:description]){ should be(media_type_collection.description)}
155
- its([:display_name]){ should be(media_type_collection.display_name)}
156
- end
157
- end
@@ -1,142 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Praxis::Plugins::PraxisMapperPlugin do
4
-
5
- subject(:plugin) { Praxis::Plugins::PraxisMapperPlugin::Plugin.instance }
6
- let(:config) { plugin.config }
7
- context 'Plugin' do
8
- context 'configuration' do
9
- subject { config }
10
- its(:log_stats) { should eq 'detailed' }
11
- its(:stats_log_level) { should eq :info }
12
- its(:repositories) { should have_key("default") }
13
-
14
- context 'default repository' do
15
- subject(:default) { config.repositories['default'] }
16
- its(['type']) { should eq 'sequel' }
17
- it 'has the right connection settings' do
18
- if RUBY_PLATFORM !~ /java/
19
- expect(subject['connection_settings'].dump).to eq( 'adapter' => 'sqlite','database' => ':memory:' )
20
- else
21
- expect(subject['connection_settings'].dump).to eq( 'adapter' => 'jdbc', 'uri' => 'jdbc:sqlite::memory:' )
22
- end
23
-
24
-
25
- end
26
- end
27
-
28
- end
29
- end
30
-
31
- context 'Request' do
32
-
33
- it 'should have identity_map accessors' do
34
- expect(Praxis::Plugins::PraxisMapperPlugin::Request.instance_methods).to include(:identity_map,:identity_map=)
35
- end
36
-
37
- it 'should have silence_mapper_stats accessors' do
38
- expect(Praxis::Plugins::PraxisMapperPlugin::Request.instance_methods)
39
- .to include(:silence_mapper_stats,:silence_mapper_stats=)
40
- end
41
- end
42
- context 'functional test' do
43
-
44
- def app
45
- Praxis::Application.instance
46
- end
47
-
48
- let(:session) { double("session", valid?: true)}
49
-
50
- around(:each) do |example|
51
- orig_level = Praxis::Application.instance.logger.level
52
- Praxis::Application.instance.logger.level = 2
53
- example.run
54
- Praxis::Application.instance.logger.level = orig_level
55
- end
56
-
57
- context 'with no identity_map set in the request' do
58
- it 'does not log stats' do
59
- expect(Praxis::Plugins::PraxisMapperPlugin::Statistics).to_not receive(:log)
60
- the_body = StringIO.new("{}") # This is a funny, GET request expecting a body
61
- get '/api/clouds/1/instances/2?api_version=1.0', nil, 'rack.input' => the_body,'CONTENT_TYPE' => "application/json", 'global_session' => session
62
-
63
- expect(last_response.status).to eq(200)
64
- end
65
- end
66
- context 'with an identity_map set in the request' do
67
- it 'logs stats' do
68
- expect(Praxis::Plugins::PraxisMapperPlugin::Statistics).to receive(:log).
69
- with(kind_of(Praxis::Request),kind_of(Praxis::Mapper::IdentityMap), 'detailed').
70
- and_call_original
71
- the_body = StringIO.new("{}") # This is a funny, GET request expecting a body
72
- get '/api/clouds/1/instances/2?create_identity_map=true&api_version=1.0', nil, 'rack.input' => the_body,'CONTENT_TYPE' => "application/json", 'global_session' => session
73
-
74
- expect(last_response.status).to eq(200)
75
- end
76
- end
77
-
78
- end
79
-
80
- context 'Statistics' do
81
- context '.log' do
82
- let(:queries){ { some: :queries } }
83
- let(:identity_map) { double('identity_map', queries: queries) }
84
- let(:log_stats){ 'detailed' }
85
- let(:request){ double('request', silence_mapper_stats: false ) }
86
-
87
- after do
88
- Praxis::Plugins::PraxisMapperPlugin::Statistics.log(request, identity_map, log_stats)
89
- end
90
-
91
- context 'when the request silences mapper stats' do
92
- let(:request){ double('request', silence_mapper_stats: true ) }
93
- it 'should not log anything' do
94
- expect(Praxis::Plugins::PraxisMapperPlugin::Statistics).to_not receive(:to_logger)
95
- end
96
- end
97
-
98
- context 'without the request silencing mapper stats' do
99
- context 'when log_stats = detailed' do
100
- it 'should call the detailed method' do
101
- expect(Praxis::Plugins::PraxisMapperPlugin::Statistics).to receive(:detailed).with(identity_map)
102
- end
103
- end
104
-
105
- context 'when log_stats = short' do
106
- let(:log_stats){ 'short' }
107
- it 'should call the short method' do
108
- expect(Praxis::Plugins::PraxisMapperPlugin::Statistics).to receive(:short).with(identity_map)
109
- end
110
- end
111
-
112
- context 'when log_stats = skip' do
113
- let(:log_stats){ 'skip' }
114
-
115
- it 'should not log anything' do
116
- expect(Praxis::Plugins::PraxisMapperPlugin::Statistics).to_not receive(:to_logger)
117
- end
118
- end
119
-
120
- context 'when there is no identity map' do
121
- let(:identity_map) { nil }
122
- it 'should not log anything' do
123
- expect(Praxis::Plugins::PraxisMapperPlugin::Statistics).to_not receive(:to_logger)
124
- end
125
- end
126
-
127
- context 'when no queries are logged in the identity map' do
128
- let(:queries){ {} }
129
- it 'should log a special message' do
130
- expect(Praxis::Plugins::PraxisMapperPlugin::Statistics).to receive(:to_logger)
131
- .with("No database interactions observed.")
132
- end
133
- end
134
-
135
- end
136
- end
137
-
138
- it 'has specs for testing the detailed log output'
139
- it 'has specs for testing the short log output'
140
- end
141
-
142
- end
@@ -1,3 +0,0 @@
1
- class PersonModel < Praxis::Mapper::Model
2
- table_name 'people'
3
- end