moonrope 2.0.0 → 2.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.
- checksums.yaml +4 -4
- data/lib/moonrope/action.rb +6 -4
- data/lib/moonrope/authenticator.rb +3 -0
- data/lib/moonrope/base.rb +17 -0
- data/lib/moonrope/dsl/authenticator_dsl.rb +4 -0
- data/lib/moonrope/dsl/structure_dsl.rb +1 -0
- data/lib/moonrope/rack_middleware.rb +50 -36
- data/lib/moonrope/request.rb +1 -1
- data/lib/moonrope/structure.rb +24 -6
- data/lib/moonrope/structure_attribute.rb +24 -0
- data/lib/moonrope/version.rb +1 -1
- data/templates/basic/_action_form.erb +66 -66
- data/templates/basic/assets/try.js +8 -2
- data/templates/basic/authenticator.erb +1 -0
- data/templates/basic/layout.erb +3 -3
- data/test/tests/rack_middleware_test.rb +8 -0
- data/test/tests/structures_test.rb +55 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec14194988474a3b6e4e0d3e40ffafb64a3fb4c1
|
4
|
+
data.tar.gz: 968649b6047917e0713c0510ed32d2c66d4265d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbda03f158543eb581faf08fe4954ce4ac567bf03017e0e33dcef295da04b28d262eaa0038facc3e8c62e84f42fdd79f41580e571ba01a659a335c0ff564a1bf
|
7
|
+
data.tar.gz: 64e355f2ef7a89bd545e951070737d2668de5a38c60013b1355c2277a4f0b02318e4d0e7223bd675e2a5364d2d1f9c887b30c3fb3730b9c170c8eddbaf432058
|
data/lib/moonrope/action.rb
CHANGED
@@ -107,19 +107,21 @@ module Moonrope
|
|
107
107
|
# Execute a block of code and catch approprite Moonrope errors and return
|
108
108
|
# a result.
|
109
109
|
#
|
110
|
-
def convert_errors_to_action_result(&block)
|
110
|
+
def convert_errors_to_action_result(start_time = nil, &block)
|
111
111
|
begin
|
112
112
|
yield block
|
113
113
|
rescue => exception
|
114
114
|
case exception
|
115
115
|
when Moonrope::Errors::RequestError
|
116
116
|
result = ActionResult.new(self)
|
117
|
+
result.time = start_time ? (Time.now - start_time).round(2) : nil
|
117
118
|
result.status = exception.status
|
118
119
|
result.data = exception.data
|
119
120
|
result
|
120
121
|
else
|
121
122
|
if error_block = @controller.base.external_errors[exception.class]
|
122
123
|
result = ActionResult.new(self)
|
124
|
+
result.time = start_time ? (Time.now - start_time).round(2) : nil
|
123
125
|
error_block.call(exception, result)
|
124
126
|
result
|
125
127
|
else
|
@@ -149,14 +151,14 @@ module Moonrope
|
|
149
151
|
#
|
150
152
|
eval_environment.default_params = self.default_params
|
151
153
|
|
152
|
-
|
154
|
+
start_time = Time.now
|
155
|
+
|
156
|
+
convert_errors_to_action_result(start_time) do
|
153
157
|
#
|
154
158
|
# Validate the parameters
|
155
159
|
#
|
156
160
|
self.validate_parameters(eval_environment.params)
|
157
161
|
|
158
|
-
start_time = Time.now
|
159
|
-
|
160
162
|
# Run before filters
|
161
163
|
controller.before_actions_for(name).each do |action|
|
162
164
|
eval_environment.instance_eval(&action.block)
|
@@ -17,6 +17,9 @@ module Moonrope
|
|
17
17
|
# @return [Symbol] the name of the authenticator
|
18
18
|
attr_reader :name
|
19
19
|
|
20
|
+
# @return [String] the friendly name for the authenticator
|
21
|
+
attr_accessor :friendly_name
|
22
|
+
|
20
23
|
# @return [String] the description for the authenticator
|
21
24
|
attr_accessor :description
|
22
25
|
|
data/lib/moonrope/base.rb
CHANGED
@@ -61,6 +61,23 @@ module Moonrope
|
|
61
61
|
@dsl.instance_eval(&block) if block_given?
|
62
62
|
end
|
63
63
|
|
64
|
+
#
|
65
|
+
# Make a new base based on configuration
|
66
|
+
#
|
67
|
+
def copy_from(other)
|
68
|
+
@environment = other.environment
|
69
|
+
@load_directories = other.load_directories
|
70
|
+
@on_request = other.on_request
|
71
|
+
other.request_error_callbacks.each { |block| self.register_request_error_callback(&block) }
|
72
|
+
other.external_errors.each { |error, block| self.register_external_error(error, &block) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def copy
|
76
|
+
new_base = self.class.new
|
77
|
+
new_base.copy_from(self)
|
78
|
+
new_base
|
79
|
+
end
|
80
|
+
|
64
81
|
#
|
65
82
|
# Reset the whole base to contain no data.
|
66
83
|
#
|
@@ -77,6 +77,7 @@ module Moonrope
|
|
77
77
|
attribute.value = options[:value]
|
78
78
|
attribute.example = options[:eg] || options[:example]
|
79
79
|
attribute.doc = options[:doc]
|
80
|
+
attribute.mutation = options[:mutation]
|
80
81
|
attribute.groups = @groups
|
81
82
|
attribute.conditions = @conditions
|
82
83
|
@structure.attributes[type] << attribute
|
@@ -25,23 +25,6 @@ module Moonrope
|
|
25
25
|
#
|
26
26
|
def call(env)
|
27
27
|
if env['PATH_INFO'] =~ Moonrope::Request.path_regex
|
28
|
-
|
29
|
-
if @options[:reload_on_each_request]
|
30
|
-
@base.load
|
31
|
-
end
|
32
|
-
|
33
|
-
#
|
34
|
-
# Call the on request block if one has been defined for the base.
|
35
|
-
#
|
36
|
-
if @base.on_request.is_a?(Proc)
|
37
|
-
@base.on_request.call(@base, env)
|
38
|
-
end
|
39
|
-
|
40
|
-
#
|
41
|
-
# Create a new request object
|
42
|
-
#
|
43
|
-
request = @base.request(env, $1)
|
44
|
-
|
45
28
|
#
|
46
29
|
# Set some global headers which are always returned
|
47
30
|
#
|
@@ -65,6 +48,32 @@ module Moonrope
|
|
65
48
|
#
|
66
49
|
global_headers['Content-Type'] = 'application/json'
|
67
50
|
|
51
|
+
#
|
52
|
+
# Reload if needed
|
53
|
+
#
|
54
|
+
if @options[:reload_on_each_request]
|
55
|
+
base = @base.copy
|
56
|
+
begin
|
57
|
+
base.load
|
58
|
+
rescue => e
|
59
|
+
return generate_error_triplet(@base, e, global_headers)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
base = @base
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Call the on request block if one has been defined for the base.
|
67
|
+
#
|
68
|
+
if base.on_request.is_a?(Proc)
|
69
|
+
base.on_request.call(base, env)
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Create a new request object
|
74
|
+
#
|
75
|
+
request = base.request(env, $1)
|
76
|
+
|
68
77
|
#
|
69
78
|
# Check the request is valid
|
70
79
|
#
|
@@ -78,30 +87,13 @@ module Moonrope
|
|
78
87
|
begin
|
79
88
|
result = request.execute
|
80
89
|
json = result.to_json
|
90
|
+
Moonrope.logger.info "[#{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")}] controller=#{request.controller.name} action=#{request.action.name} status=#{result.status} time=#{result.time} ip=#{request.ip} size=#{json.bytesize}"
|
81
91
|
global_headers['Content-Length'] = json.bytesize.to_s
|
82
92
|
[200, global_headers.merge(result.headers), [json]]
|
83
93
|
rescue JSON::ParserError => e
|
84
94
|
[400, global_headers, [{:status => 'invalid-json', :details => e.message}.to_json]]
|
85
95
|
rescue => e
|
86
|
-
|
87
|
-
Moonrope.logger.info e.message
|
88
|
-
Moonrope.logger.info e.backtrace.join("\n")
|
89
|
-
|
90
|
-
response = {:status => 'internal-server-error'}
|
91
|
-
|
92
|
-
# Call any request errors which have been registered on the base
|
93
|
-
@base.request_error_callbacks.each do |callback|
|
94
|
-
callback.call(request, e)
|
95
|
-
end
|
96
|
-
|
97
|
-
# If in development, return more details about the exception which was raised.
|
98
|
-
if @base.environment == 'development'
|
99
|
-
response[:error] = e.class.to_s
|
100
|
-
response[:message] = e.message
|
101
|
-
response[:backtrace] = e.backtrace[0,6]
|
102
|
-
end
|
103
|
-
|
104
|
-
[500, global_headers, [response.to_json]]
|
96
|
+
generate_error_triplet(base, e, global_headers)
|
105
97
|
end
|
106
98
|
|
107
99
|
else
|
@@ -113,5 +105,27 @@ module Moonrope
|
|
113
105
|
end
|
114
106
|
end
|
115
107
|
|
108
|
+
def generate_error_triplet(base, exception, headers = {})
|
109
|
+
Moonrope.logger.info exception.class
|
110
|
+
Moonrope.logger.info exception.message
|
111
|
+
Moonrope.logger.info exception.backtrace.join("\n")
|
112
|
+
|
113
|
+
response = {:status => 'internal-server-error'}
|
114
|
+
|
115
|
+
# Call any request errors which have been registered on the base
|
116
|
+
base.request_error_callbacks.each do |callback|
|
117
|
+
callback.call(request, exception)
|
118
|
+
end
|
119
|
+
|
120
|
+
# If in development, return more details about the exception which was raised.
|
121
|
+
if base.environment == 'development'
|
122
|
+
response[:error] = exception.class.to_s
|
123
|
+
response[:message] = exception.message
|
124
|
+
response[:backtrace] = exception.backtrace[0,6]
|
125
|
+
end
|
126
|
+
|
127
|
+
[500, headers, [response.to_json]]
|
128
|
+
end
|
129
|
+
|
116
130
|
end
|
117
131
|
end
|
data/lib/moonrope/request.rb
CHANGED
@@ -120,7 +120,7 @@ module Moonrope
|
|
120
120
|
#
|
121
121
|
def params
|
122
122
|
@params ||= begin
|
123
|
-
if @env['CONTENT_TYPE']
|
123
|
+
if @env['CONTENT_TYPE'] && @env['CONTENT_TYPE'] =~ /\Aapplication\/json(;|\z)/i
|
124
124
|
Moonrope::ParamSet.new(rack_request.body.read)
|
125
125
|
else
|
126
126
|
Moonrope::ParamSet.new(rack_request.params['params'])
|
data/lib/moonrope/structure.rb
CHANGED
@@ -85,13 +85,29 @@ module Moonrope
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
+
if options[:attributes]
|
89
|
+
hash.reject! { |k,v| !options[:attributes].include?(k.to_sym) }
|
90
|
+
end
|
91
|
+
|
88
92
|
# Add expansions
|
89
93
|
if options[:expansions]
|
90
94
|
|
95
|
+
if options[:expansions].is_a?(Array)
|
96
|
+
expansions_to_include = options[:expansions].each_with_object({}) do |expan, hash|
|
97
|
+
if expan.is_a?(Symbol) || expan.is_a?(String)
|
98
|
+
hash[expan.to_sym] = {}
|
99
|
+
elsif expan.is_a?(Hash)
|
100
|
+
hash[expan.first.first.to_sym] = expan.first.last
|
101
|
+
end
|
102
|
+
end
|
103
|
+
else
|
104
|
+
expansions_to_include = true
|
105
|
+
end
|
106
|
+
|
91
107
|
# Add structured expansions
|
92
108
|
@attributes[:expansion].each do |attribute|
|
93
|
-
next if
|
94
|
-
DeepMerge.deep_merge! hash_for_attributes([attribute], object, environment), hash
|
109
|
+
next if expansions_to_include.is_a?(Hash) && !expansions_to_include.keys.include?(attribute.name.to_sym)
|
110
|
+
DeepMerge.deep_merge! hash_for_attributes([attribute], object, environment, :structure_opts => expansions_to_include.is_a?(Hash) && expansions_to_include[attribute.name.to_sym]), hash
|
95
111
|
end
|
96
112
|
|
97
113
|
# Add the expansions
|
@@ -162,7 +178,7 @@ module Moonrope
|
|
162
178
|
#
|
163
179
|
# Return a returnable hash for a given set of structured fields.
|
164
180
|
#
|
165
|
-
def hash_for_attributes(attributes, object, environment)
|
181
|
+
def hash_for_attributes(attributes, object, environment, value_options = {})
|
166
182
|
return {} unless attributes.is_a?(Array)
|
167
183
|
Hash.new.tap do |hash|
|
168
184
|
attributes.each do |attribute|
|
@@ -180,9 +196,11 @@ module Moonrope
|
|
180
196
|
elsif attribute.value
|
181
197
|
value = attribute.value
|
182
198
|
else
|
183
|
-
value = value_for_attribute(object, environment, attribute)
|
199
|
+
value = value_for_attribute(object, environment, attribute, value_options)
|
184
200
|
end
|
185
201
|
|
202
|
+
value = attribute.mutate(value)
|
203
|
+
|
186
204
|
if attribute.groups.empty?
|
187
205
|
hash[attribute.name] = value
|
188
206
|
else
|
@@ -203,7 +221,7 @@ module Moonrope
|
|
203
221
|
#
|
204
222
|
# Return a value for a structured field.
|
205
223
|
#
|
206
|
-
def value_for_attribute(object, environment,
|
224
|
+
def value_for_attribute(object, environment, attribute, options = {})
|
207
225
|
if attribute.source_attribute.is_a?(Proc)
|
208
226
|
value = environment.instance_eval(&attribute.source_attribute)
|
209
227
|
else
|
@@ -214,7 +232,7 @@ module Moonrope
|
|
214
232
|
# If a structure is required, lookup the desired structure and set the
|
215
233
|
# hash value as appropriate.
|
216
234
|
if structure = self.base.structure(attribute.structure)
|
217
|
-
structure_opts = attribute.structure_opts || {}
|
235
|
+
structure_opts = options[:structure_opts] || attribute.structure_opts || {}
|
218
236
|
if value.respond_to?(:map)
|
219
237
|
value.map do |v|
|
220
238
|
structure.hash(v, structure_opts.merge(:request => environment.request))
|
@@ -12,6 +12,7 @@ module Moonrope
|
|
12
12
|
attr_accessor :value
|
13
13
|
attr_accessor :example
|
14
14
|
attr_accessor :doc
|
15
|
+
attr_accessor :mutation
|
15
16
|
|
16
17
|
def initialize(type, name)
|
17
18
|
@type = type
|
@@ -28,12 +29,35 @@ module Moonrope
|
|
28
29
|
([groups] + [name]).flatten.compact.join('.')
|
29
30
|
end
|
30
31
|
|
32
|
+
def mutate(value)
|
33
|
+
if mutation
|
34
|
+
value ? value.public_send(mutation) : nil
|
35
|
+
else
|
36
|
+
auto_mutate(value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def auto_mutate(value)
|
41
|
+
case value_type
|
42
|
+
when :timestamp
|
43
|
+
value.is_a?(Time) ? value.to_s : value
|
44
|
+
when :unix_timestamp
|
45
|
+
value.to_i
|
46
|
+
else
|
47
|
+
value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
31
51
|
def example
|
32
52
|
@example ||= begin
|
33
53
|
if value_type == :timestamp
|
34
54
|
"2016-12-25 09:42:00 +0000"
|
55
|
+
elsif value_type == :unix_timestamp
|
56
|
+
"1491070507"
|
35
57
|
elsif value_type == :boolean
|
36
58
|
"false"
|
59
|
+
elsif value_type == :uuid
|
60
|
+
"017dabc1-3f4f-47ab-ab7d-86e2ed0de679"
|
37
61
|
end
|
38
62
|
end
|
39
63
|
end
|
data/lib/moonrope/version.rb
CHANGED
@@ -1,77 +1,77 @@
|
|
1
|
-
|
2
|
-
<
|
3
|
-
<
|
4
|
-
|
5
|
-
|
6
|
-
<
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
<% unless host.nil? %>
|
2
|
+
<p class='tryFormActivate'><a class='tryFormActivate__button' href='#'>Try this request in your browser</a></p>
|
3
|
+
<form class='tryForm'>
|
4
|
+
<input type='hidden' name='controller' value='<%= controller.name %>'>
|
5
|
+
<input type='hidden' name='action' value='<%= action.name %>'>
|
6
|
+
<div class='tryForm__header'>
|
7
|
+
<input type='text' id='host' name='host' value='<%= host %>'>
|
8
|
+
/api/
|
9
|
+
<input type='text' id='version' name='version' value='v1' class='v'>
|
10
|
+
/<%= controller.name %>/<%= action.name %>
|
11
|
+
</div>
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
<% if action.authenticator_to_use.is_a?(Moonrope::Authenticator) %>
|
14
|
+
<p class='tryForm__heading'>Headers</p>
|
15
|
+
<table class='tryForm__table'>
|
16
|
+
<% for name, options in action.authenticator_to_use.headers %>
|
17
|
+
<tr>
|
18
|
+
<td width="50%"><code><%= name %></code></td>
|
19
|
+
<td width="50%"><input type='text' class='tryForm__tableField headerField' name='<%= name %>'></td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
</table>
|
20
23
|
<% end %>
|
21
|
-
</table>
|
22
|
-
<% end %>
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
<% unless action.params.empty? %>
|
26
|
+
<p class='tryForm__heading'>Parameters</p>
|
27
|
+
<table class='tryForm__table'>
|
28
|
+
<% for name, param in action.params %>
|
29
|
+
<tr>
|
30
|
+
<td width="30%"><code><%= name %></code></td>
|
31
|
+
<td width="20%"><%= friendly_type param[:type] %></td>
|
32
|
+
<td width="50%"><input type='text' class='tryForm__tableField paramField' name='<%= name %>' placeholder='<%= param[:default] %>' data-type='<%= param[:type] %>'></td>
|
33
|
+
</tr>
|
34
|
+
<% end %>
|
35
|
+
</table>
|
33
36
|
<% end %>
|
34
|
-
</table>
|
35
|
-
<% end %>
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
<div class='tryForm__checkbox'>
|
45
|
-
<input type='checkbox' class='tryForm__fullAttrs' name='full' id="full_attrs" <% if action.includes_full_attributes? %>checked='checked'<%end%>>
|
46
|
-
<label for="full_attrs">Yes - include extended attributes</label>
|
47
|
-
</div>
|
48
|
-
</td>
|
49
|
-
</tr>
|
50
|
-
<% end %>
|
51
|
-
<% if action.can_change_expansions? %>
|
52
|
-
<tr>
|
53
|
-
<td width="50%">Include expansions?</td>
|
54
|
-
<td width="50%">
|
55
|
-
<% for expansion in action.available_expansions %>
|
38
|
+
<% if action.can_change_full? || action.can_change_expansions? %>
|
39
|
+
<p class='tryForm__heading'>Structures</p>
|
40
|
+
<table class='tryForm__table'>
|
41
|
+
<% if action.can_change_full? %>
|
42
|
+
<tr>
|
43
|
+
<td width="50%">Include extended attributes?</td>
|
44
|
+
<td width="50%">
|
56
45
|
<div class='tryForm__checkbox'>
|
57
|
-
<input type='checkbox' class='
|
58
|
-
<label for="
|
46
|
+
<input type='checkbox' class='tryForm__fullAttrs' name='full' id="full_attrs" <% if action.includes_full_attributes? %>checked='checked'<%end%>>
|
47
|
+
<label for="full_attrs">Yes - include extended attributes</label>
|
59
48
|
</div>
|
60
|
-
|
61
|
-
</
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
49
|
+
</td>
|
50
|
+
</tr>
|
51
|
+
<% end %>
|
52
|
+
<% if action.can_change_expansions? %>
|
53
|
+
<tr>
|
54
|
+
<td width="50%">Include expansions?</td>
|
55
|
+
<td width="50%">
|
56
|
+
<% for expansion in action.available_expansions %>
|
57
|
+
<div class='tryForm__checkbox'>
|
58
|
+
<input type='checkbox' class='tryForm__expansions' name='<%= expansion%>' id="expan_<%= expansion %>" <% if action.includes_expansion?(expansion) %>checked='checked'<%end%>>
|
59
|
+
<label for="expan_<%= expansion %>"><%= expansion %></label>
|
60
|
+
</div>
|
61
|
+
<% end %>
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
<% end %>
|
66
65
|
|
67
|
-
|
66
|
+
</table>
|
68
67
|
|
69
|
-
|
70
|
-
<button class='tryForm__buttonLink' type='submit'>Make this request</button>
|
71
|
-
<button class='tryForm__buttonLink tryFormCancel' type='button'>Cancel</button>
|
72
|
-
</p>
|
73
|
-
|
74
|
-
<pre class='tryForm__output'>The request output will be shown here...</pre>
|
75
|
-
</form>
|
68
|
+
<% end %>
|
76
69
|
|
70
|
+
<p class='tryForm__button'>
|
71
|
+
<button class='tryForm__buttonLink' type='submit'>Make this request</button>
|
72
|
+
<button class='tryForm__buttonLink tryFormCancel' type='button'>Cancel</button>
|
73
|
+
</p>
|
77
74
|
|
75
|
+
<pre class='tryForm__output'>The request output will be shown here...</pre>
|
76
|
+
</form>
|
77
|
+
<% end %>
|
@@ -97,11 +97,17 @@ $(document).ready(function() {
|
|
97
97
|
outputBox.text(JSON.stringify(data, null, 4))
|
98
98
|
outputBox.show()
|
99
99
|
},
|
100
|
-
error: function() {
|
100
|
+
error: function(xhr) {
|
101
101
|
// Errors which occurr aren't very well reported at the moment.
|
102
102
|
// They should be.
|
103
|
+
if(xhr.getResponseHeader('content-type') == 'application/json') {
|
104
|
+
var text = JSON.stringify(JSON.parse(xhr.responseText), null, 4)
|
105
|
+
} else {
|
106
|
+
var text = "Failed to make request."
|
107
|
+
}
|
108
|
+
|
103
109
|
outputBox.show()
|
104
|
-
outputBox.text(
|
110
|
+
outputBox.text(text)
|
105
111
|
outputBox.addClass('tryForm__output--error').removeClass('tryForm__output--success')
|
106
112
|
}
|
107
113
|
})
|
@@ -6,6 +6,7 @@
|
|
6
6
|
<% else %>
|
7
7
|
<% set_page_title "#{humanize(authenticator.name.to_s.capitalize)} Authenticator" %>
|
8
8
|
<h1><%= humanize(authenticator.name.to_s.capitalize) %> Authenticator</h1>
|
9
|
+
<% set_active_nav "authenticator-#{authenticator.name.to_s}" %>
|
9
10
|
<% end %>
|
10
11
|
|
11
12
|
<p class='text'>
|
data/templates/basic/layout.erb
CHANGED
@@ -17,10 +17,10 @@
|
|
17
17
|
Home
|
18
18
|
</a>
|
19
19
|
</li>
|
20
|
-
<%
|
20
|
+
<% base.authenticators.select { |k,v| v.friendly_name }.each do |id, authenticator| %>
|
21
21
|
<li>
|
22
|
-
<a href='<%= path('authenticators/
|
23
|
-
|
22
|
+
<a href='<%= path('authenticators/' + id.to_s) %>' class="<%= active_nav == "authenticator-" + id.to_s ? 'active' : '' %>">
|
23
|
+
<%= authenticator.friendly_name %>
|
24
24
|
</a>
|
25
25
|
</li>
|
26
26
|
<% end %>
|
@@ -68,6 +68,14 @@ class RackMiddlewareTest < Test::Unit::TestCase
|
|
68
68
|
assert_equal 'Adam', response_json['data']
|
69
69
|
end
|
70
70
|
|
71
|
+
def test_params_in_body_with_charset
|
72
|
+
post "/api/v1/users/echo", '{"name":"Adam"}', {'CONTENT_TYPE' => 'application/json; charset=utf8'}
|
73
|
+
assert_equal 200, last_response.status
|
74
|
+
assert response_json = JSON.parse(last_response.body)
|
75
|
+
assert_equal 'success', response_json['status']
|
76
|
+
assert_equal 'Adam', response_json['data']
|
77
|
+
end
|
78
|
+
|
71
79
|
def test_passing_invalid_json_renders_a_bad_request
|
72
80
|
get "/api/v1/users/list", {:params => "{invalidjson}"}
|
73
81
|
assert_equal 400, last_response.status
|
@@ -332,4 +332,59 @@ class StructuresTest < Test::Unit::TestCase
|
|
332
332
|
assert_equal "Bananas!", base.structure(:animal).attributes[:basic].select { |a| a.name == :example2 }.first.description
|
333
333
|
end
|
334
334
|
|
335
|
+
def test_mutating_values
|
336
|
+
base = Moonrope::Base.new do
|
337
|
+
structure :animal do
|
338
|
+
basic :name, :mutation => :downcase
|
339
|
+
end
|
340
|
+
end
|
341
|
+
assert_equal 'fido', base.structure(:animal).hash(Animal.new(:name => 'FIDO'))[:name]
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_auto_mutating_values
|
345
|
+
base = Moonrope::Base.new do
|
346
|
+
structure :animal do
|
347
|
+
basic :name, :type => :unix_timestamp
|
348
|
+
end
|
349
|
+
end
|
350
|
+
assert_equal 1234567890, base.structure(:animal).hash(Animal.new(:name => Time.at(1234567890)))[:name]
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_manually_selecting_attributes
|
354
|
+
base = Moonrope::Base.new do
|
355
|
+
structure :animal do
|
356
|
+
basic :id
|
357
|
+
basic :name
|
358
|
+
end
|
359
|
+
end
|
360
|
+
hash = base.structure(:animal).hash(Animal.new(:id => 12345, :name => "Fido"), :attributes => [:id])
|
361
|
+
assert_equal 12345, hash[:id]
|
362
|
+
assert_equal false, hash.has_key?(:name)
|
363
|
+
end
|
364
|
+
|
365
|
+
|
366
|
+
def test_setting_options_for_embedded_expansions
|
367
|
+
user = User.new(:id => 1, :username => 'dave')
|
368
|
+
animal1 = Animal.new(:id => 1, :name => 'Fido', :color => 'Ginger', :user => user)
|
369
|
+
animal2 = Animal.new(:id => 2, :name => 'Jess', :color => 'Black & White', :user => user)
|
370
|
+
user.animals << animal1
|
371
|
+
user.animals << animal2
|
372
|
+
|
373
|
+
base = Moonrope::Base.new do
|
374
|
+
structure :user do
|
375
|
+
basic { {:id => o.id, :username => o.username } }
|
376
|
+
expansion :animals, :structure => :animal
|
377
|
+
end
|
378
|
+
|
379
|
+
structure :animal do
|
380
|
+
basic :id
|
381
|
+
basic :name
|
382
|
+
full :color
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
hash = base.structure(:user).hash(user, :expansions => [{:animals => {:full => true}}])
|
387
|
+
assert_equal 'Ginger', hash[:animals][0][:color]
|
388
|
+
end
|
389
|
+
|
335
390
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moonrope
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Cooke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -192,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
192
192
|
version: '0'
|
193
193
|
requirements: []
|
194
194
|
rubyforge_project:
|
195
|
-
rubygems_version: 2.
|
195
|
+
rubygems_version: 2.5.1
|
196
196
|
signing_key:
|
197
197
|
specification_version: 4
|
198
198
|
summary: An API server DSL.
|