moonrope 1.3.3 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +9 -0
- data/Gemfile.lock +47 -0
- data/MIT-LICENCE +20 -0
- data/README.md +24 -0
- data/bin/moonrope +28 -0
- data/docs/authentication.md +114 -0
- data/docs/controllers.md +106 -0
- data/docs/exceptions.md +27 -0
- data/docs/introduction.md +29 -0
- data/docs/structures.md +214 -0
- data/example/authentication.rb +50 -0
- data/example/controllers/meta_controller.rb +14 -0
- data/example/controllers/users_controller.rb +92 -0
- data/example/structures/pet_structure.rb +12 -0
- data/example/structures/user_structure.rb +35 -0
- data/lib/moonrope.rb +5 -4
- data/lib/moonrope/action.rb +170 -40
- data/lib/moonrope/authenticator.rb +42 -0
- data/lib/moonrope/base.rb +67 -6
- data/lib/moonrope/controller.rb +4 -2
- data/lib/moonrope/doc_context.rb +94 -0
- data/lib/moonrope/doc_server.rb +123 -0
- data/lib/moonrope/dsl/action_dsl.rb +159 -9
- data/lib/moonrope/dsl/authenticator_dsl.rb +35 -0
- data/lib/moonrope/dsl/base_dsl.rb +21 -18
- data/lib/moonrope/dsl/controller_dsl.rb +60 -9
- data/lib/moonrope/dsl/filterable_dsl.rb +27 -0
- data/lib/moonrope/dsl/structure_dsl.rb +28 -2
- data/lib/moonrope/errors.rb +13 -0
- data/lib/moonrope/eval_environment.rb +82 -3
- data/lib/moonrope/eval_helpers.rb +47 -8
- data/lib/moonrope/eval_helpers/filter_helper.rb +82 -0
- data/lib/moonrope/guard.rb +35 -0
- data/lib/moonrope/html_generator.rb +65 -0
- data/lib/moonrope/param_set.rb +11 -1
- data/lib/moonrope/rack_middleware.rb +66 -37
- data/lib/moonrope/railtie.rb +31 -14
- data/lib/moonrope/request.rb +43 -15
- data/lib/moonrope/structure.rb +100 -18
- data/lib/moonrope/structure_attribute.rb +39 -0
- data/lib/moonrope/version.rb +1 -1
- data/moonrope.gemspec +21 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/specs/action_spec.rb +455 -0
- data/spec/specs/base_spec.rb +29 -0
- data/spec/specs/controller_spec.rb +31 -0
- data/spec/specs/param_set_spec.rb +31 -0
- data/templates/basic/_action_form.erb +77 -0
- data/templates/basic/_errors_table.erb +32 -0
- data/templates/basic/_structure_attributes_list.erb +55 -0
- data/templates/basic/action.erb +168 -0
- data/templates/basic/assets/lock.svg +3 -0
- data/templates/basic/assets/reset.css +101 -0
- data/templates/basic/assets/style.css +348 -0
- data/templates/basic/assets/tool.svg +4 -0
- data/templates/basic/assets/try.js +157 -0
- data/templates/basic/authenticator.erb +52 -0
- data/templates/basic/controller.erb +20 -0
- data/templates/basic/index.erb +114 -0
- data/templates/basic/layout.erb +46 -0
- data/templates/basic/structure.erb +23 -0
- data/test/test_helper.rb +81 -0
- data/test/tests/action_access_test.rb +63 -0
- data/test/tests/actions_test.rb +524 -0
- data/test/tests/authenticators_test.rb +87 -0
- data/test/tests/base_test.rb +35 -0
- data/test/tests/controllers_test.rb +49 -0
- data/test/tests/eval_environment_test.rb +136 -0
- data/test/tests/evel_helpers_test.rb +60 -0
- data/test/tests/examples_test.rb +11 -0
- data/test/tests/helpers_test.rb +97 -0
- data/test/tests/param_set_test.rb +44 -0
- data/test/tests/rack_middleware_test.rb +131 -0
- data/test/tests/request_test.rb +232 -0
- data/test/tests/structures_param_extensions_test.rb +159 -0
- data/test/tests/structures_test.rb +398 -0
- metadata +71 -56
@@ -0,0 +1,35 @@
|
|
1
|
+
module Moonrope
|
2
|
+
module DSL
|
3
|
+
class AuthenticatorDSL
|
4
|
+
|
5
|
+
def initialize(authenticator)
|
6
|
+
@authenticator = authenticator
|
7
|
+
end
|
8
|
+
|
9
|
+
def friendly_name(value)
|
10
|
+
@authenticator.friendly_name = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def description(value)
|
14
|
+
@authenticator.description = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def header(name, description = nil, options = {})
|
18
|
+
@authenticator.headers[name] = options.merge(:name => name, :description => description)
|
19
|
+
end
|
20
|
+
|
21
|
+
def error(name, description = nil, options = {})
|
22
|
+
@authenticator.errors[name] = options.merge(:name => name, :description => description)
|
23
|
+
end
|
24
|
+
|
25
|
+
def lookup(&block)
|
26
|
+
@authenticator.lookup = block
|
27
|
+
end
|
28
|
+
|
29
|
+
def rule(name, error_code, description = nil, &block)
|
30
|
+
@authenticator.rules[name] = {:name => name, :error_code => error_code, :description => description, :block => block}
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'moonrope/structure'
|
2
|
+
require 'moonrope/controller'
|
3
|
+
require 'moonrope/authenticator'
|
4
|
+
|
1
5
|
module Moonrope
|
2
6
|
module DSL
|
3
7
|
class BaseDSL
|
@@ -47,24 +51,6 @@ module Moonrope
|
|
47
51
|
controller
|
48
52
|
end
|
49
53
|
|
50
|
-
#
|
51
|
-
# Set the authenticator for the API.
|
52
|
-
#
|
53
|
-
# @yield stores the block as the authenticator
|
54
|
-
#
|
55
|
-
def authenticator(&block)
|
56
|
-
@base.authenticator = block
|
57
|
-
end
|
58
|
-
|
59
|
-
#
|
60
|
-
# Set the default access check block.
|
61
|
-
#
|
62
|
-
# @yield stores the block as the access check
|
63
|
-
#
|
64
|
-
def default_access(value = nil, &block)
|
65
|
-
@base.default_access = block_given? ? block : value
|
66
|
-
end
|
67
|
-
|
68
54
|
#
|
69
55
|
# Define a new helper in the global namespace
|
70
56
|
#
|
@@ -81,6 +67,23 @@ module Moonrope
|
|
81
67
|
helper_instance
|
82
68
|
end
|
83
69
|
|
70
|
+
#
|
71
|
+
# Define a new authenticator
|
72
|
+
#
|
73
|
+
def authenticator(name, &block)
|
74
|
+
authenticator = Moonrope::Authenticator.new(name)
|
75
|
+
dsl = Moonrope::DSL::AuthenticatorDSL.new(authenticator)
|
76
|
+
dsl.instance_eval(&block) if block_given?
|
77
|
+
@base.authenticators[name] = authenticator
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Define a new global shared action
|
82
|
+
#
|
83
|
+
def shared_action(name, &block)
|
84
|
+
@base.shared_actions[name] = block
|
85
|
+
end
|
86
|
+
|
84
87
|
end
|
85
88
|
end
|
86
89
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'moonrope/action'
|
2
|
+
require 'moonrope/before_action'
|
3
|
+
|
1
4
|
module Moonrope
|
2
5
|
module DSL
|
3
6
|
class ControllerDSL
|
@@ -14,6 +17,31 @@ module Moonrope
|
|
14
17
|
# @return [Moonrope::Controller] the associated controller
|
15
18
|
attr_reader :controller
|
16
19
|
|
20
|
+
#
|
21
|
+
# Stop this controller frmo being documented
|
22
|
+
#
|
23
|
+
def no_doc!
|
24
|
+
@controller.doc = false
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Set the friendly name for the controller
|
29
|
+
#
|
30
|
+
# @param name [String]
|
31
|
+
#
|
32
|
+
def friendly_name(string)
|
33
|
+
@controller.friendly_name = string
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Set the description for the controller
|
38
|
+
#
|
39
|
+
# @param description [String]
|
40
|
+
#
|
41
|
+
def description(description)
|
42
|
+
@controller.description = description
|
43
|
+
end
|
44
|
+
|
17
45
|
#
|
18
46
|
# Defines a new action within the controller.
|
19
47
|
#
|
@@ -28,6 +56,29 @@ module Moonrope
|
|
28
56
|
action
|
29
57
|
end
|
30
58
|
|
59
|
+
#
|
60
|
+
# Set the name of the authenticator to use for all actions in this controller
|
61
|
+
#
|
62
|
+
# @param name [Symbol]
|
63
|
+
#
|
64
|
+
def authenticator(name)
|
65
|
+
@controller.authenticator = name
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Set the name of the access rule to use for all actions in this controller
|
70
|
+
#
|
71
|
+
# @param name [Symbol]
|
72
|
+
#
|
73
|
+
def access_rule(name)
|
74
|
+
if name.is_a?(Hash)
|
75
|
+
authenticator name.first[0]
|
76
|
+
access_rule name.first[1]
|
77
|
+
else
|
78
|
+
@controller.access_rule = name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
31
82
|
#
|
32
83
|
# Defines a new before action within the controller.
|
33
84
|
#
|
@@ -43,14 +94,6 @@ module Moonrope
|
|
43
94
|
before_action
|
44
95
|
end
|
45
96
|
|
46
|
-
#
|
47
|
-
# Defines the access required for controller methods which do not
|
48
|
-
# define their own access.
|
49
|
-
#
|
50
|
-
def access(value = nil, &block)
|
51
|
-
@controller.access = block_given? ? block : value
|
52
|
-
end
|
53
|
-
|
54
97
|
#
|
55
98
|
# Defines a new helper for this controller.
|
56
99
|
#
|
@@ -61,9 +104,17 @@ module Moonrope
|
|
61
104
|
if @controller.base.helper(name, @controller)
|
62
105
|
raise Moonrope::Errors::HelperAlreadyDefined, "Helper has already been defined with name `#{name}`"
|
63
106
|
end
|
64
|
-
|
65
107
|
@controller.base.helpers << Moonrope::Helper.new(name, @controller, options, &block)
|
66
108
|
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Define a shared action which can be used by any action
|
112
|
+
#
|
113
|
+
# @param name[Symbol] the name of the shared action
|
114
|
+
#
|
115
|
+
def shared_action(name, &block)
|
116
|
+
@controller.shared_actions[name] = block
|
117
|
+
end
|
67
118
|
end
|
68
119
|
end
|
69
120
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Moonrope
|
2
|
+
module DSL
|
3
|
+
class FilterableDSL
|
4
|
+
|
5
|
+
def initialize(action)
|
6
|
+
@action = action
|
7
|
+
end
|
8
|
+
|
9
|
+
def attribute(name, options = {}, &block)
|
10
|
+
if options[:type] == Integer || options[:type] == Float
|
11
|
+
# Numbers
|
12
|
+
options[:operators] ||= [:eq, :not_eq, :gt, :gte, :lt, :lte, :in, :not_in]
|
13
|
+
elsif options[:type] == String
|
14
|
+
# Strings
|
15
|
+
options[:operators] ||= [:eq, :not_eq, :starts_with, :ends_with, :in, :not_in]
|
16
|
+
elsif options[:type] == :timestamp
|
17
|
+
# Times
|
18
|
+
options[:operators] ||= [:eq, :not_eq, :gt, :gte, :lt, :lte]
|
19
|
+
else
|
20
|
+
# Everything else
|
21
|
+
options[:operators] ||= [:eq, :not_eq]
|
22
|
+
end
|
23
|
+
@action.filters[name] = options.merge(:name => name, :block => block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'moonrope/structure_attribute'
|
2
|
+
|
1
3
|
module Moonrope
|
2
4
|
module DSL
|
3
5
|
class StructureDSL
|
@@ -26,6 +28,10 @@ module Moonrope
|
|
26
28
|
@conditions = []
|
27
29
|
end
|
28
30
|
|
31
|
+
def no_doc!
|
32
|
+
@structure.doc = false
|
33
|
+
end
|
34
|
+
|
29
35
|
def scope(options = {}, &block)
|
30
36
|
scope_dsl = self.class.new(@structure)
|
31
37
|
scope_dsl.options = options
|
@@ -35,12 +41,21 @@ module Moonrope
|
|
35
41
|
def group(name, &block)
|
36
42
|
scope_dsl = self.class.new(@structure)
|
37
43
|
scope_dsl.groups = [@groups, name].flatten
|
44
|
+
scope_dsl.conditions = @conditions
|
38
45
|
scope_dsl.instance_eval(&block)
|
39
46
|
end
|
40
47
|
|
41
|
-
def condition(condition, &block)
|
48
|
+
def condition(condition, description = nil, &block)
|
42
49
|
scope_dsl = self.class.new(@structure)
|
50
|
+
if condition.is_a?(Hash) && condition.size == 1
|
51
|
+
condition = {:authenticator => condition.first[0], :access_rule => condition.first[1]}
|
52
|
+
elsif condition.is_a?(Symbol)
|
53
|
+
condition = {:authenticator => :default, :access_rule => condition}
|
54
|
+
else
|
55
|
+
condition = {:block => condition, :description => description}
|
56
|
+
end
|
43
57
|
scope_dsl.conditions = [@conditions, condition].flatten
|
58
|
+
scope_dsl.groups = @groups
|
44
59
|
scope_dsl.instance_eval(&block)
|
45
60
|
end
|
46
61
|
|
@@ -61,6 +76,8 @@ module Moonrope
|
|
61
76
|
attribute.source_attribute = options[:source_attribute]
|
62
77
|
attribute.value = options[:value]
|
63
78
|
attribute.example = options[:eg] || options[:example]
|
79
|
+
attribute.doc = options[:doc]
|
80
|
+
attribute.mutation = options[:mutation]
|
64
81
|
attribute.groups = @groups
|
65
82
|
attribute.conditions = @conditions
|
66
83
|
@structure.attributes[type] << attribute
|
@@ -84,7 +101,16 @@ module Moonrope
|
|
84
101
|
|
85
102
|
def expansion(name, *args, &block)
|
86
103
|
if block_given?
|
87
|
-
|
104
|
+
if args[0].is_a?(String)
|
105
|
+
attrs = args[1] || {}
|
106
|
+
attrs[:description] = args[0]
|
107
|
+
elsif args[0].is_a?(Hash)
|
108
|
+
attrs = atrs[0]
|
109
|
+
else
|
110
|
+
attrs = {}
|
111
|
+
end
|
112
|
+
|
113
|
+
@structure.expansions[name] = attrs.merge({:block => block, :conditions => @conditions})
|
88
114
|
else
|
89
115
|
attribute(:expansion, name, *args)
|
90
116
|
end
|
data/lib/moonrope/errors.rb
CHANGED
@@ -5,6 +5,9 @@ module Moonrope
|
|
5
5
|
end
|
6
6
|
|
7
7
|
class HelperAlreadyDefined < Error; end
|
8
|
+
class MissingAuthenticator < Error; end
|
9
|
+
class MissingAccessRule < Error; end
|
10
|
+
class InvalidSharedAction < Error; end
|
8
11
|
|
9
12
|
class RequestError < Error
|
10
13
|
attr_reader :options
|
@@ -22,6 +25,16 @@ module Moonrope
|
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
28
|
+
class StructuredError < RequestError
|
29
|
+
def status
|
30
|
+
"error"
|
31
|
+
end
|
32
|
+
|
33
|
+
def data
|
34
|
+
@options
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
25
38
|
class AccessDenied < RequestError
|
26
39
|
def status
|
27
40
|
'access-denied'
|
@@ -1,7 +1,11 @@
|
|
1
|
+
require 'moonrope/eval_helpers'
|
2
|
+
require 'moonrope/eval_helpers/filter_helper'
|
3
|
+
|
1
4
|
module Moonrope
|
2
5
|
class EvalEnvironment
|
3
6
|
|
4
7
|
include Moonrope::EvalHelpers
|
8
|
+
include Moonrope::EvalHelpers::FilterHelper
|
5
9
|
|
6
10
|
# @return [Moonrope::Base] the base object
|
7
11
|
attr_reader :base
|
@@ -28,9 +32,10 @@ module Moonrope
|
|
28
32
|
# @param request [Moonrope::Request]
|
29
33
|
# @param accessors [Hash] additional variables which can be made available
|
30
34
|
#
|
31
|
-
def initialize(base, request, accessors = {})
|
35
|
+
def initialize(base, request, action = nil, accessors = {})
|
32
36
|
@base = base
|
33
37
|
@request = request
|
38
|
+
@action = action
|
34
39
|
@accessors = accessors
|
35
40
|
@default_params = {}
|
36
41
|
reset
|
@@ -46,8 +51,8 @@ module Moonrope
|
|
46
51
|
#
|
47
52
|
# @return [Object] the authenticated object
|
48
53
|
#
|
49
|
-
def
|
50
|
-
request ? request.
|
54
|
+
def identity
|
55
|
+
request ? request.identity : nil
|
51
56
|
end
|
52
57
|
|
53
58
|
#
|
@@ -143,6 +148,54 @@ module Moonrope
|
|
143
148
|
raise Moonrope::Errors::Error, "No structure found named '#{structure_name}'"
|
144
149
|
end
|
145
150
|
|
151
|
+
if options.delete(:return)
|
152
|
+
if options.empty? && action && action.returns && action.returns[:structure_opts].is_a?(Hash)
|
153
|
+
options = action.returns[:structure_opts]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
if request
|
158
|
+
if options[:paramable]
|
159
|
+
if options[:paramable].is_a?(Hash)
|
160
|
+
options[:expansions] = options[:paramable][:expansions]
|
161
|
+
options[:full] = options[:paramable][:full]
|
162
|
+
end
|
163
|
+
|
164
|
+
if options[:paramable] == true || options[:paramable].is_a?(Hash) && options[:paramable].has_key?(:expansions)
|
165
|
+
if request.params["_expansions"].is_a?(Array)
|
166
|
+
options[:expansions] = request.params["_expansions"].map(&:to_sym)
|
167
|
+
if options[:paramable].is_a?(Hash) && options[:paramable][:expansions].is_a?(Array)
|
168
|
+
whitelist = options[:paramable][:expansions]
|
169
|
+
options[:expansions].reject! { |e| !whitelist.include?(e) }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
if request.params["_expansions"] == true
|
174
|
+
if options[:paramable].is_a?(Hash)
|
175
|
+
if options[:paramable][:expansions].is_a?(Array)
|
176
|
+
options[:expansions] = options[:paramable][:expansions]
|
177
|
+
elsif options[:paramable].has_key?(:expansions)
|
178
|
+
options[:expansions] = true
|
179
|
+
end
|
180
|
+
else
|
181
|
+
options[:expansions] = true
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
if request.params["_expansions"] == false
|
186
|
+
options[:expansions] = nil
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
if request.params.has?("_full")
|
192
|
+
if options[:paramable] == true || (options[:paramable].is_a?(Hash) && options[:paramable].has_key?(:full))
|
193
|
+
options[:full] = !!request.params["_full"]
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
146
199
|
structure.hash(object, options.merge(:request => @request))
|
147
200
|
end
|
148
201
|
|
@@ -169,5 +222,31 @@ module Moonrope
|
|
169
222
|
self.structure_for(structure_name).is_a?(Moonrope::Structure)
|
170
223
|
end
|
171
224
|
|
225
|
+
#
|
226
|
+
# Copy the list of parameters onto the given objectr
|
227
|
+
#
|
228
|
+
def copy_params_to(object, *params_to_copy)
|
229
|
+
if params_to_copy.first.is_a?(Hash)
|
230
|
+
options = params_to_copy.shift
|
231
|
+
if options[:from]
|
232
|
+
all_params = action.params.select { |_,p| p[:from_shared_action].include?(options[:from]) }
|
233
|
+
params_to_copy = params_to_copy + all_params.keys
|
234
|
+
end
|
235
|
+
end
|
236
|
+
params_to_copy.each do |param_name|
|
237
|
+
if param_definition = action.params[param_name]
|
238
|
+
if params.has?(param_name)
|
239
|
+
if param_definition[:apply]
|
240
|
+
instance_exec(object, params[param_name], ¶m_definition[:apply])
|
241
|
+
elsif object.respond_to?("#{param_name}=")
|
242
|
+
object.send("#{param_name}=", params[param_name])
|
243
|
+
end
|
244
|
+
end
|
245
|
+
else
|
246
|
+
raise Moonrope::Errors::Error, "Attempted to copy parameter #{parameter} to object but no definition exists"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
172
251
|
end
|
173
252
|
end
|
@@ -7,29 +7,68 @@ module Moonrope
|
|
7
7
|
# @param type [Symbol] the type of error to raise
|
8
8
|
# @param message [String, Hash or Array] options to pass with the error (usually a message)
|
9
9
|
#
|
10
|
-
def error(type, message)
|
10
|
+
def error(type, code_or_message = nil, message = nil)
|
11
11
|
case type
|
12
|
-
when :not_found then raise(Moonrope::Errors::NotFound,
|
13
|
-
when :access_denied then raise(Moonrope::Errors::AccessDenied,
|
14
|
-
when :validation_error then raise(Moonrope::Errors::ValidationError,
|
15
|
-
when :parameter_error then raise(Moonrope::Errors::ParameterError,
|
12
|
+
when :not_found then raise(Moonrope::Errors::NotFound, code_or_message)
|
13
|
+
when :access_denied then raise(Moonrope::Errors::AccessDenied, code_or_message)
|
14
|
+
when :validation_error then raise(Moonrope::Errors::ValidationError, code_or_message)
|
15
|
+
when :parameter_error then raise(Moonrope::Errors::ParameterError, code_or_message)
|
16
|
+
when :structured_error then structured_error(code_or_message, message)
|
16
17
|
else
|
17
|
-
|
18
|
+
if type.is_a?(String)
|
19
|
+
if code_or_message.is_a?(Hash)
|
20
|
+
structured_error(type, nil, code_or_message)
|
21
|
+
else
|
22
|
+
structured_error(type, code_or_message, message.is_a?(Hash) ? message : {})
|
23
|
+
end
|
24
|
+
else
|
25
|
+
raise Moonrope::Errors::RequestError, code_or_message
|
26
|
+
end
|
18
27
|
end
|
19
28
|
end
|
20
29
|
|
30
|
+
#
|
31
|
+
# Raises a structured error.
|
32
|
+
#
|
33
|
+
# @param code [String] the code to return
|
34
|
+
# @param message [String] explantory text to return
|
35
|
+
# @param additional [Hash] additional data to return with the error
|
36
|
+
#
|
37
|
+
def structured_error(code, message, additional = {})
|
38
|
+
if action
|
39
|
+
if action.authenticator_to_use.is_a?(Moonrope::Authenticator)
|
40
|
+
errors = action.authenticator_to_use.errors.merge(action.errors)
|
41
|
+
else
|
42
|
+
errors = action.errors
|
43
|
+
end
|
44
|
+
if error = errors[code]
|
45
|
+
message = error[:description].gsub(/\{(\w+)\}/) { additional[$1.to_sym] }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
raise Moonrope::Errors::StructuredError, {:code => code, :message => message}.merge(additional)
|
49
|
+
end
|
50
|
+
|
21
51
|
#
|
22
52
|
# Return paginated information
|
23
53
|
#
|
24
54
|
def paginate(collection, max_per_page = 60, &block)
|
25
55
|
per_page = params.per_page || 30
|
26
56
|
per_page = max_per_page if per_page < 1 || per_page > max_per_page
|
27
|
-
paginated_results = collection.page(params.page).per(per_page)
|
28
|
-
set_flag :paginated, {:page => params.page, :per_page => per_page, :total_pages => paginated_results.total_pages, :total_records => paginated_results.total_count}
|
57
|
+
paginated_results = collection.page(params.page || 1).per(per_page)
|
58
|
+
set_flag :paginated, {:page => params.page || 1, :per_page => per_page, :total_pages => paginated_results.total_pages, :total_records => paginated_results.total_count}
|
29
59
|
paginated_results.to_a.map do |result|
|
30
60
|
block.call(result)
|
31
61
|
end
|
32
62
|
end
|
33
63
|
|
64
|
+
#
|
65
|
+
# Return information sorted by appropriate values from parameters
|
66
|
+
#
|
67
|
+
def sort(collection, &block)
|
68
|
+
collection = collection.order(params.sort_by => params.order)
|
69
|
+
set_flag :sorted, {:by => params.sort_by, :order => params.order}
|
70
|
+
block.call(collection)
|
71
|
+
end
|
72
|
+
|
34
73
|
end
|
35
74
|
end
|