praxis 0.22.pre.2 → 2.0.pre.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +323 -324
- data/lib/praxis/action_definition.rb +7 -9
- data/lib/praxis/api_definition.rb +27 -44
- data/lib/praxis/api_general_info.rb +2 -3
- data/lib/praxis/application.rb +14 -141
- data/lib/praxis/bootloader.rb +1 -2
- data/lib/praxis/bootloader_stages/environment.rb +13 -0
- data/lib/praxis/controller.rb +0 -2
- data/lib/praxis/dispatcher.rb +4 -6
- data/lib/praxis/docs/generator.rb +8 -18
- data/lib/praxis/docs/link_builder.rb +1 -1
- data/lib/praxis/error_handler.rb +5 -5
- data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +1 -1
- data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +125 -0
- data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +16 -18
- data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +5 -5
- data/lib/praxis/extensions/field_selection.rb +1 -12
- data/lib/praxis/extensions/rendering.rb +1 -1
- data/lib/praxis/file_group.rb +1 -1
- data/lib/praxis/handlers/xml.rb +1 -1
- data/lib/praxis/mapper/active_model_compat.rb +63 -0
- data/lib/praxis/mapper/resource.rb +242 -0
- data/lib/praxis/mapper/selector_generator.rb +126 -0
- data/lib/praxis/mapper/sequel_compat.rb +37 -0
- data/lib/praxis/middleware_app.rb +13 -15
- data/lib/praxis/multipart/part.rb +3 -5
- data/lib/praxis/plugins/mapper_plugin.rb +50 -0
- data/lib/praxis/request.rb +14 -7
- data/lib/praxis/request_stages/response.rb +2 -3
- data/lib/praxis/resource_definition.rb +10 -14
- data/lib/praxis/response.rb +6 -5
- data/lib/praxis/response_definition.rb +5 -7
- data/lib/praxis/response_template.rb +3 -4
- data/lib/praxis/responses/http.rb +36 -0
- data/lib/praxis/responses/internal_server_error.rb +12 -3
- data/lib/praxis/responses/multipart_ok.rb +11 -4
- data/lib/praxis/responses/validation_error.rb +10 -1
- data/lib/praxis/router.rb +3 -3
- data/lib/praxis/tasks/api_docs.rb +2 -10
- data/lib/praxis/tasks/routes.rb +0 -1
- data/lib/praxis/version.rb +1 -1
- data/lib/praxis.rb +13 -9
- data/praxis.gemspec +2 -3
- data/spec/functional_spec.rb +0 -1
- data/spec/praxis/action_definition_spec.rb +15 -26
- data/spec/praxis/api_definition_spec.rb +8 -13
- data/spec/praxis/api_general_info_spec.rb +8 -3
- data/spec/praxis/application_spec.rb +7 -13
- data/spec/praxis/handlers/xml_spec.rb +2 -2
- data/spec/praxis/mapper/resource_spec.rb +169 -0
- data/spec/praxis/mapper/selector_generator_spec.rb +301 -0
- data/spec/praxis/middleware_app_spec.rb +15 -9
- data/spec/praxis/request_spec.rb +7 -17
- data/spec/praxis/request_stages/validate_spec.rb +1 -1
- data/spec/praxis/resource_definition_spec.rb +10 -12
- data/spec/praxis/response_definition_spec.rb +5 -22
- data/spec/praxis/response_spec.rb +5 -12
- data/spec/praxis/responses/internal_server_error_spec.rb +5 -2
- data/spec/praxis/router_spec.rb +4 -8
- data/spec/spec_app/app/models/person.rb +3 -3
- data/spec/spec_app/config/environment.rb +3 -21
- data/spec/spec_app/config.ru +6 -1
- data/spec/spec_helper.rb +2 -17
- data/spec/support/spec_resources.rb +131 -0
- metadata +19 -31
- data/lib/praxis/extensions/attribute_filtering/query_builder.rb +0 -39
- data/lib/praxis/extensions/attribute_filtering.rb +0 -28
- data/lib/praxis/extensions/mapper_selectors.rb +0 -16
- data/lib/praxis/media_type_collection.rb +0 -127
- data/lib/praxis/plugins/praxis_mapper_plugin.rb +0 -246
- data/spec/praxis/media_type_collection_spec.rb +0 -157
- data/spec/praxis/plugins/praxis_mapper_plugin_spec.rb +0 -142
@@ -1,246 +0,0 @@
|
|
1
|
-
require 'praxis-mapper'
|
2
|
-
require 'singleton'
|
3
|
-
|
4
|
-
require 'terminal-table'
|
5
|
-
|
6
|
-
# Plugin for applications which use the 'praxis-mapper' gem.
|
7
|
-
#
|
8
|
-
# This plugin provides the following features:
|
9
|
-
# 1. Sets up the PraxisMapper::IdentityMap for your application and assigns
|
10
|
-
# it to the controller's request.identity_map for access from your
|
11
|
-
# application.
|
12
|
-
# 2. Connects to your database and dumps a log of database interaction stats
|
13
|
-
# (if enabled via the :log_stats option).
|
14
|
-
#
|
15
|
-
# This plugin accepts one of the following options:
|
16
|
-
# 1. config_file: A String indicating the path where this plugin's config
|
17
|
-
# file exists.
|
18
|
-
# 2. config_data: A Hash of data that is merged into the YAML hash loaded
|
19
|
-
# from config_file.
|
20
|
-
#
|
21
|
-
# The config_data Hash contains the following keys:
|
22
|
-
# 1. repositories: A Hash containing the configs for the database repositories
|
23
|
-
# queried through praxis-mapper. This parameter is a Hash where a key is
|
24
|
-
# the identifier for a repository and the value is the options one
|
25
|
-
# would give to the 'sequel' gem. For example:
|
26
|
-
# repositories: {
|
27
|
-
# default: {
|
28
|
-
# host: 127.0.0.1,
|
29
|
-
# username: root,
|
30
|
-
# password: nil,
|
31
|
-
# database: myapp_dev,
|
32
|
-
# adapter: mysql2
|
33
|
-
# }
|
34
|
-
# }
|
35
|
-
# 2. log_stats: A String indicating what kind of DB stats you would like
|
36
|
-
# output into the Praxis::Application.current_instance.logger app log. Possible
|
37
|
-
# values are: "detailed", "short", and "skip" (i.e. do not print the stats
|
38
|
-
# at all).
|
39
|
-
# 3. stats_log_level: the logging level with which the statistics should be logged.
|
40
|
-
#
|
41
|
-
# See http://praxis-framework.io/reference/plugins/ for further details on how
|
42
|
-
# to use a plugin and pass it options.
|
43
|
-
#
|
44
|
-
module Praxis
|
45
|
-
module Plugins
|
46
|
-
module PraxisMapperPlugin
|
47
|
-
include Praxis::PluginConcern
|
48
|
-
|
49
|
-
class RepositoryConfig < Attributor::Hash
|
50
|
-
self.key_type = String
|
51
|
-
|
52
|
-
keys allow_extra: true do
|
53
|
-
key 'type', String, default: 'sequel'
|
54
|
-
extra 'connection_settings'
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
|
60
|
-
class Plugin < Praxis::Plugin
|
61
|
-
include Singleton
|
62
|
-
|
63
|
-
def initialize
|
64
|
-
@options = {
|
65
|
-
config_file: 'config/praxis_mapper.yml',
|
66
|
-
config_data: {
|
67
|
-
repositories: {}
|
68
|
-
}
|
69
|
-
}
|
70
|
-
end
|
71
|
-
|
72
|
-
def config_key
|
73
|
-
:praxis_mapper
|
74
|
-
end
|
75
|
-
|
76
|
-
def prepare_config!(node)
|
77
|
-
node.attributes do
|
78
|
-
attribute :log_stats, String, values: ['detailed', 'short', 'skip'], default: 'detailed'
|
79
|
-
attribute :stats_log_level, Symbol, values: [:fatal,:error,:warn,:info,:debug], default: :info
|
80
|
-
attribute :repositories, Attributor::Hash.of(key: String, value: RepositoryConfig)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# Make our own custom load_config! method
|
85
|
-
def load_config!
|
86
|
-
config_file_path = application.root + options[:config_file]
|
87
|
-
result = config_file_path.exist? ? YAML.load_file(config_file_path) : {}
|
88
|
-
result.merge(@options[:config_data])
|
89
|
-
end
|
90
|
-
|
91
|
-
def setup!
|
92
|
-
self.config.repositories.each do |repository_name, repository_config|
|
93
|
-
type = repository_config['type']
|
94
|
-
connection_settings = repository_config['connection_settings']
|
95
|
-
|
96
|
-
case type
|
97
|
-
when 'sequel'
|
98
|
-
self.setup_sequel_repository(repository_name, connection_settings)
|
99
|
-
else
|
100
|
-
raise "unsupported repository type: #{type}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
log_stats = PraxisMapperPlugin::Plugin.instance.config.log_stats
|
105
|
-
unless log_stats == 'skip'
|
106
|
-
Praxis::Notifications.subscribe 'praxis.request.all' do |name, *junk, payload|
|
107
|
-
if (payload[:request].identity_map?)
|
108
|
-
identity_map = payload[:request].identity_map
|
109
|
-
PraxisMapperPlugin::Statistics.log(payload[:request], identity_map, log_stats)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def setup_sequel_repository(name, settings)
|
116
|
-
db = Sequel.connect(settings.dump.symbolize_keys)
|
117
|
-
|
118
|
-
Praxis::Mapper::ConnectionManager.setup do
|
119
|
-
repository(name.to_sym) { db }
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
module Request
|
125
|
-
def identity_map
|
126
|
-
@identity_map ||= Praxis::Mapper::IdentityMap.new
|
127
|
-
end
|
128
|
-
|
129
|
-
def identity_map=(map)
|
130
|
-
@identity_map = map
|
131
|
-
end
|
132
|
-
|
133
|
-
def identity_map?
|
134
|
-
!@identity_map.nil?
|
135
|
-
end
|
136
|
-
|
137
|
-
def silence_mapper_stats
|
138
|
-
@silence_mapper_stats
|
139
|
-
end
|
140
|
-
|
141
|
-
def silence_mapper_stats=(value)
|
142
|
-
@silence_mapper_stats = value
|
143
|
-
end
|
144
|
-
|
145
|
-
end
|
146
|
-
|
147
|
-
module Controller
|
148
|
-
extend ActiveSupport::Concern
|
149
|
-
|
150
|
-
included do
|
151
|
-
# Ensure we call #release on any identity map
|
152
|
-
# that may be set by the controller after the action
|
153
|
-
# completes.
|
154
|
-
around :action do |controller, callee|
|
155
|
-
begin
|
156
|
-
callee.call
|
157
|
-
ensure
|
158
|
-
if controller.request.identity_map?
|
159
|
-
controller.request.identity_map.release
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def identity_map
|
166
|
-
request.identity_map
|
167
|
-
end
|
168
|
-
|
169
|
-
end
|
170
|
-
|
171
|
-
module Statistics
|
172
|
-
|
173
|
-
def self.log(request, identity_map, log_stats)
|
174
|
-
return if identity_map.nil?
|
175
|
-
return if request.silence_mapper_stats == true
|
176
|
-
if identity_map.queries.empty?
|
177
|
-
self.to_logger "No database interactions observed."
|
178
|
-
return
|
179
|
-
end
|
180
|
-
|
181
|
-
|
182
|
-
case log_stats
|
183
|
-
when 'detailed'
|
184
|
-
self.detailed(identity_map)
|
185
|
-
when 'short'
|
186
|
-
self.short(identity_map)
|
187
|
-
when 'skip'
|
188
|
-
# Shouldn't receive this. But anyway...no-op.
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
def self.detailed(identity_map)
|
193
|
-
stats_by_model = identity_map.query_statistics.sum_totals_by_model
|
194
|
-
stats_total = identity_map.query_statistics.sum_totals
|
195
|
-
fields = [ :query_count, :records_loaded, :datastore_interactions, :datastore_interaction_time]
|
196
|
-
rows = []
|
197
|
-
|
198
|
-
total_models_loaded = 0
|
199
|
-
# stats per model
|
200
|
-
stats_by_model.each do |model, totals|
|
201
|
-
total_values = totals.values_at(*fields)
|
202
|
-
self.round_fields_at( total_values , [fields.index(:datastore_interaction_time)])
|
203
|
-
row = [ model ] + total_values
|
204
|
-
models_loaded = identity_map.all(model).size
|
205
|
-
total_models_loaded += models_loaded
|
206
|
-
row << models_loaded
|
207
|
-
rows << row
|
208
|
-
end
|
209
|
-
|
210
|
-
rows << :separator
|
211
|
-
|
212
|
-
# totals for all models
|
213
|
-
stats_total_values = stats_total.values_at(*fields)
|
214
|
-
self.round_fields_at(stats_total_values , [fields.index(:datastore_interaction_time)])
|
215
|
-
rows << [ "All Models" ] + stats_total_values + [total_models_loaded]
|
216
|
-
|
217
|
-
table = Terminal::Table.new \
|
218
|
-
:rows => rows,
|
219
|
-
:title => "Praxis::Mapper Statistics",
|
220
|
-
:headings => [ "Model", "# Queries", "Records Loaded", "Interactions", "Time(sec)", "Models Loaded" ]
|
221
|
-
|
222
|
-
table.align_column(1, :right)
|
223
|
-
table.align_column(2, :right)
|
224
|
-
table.align_column(3, :right)
|
225
|
-
table.align_column(4, :right)
|
226
|
-
table.align_column(5, :right)
|
227
|
-
self.to_logger "\n#{table.to_s}"
|
228
|
-
end
|
229
|
-
|
230
|
-
def self.round_fields_at(values, indices)
|
231
|
-
indices.each do |idx|
|
232
|
-
values[idx] = "%.3f" % values[idx]
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
def self.short(identity_map)
|
237
|
-
self.to_logger identity_map.query_statistics.sum_totals.to_s
|
238
|
-
end
|
239
|
-
|
240
|
-
def self.to_logger(message)
|
241
|
-
Praxis::Application.current_instance.logger.__send__(Plugin.instance.config.stats_log_level, "Praxis::Mapper Statistics: #{message}")
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
@@ -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
|