Class: Moonrope::Action

Inherits:
Object
  • Object
show all
Defined in:
lib/moonrope/action.rb

Constant Summary collapse

TRUE_LIKE_VALUES =
['true', '1', 1, true]
FALSE_LIKE_VALUES =
['false', '0', 0, false]
BOOLEAN_VALUES =
TRUE_LIKE_VALUES + FALSE_LIKE_VALUES

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(controller, name) { ... } ⇒ Action

Initialize a new action

Parameters:

  • controller (Moonrope::Controller)

    the controller this action belongs to

  • name (Symbol)

    the name of the action

Yields:

  • allows the action to be configured via Moonrope::DSL::ActionDSL



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/moonrope/action.rb', line 56

def initialize(controller, name, &block)
  @controller = controller
  @name = name
  @params = {}
  @errors = {}
  @traits = []
  @actions = []
  @filters = {}
  @dsl = Moonrope::DSL::ActionDSL.new(self)
  @dsl.instance_eval(&block) if block_given?
end

Instance Attribute Details

#access_ruleSymbol

Returns the name of the access rule for this action.

Returns:

  • (Symbol)

    the name of the access rule for this action



32
33
34
# File 'lib/moonrope/action.rb', line 32

def access_rule
  @access_rule
end

#actionsArray

Returns the actual action blocks for the action.

Returns:

  • (Array)

    the actual action blocks for the action



26
27
28
# File 'lib/moonrope/action.rb', line 26

def actions
  @actions
end

#authenticatorSymbol

Returns the name of the authenticator for this action.

Returns:

  • (Symbol)

    the name of the authenticator for this action



29
30
31
# File 'lib/moonrope/action.rb', line 29

def authenticator
  @authenticator
end

#controllerMoonrope::Controller (readonly)

Returns the associated controller.

Returns:



8
9
10
# File 'lib/moonrope/action.rb', line 8

def controller
  @controller
end

#descriptionString

Returns the description of the action.

Returns:

  • (String)

    the description of the action



23
24
25
# File 'lib/moonrope/action.rb', line 23

def description
  @description
end

#docBool

Returns whether or not the action should be documented.

Returns:

  • (Bool)

    whether or not the action should be documented



41
42
43
# File 'lib/moonrope/action.rb', line 41

def doc
  @doc
end

#dslMoonrope::DSL::Action (readonly)

Returns the action’s DSL.

Returns:

  • (Moonrope::DSL::Action)

    the action’s DSL



14
15
16
# File 'lib/moonrope/action.rb', line 14

def dsl
  @dsl
end

#errorsHash

Returns the errors which can be retuend by this action.

Returns:

  • (Hash)

    the errors which can be retuend by this action



35
36
37
# File 'lib/moonrope/action.rb', line 35

def errors
  @errors
end

#filtersHash (readonly)

Returns a hash of filters that are applied.

Returns:

  • (Hash)

    a hash of filters that are applied



47
48
49
# File 'lib/moonrope/action.rb', line 47

def filters
  @filters
end

#nameSymbol (readonly)

Returns the name of the action.

Returns:

  • (Symbol)

    the name of the action



11
12
13
# File 'lib/moonrope/action.rb', line 11

def name
  @name
end

#paramsHash (readonly)

Returns the params available for the action.

Returns:

  • (Hash)

    the params available for the action



17
18
19
# File 'lib/moonrope/action.rb', line 17

def params
  @params
end

#returnsHash

Returns details of what will be returned on success.

Returns:

  • (Hash)

    details of what will be returned on success



38
39
40
# File 'lib/moonrope/action.rb', line 38

def returns
  @returns
end

#titleString

Returns the title of the action.

Returns:

  • (String)

    the title of the action



20
21
22
# File 'lib/moonrope/action.rb', line 20

def title
  @title
end

#traitsArray (readonly)

Returns additional traits that have been applied to this action.

Returns:

  • (Array)

    additional traits that have been applied to this action



44
45
46
# File 'lib/moonrope/action.rb', line 44

def traits
  @traits
end

Instance Method Details

#access_rule_to_useSymbol

Return the access rule to use for this action#

Returns:

  • (Symbol)


102
103
104
# File 'lib/moonrope/action.rb', line 102

def access_rule_to_use
  @access_rule_to_use ||= access_rule || @controller.access_rule || :default
end

#authenticator_to_useMoonrope::Authenticator

 Return the authenticator that should be used when executing this action



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/moonrope/action.rb', line 85

def authenticator_to_use
  @authenticator_to_use ||= begin
    if @authenticator
      @controller.base.authenticators[@authenticator] || :not_found
    elsif @controller.authenticator
      @controller.base.authenticators[@controller.authenticator] || :not_found
    else
      @controller.base.authenticators[:default] || :none
    end
  end
end

#available_expansionsObject

Which expansions is the user permitted to include/exclude when calling this action.



319
320
321
322
323
324
325
326
327
328
329
# File 'lib/moonrope/action.rb', line 319

def available_expansions
  if returns && (structure = returns[:structure]) && can_change_expansions?
    if returns[:structure_opts][:paramable].is_a?(Hash) && returns[:structure_opts][:paramable][:expansions].is_a?(Array)
      returns[:structure_opts][:paramable][:expansions]
    else
      @controller.base.structure(structure).all_expansions
    end
  else
    []
  end
end

#can_change_expansions?Boolean

 Does this action allow the user to include/exclude expansions when calling this action?

Returns:

  • (Boolean)


292
293
294
295
296
297
298
299
# File 'lib/moonrope/action.rb', line 292

def can_change_expansions?
  if returns && opts = returns[:structure_opts]
    opts[:paramable] == true ||
    (opts[:paramable].is_a?(Hash) && opts[:paramable].has_key?(:expansions))
  else
    false
  end
end

#can_change_full?Boolean

Does this action allow the user to include/exclude full attributes when calling this action?

Returns:

  • (Boolean)


267
268
269
270
271
272
273
274
# File 'lib/moonrope/action.rb', line 267

def can_change_full?
  if returns && opts = returns[:structure_opts]
    opts[:paramable] == true ||
    (opts[:paramable].is_a?(Hash) && opts[:paramable].has_key?(:full))
  else
    false
  end
end

#check_access(request = nil) ⇒ Boolean

Check whether the authenticated user has access to this request. Accepts a Request or an EvalEnvironment.

Parameters:

Returns:

  • (Boolean)


196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/moonrope/action.rb', line 196

def check_access(request = nil)
  if request.is_a?(EvalEnvironment)
    eval_environment = request
  else
    eval_environment = EvalEnvironment.new(@controller.base, request, self)
  end

  if authenticator_to_use.is_a?(Moonrope::Authenticator)
    if rule = authenticator_to_use.rules[access_rule_to_use]
      eval_environment.instance_exec(self, &rule[:block]) == true
    else
      if access_rule_to_use == :default
        # The default rule on any authenticator will allow everything so we
        # don't need to worry about this not being defined.
        true
      else
        # If an access rule that doesn't exist has been requested, we will
        # raise an internal error.
        raise Moonrope::Errors::MissingAccessRule, "The rule '#{access_rule_to_use}' was not found on '#{authenticator_to_use.name}' authenticator"
      end
    end
  else
    true
  end
end

#convert_errors_to_action_result(start_time = nil, &block) ⇒ Object

Execute a block of code and catch approprite Moonrope errors and return a result.



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/moonrope/action.rb', line 110

def convert_errors_to_action_result(start_time = nil, &block)
  begin
    yield block
  rescue => exception
    case exception
    when Moonrope::Errors::RequestError
      result = ActionResult.new(self)
      result.time = start_time ? (Time.now - start_time).round(2) : nil
      result.status = exception.status
      result.data = exception.data
      result
    else
      if error_block = @controller.base.external_errors[exception.class]
        result = ActionResult.new(self)
        result.time = start_time ? (Time.now - start_time).round(2) : nil
        error_block.call(exception, result)
        result
      else
        raise
      end
    end
  end
end

#default_paramsHash

Return a hash of all params for this action which are

Returns:

  • (Hash)

    hash with field names as keys with default values



73
74
75
76
77
78
# File 'lib/moonrope/action.rb', line 73

def default_params
  @params.inject({}) do |h,(k,v)|
    h[k.to_s] = v[:default] if v[:default]
    h
  end
end

#execute(request = nil) ⇒ Moonrope::ActionResult

Executes the action and returns a ActionResult object with the result of the action.

Parameters:

Returns:



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/moonrope/action.rb', line 141

def execute(request = nil)
  if request.is_a?(EvalEnvironment)
    eval_environment = request
  else
    eval_environment = EvalEnvironment.new(@controller.base, request, self)
  end

  #
  # Set this actions default parameters in the eval environment so that
  # it has access to them.
  #
  eval_environment.default_params = self.default_params

  start_time = Time.now

  convert_errors_to_action_result(start_time) do
    #
    # Validate the parameters
    #
    self.validate_parameters(eval_environment.params)

    # Run before filters
    controller.before_actions_for(name).each do |action|
      eval_environment.instance_eval(&action.block)
    end

    # Run the actual action
    response = nil
    actions.each do |action|
      response = eval_environment.instance_exec(response, &action)
    end

    # Calculate the length of time this request takes
    time_to_run = Time.now - start_time

    # Prepare a action result
    result = ActionResult.new(self)
    result.data     = response
    result.status   = 'success'
    result.time     = time_to_run.round(2)
    result.flags    = eval_environment.flags
    result.headers  = eval_environment.headers

    # Return the result object
    result
  end
end

#includes_expansion?(expansion) ⇒ Boolean

Does this action include full attributes by default?

Returns:

  • (Boolean)


304
305
306
307
308
309
310
311
312
313
# File 'lib/moonrope/action.rb', line 304

def includes_expansion?(expansion)
  if returns && opts = returns[:structure_opts]
    (opts[:paramable].is_a?(Hash) && opts[:paramable][:expansions] == true) ||
    opts[:expansions] == true ||
    (opts[:paramable].is_a?(Hash) && opts[:paramable][:expansions].is_a?(Array) && opts[:paramable][:expansions].include?(expansion)) ||
    (opts[:expansions].is_a?(Array) && opts[:expansions].include?(expansion))
  else
    false
  end
end

#includes_full_attributes?Boolean

Does this action include full attributes by default?

Returns:

  • (Boolean)


279
280
281
282
283
284
285
286
# File 'lib/moonrope/action.rb', line 279

def includes_full_attributes?
  if returns && opts = returns[:structure_opts]
    (opts[:paramable].is_a?(Hash) && opts[:paramable][:full] == true) ||
    opts[:full] == true
  else
    false
  end
end

#validate_parameters(param_set) ⇒ Boolean

Return whether or not the passed ParamSet is valid for this action

Parameters:

Returns:

  • (Boolean)


228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/moonrope/action.rb', line 228

def validate_parameters(param_set)
  @params.each do |name, value|
    if value[:required] && param_set[name].nil?
      raise Moonrope::Errors::ParameterError, "`#{name}` parameter is required but is missing"
    end

    if value[:regex] && param_set[name] && !(param_set[name].to_s =~ value[:regex])
      raise Moonrope::Errors::ParameterError, "`#{name}` parameter is invalid"
    end

    if value[:options].is_a?(Array) && param_set[name] && !value[:options].include?(param_set[name])
      raise Moonrope::Errors::ParameterError, "`#{name}` must be one of #{value[:options].join(', ')}"
    end

    if value[:type] && param_set[name]
      if value[:type] == :boolean
        if BOOLEAN_VALUES.include?(param_set[name])
          param_set._set_value(name, TRUE_LIKE_VALUES.include?(param_set[name]))
        else
          raise Moonrope::Errors::ParameterError, "`#{name}` should be a boolean value"
        end
      elsif value[:type].is_a?(Symbol) || value[:type].is_a?(String)
        # Value is a symbol, nothing to do.
      elsif !param_set[name].is_a?(value[:type])
        raise Moonrope::Errors::ParameterError, "`#{name}` should be a `#{value[:type]}` but is a `#{param_set[name].class}`"
      end
    end
  end
  true
end