activefunction 0.3.5 → 0.4.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 +10 -1
- data/README.md +182 -69
- data/lib/.rbnext/2.7/active_function/functions/strong_parameters.rb +84 -41
- data/lib/.rbnext/3.0/active_function/base.rb +58 -0
- data/lib/.rbnext/3.0/active_function/functions/response.rb +38 -19
- data/lib/.rbnext/3.0/active_function.rb +63 -0
- data/lib/.rbnext/3.1/active_function/functions/response.rb +49 -0
- data/lib/active_function/base.rb +52 -14
- data/lib/active_function/functions/callbacks.rb +58 -58
- data/lib/active_function/functions/rendering.rb +36 -9
- data/lib/active_function/functions/response.rb +38 -19
- data/lib/active_function/functions/strong_parameters.rb +84 -41
- data/lib/active_function/version.rb +1 -1
- data/lib/active_function.rb +54 -3
- metadata +55 -26
- data/bin/console +0 -15
- data/bin/rake +0 -27
- data/bin/rubocop +0 -27
- data/bin/ruby-next +0 -16
- data/bin/setup +0 -8
- data/lib/.rbnext/3.0/active_function/functions/core.rb +0 -49
- data/lib/active_function/functions/core.rb +0 -49
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_function_core"
|
4
|
+
require "active_function/version"
|
5
|
+
require "active_function/base"
|
6
|
+
|
7
|
+
RubyNext::Language.setup_gem_load_path(transpile: true)
|
8
|
+
|
9
|
+
module ActiveFunction
|
10
|
+
class << self
|
11
|
+
# Configure ActiveFunction through DSL method calls.
|
12
|
+
# Setups {ActiveFunction::Base} with provided internal and custom plugins.
|
13
|
+
# Also freezes plugins and {ActiveFunction::Base}.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# ActiveFunction.config do
|
17
|
+
# plugin :callbacks
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @param block [Proc] class_eval'ed block in ActiveFunction module.
|
21
|
+
# @return [void]
|
22
|
+
def config(&block)
|
23
|
+
class_eval(&block)
|
24
|
+
@_plugins.freeze
|
25
|
+
self::Base.freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
# List of registered internal plugins.
|
29
|
+
def plugins ; @_plugins ||= {}; end
|
30
|
+
|
31
|
+
# Register internal Symbol'ed plugin.
|
32
|
+
#
|
33
|
+
# @param [Symbol] symbol name of internal plugin,
|
34
|
+
# should match file name in ./lib/active_function/functions/*.rb
|
35
|
+
# @param [Module] mod module to register.
|
36
|
+
def register_plugin(symbol, mod)
|
37
|
+
plugins[symbol] = mod
|
38
|
+
end
|
39
|
+
|
40
|
+
# Add plugin to ActiveFunction::Base.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# ActiveFunction.plugin :callbacks
|
44
|
+
# ActiveFunction.plugin CustomPlugin
|
45
|
+
#
|
46
|
+
# @param [Symbol, Module] mod
|
47
|
+
# @return [void]
|
48
|
+
def plugin(mod)
|
49
|
+
if mod.is_a? Symbol
|
50
|
+
begin
|
51
|
+
require "active_function/functions/#{mod}"
|
52
|
+
mod = plugins.fetch(mod)
|
53
|
+
rescue LoadError
|
54
|
+
raise ArgumentError, "Unknown plugin #{mod}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
self::Base.include(mod)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
plugin :response
|
63
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveFunction
|
4
|
+
module Functions
|
5
|
+
# The only required plugin for {ActiveFunction::Base} to work.
|
6
|
+
# Provides a simple {Response} object to manage response details.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# response = Response.new.tap do |r|
|
10
|
+
# r.body = "Hello World!"
|
11
|
+
# r.headers = {"Content-Type" => "text/plain"}
|
12
|
+
# r.commit!
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# response.performed? # => true
|
16
|
+
# response.to_h # => { statusCode: 200, headers: { "Content-Type" => "text/plain" }, body: "Hello World!" }
|
17
|
+
module Response
|
18
|
+
ActiveFunction.register_plugin :response, self
|
19
|
+
|
20
|
+
class Response < Struct.new(:status, :headers, :body, :committed)
|
21
|
+
# Initializes a new Response instance with default values.
|
22
|
+
#
|
23
|
+
# @param status [Integer] HTTP status code.
|
24
|
+
# @param headers [Hash] HTTP headers.
|
25
|
+
# @param body [Object] Response body.
|
26
|
+
# @param committed [Boolean] Indicates whether the response has been committed (default is false).
|
27
|
+
def initialize(status: 200, headers: {}, body: nil, committed: false) = super(status, headers, body, committed)
|
28
|
+
|
29
|
+
# Converts the Response instance to a hash for JSON serialization.
|
30
|
+
#
|
31
|
+
# @return [Hash{statusCode: Integer, headers: Hash, body: Object}]
|
32
|
+
def to_h
|
33
|
+
{
|
34
|
+
statusCode: status,
|
35
|
+
headers: headers,
|
36
|
+
body: body
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Marks the response as committed.
|
41
|
+
def commit!
|
42
|
+
self.committed = true
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :committed?, :committed
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/active_function/base.rb
CHANGED
@@ -1,20 +1,58 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveFunction
|
4
|
-
class
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
4
|
+
# Abstract base class with request processing logic.
|
5
|
+
class SuperBase
|
6
|
+
attr_reader :action_name, :request, :response
|
7
|
+
|
8
|
+
def initialize(action_name, request, response)
|
9
|
+
@action_name = action_name
|
10
|
+
@request = request
|
11
|
+
@response = response
|
12
|
+
end
|
13
|
+
|
14
|
+
# Executes specified @action_name instance method and returns Hash'ed response object
|
15
|
+
def dispatch
|
16
|
+
process(action_name)
|
17
|
+
|
18
|
+
@response.commit! unless performed?
|
19
|
+
|
20
|
+
@response.to_h
|
21
|
+
end
|
22
|
+
|
23
|
+
def process(action) = public_send(action)
|
24
|
+
|
25
|
+
private def performed? = @response.committed?
|
26
|
+
end
|
27
|
+
|
28
|
+
# The main base class for defining functions using the ActiveFunction framework.
|
29
|
+
# Public methods of this class are considered as actions and be proceeded on {ActiveFunction::Base.process} call.
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# class MyFunction < ActiveFunction::Base
|
33
|
+
# def index
|
34
|
+
# if user = User.find(@request.dig(:data, :user, :id))
|
35
|
+
# @response.body = user.to_h
|
36
|
+
# else
|
37
|
+
# @response.status = 404
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
class Base < SuperBase
|
42
|
+
Error = Class.new(StandardError)
|
43
|
+
|
44
|
+
# Processes specified action and returns Hash'ed {ActiveFunction::Functions::Response::Response} object.
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# MyFunction.process :index, { data: { user: { id: 1 } } } # => { statusCode: 200, body: { id: 1, name: "Pupa" }, headers: {} }
|
48
|
+
#
|
49
|
+
# @param [String, Symbol] action_name - name of method to call
|
50
|
+
# @param [Hash] request - request parameters.
|
51
|
+
# @param [Response] response - Functions::Response response object.
|
52
|
+
def self.process(action_name, request = {}, response = Response.new)
|
53
|
+
raise ArgumentError, "Action method #{action_name} is not defined" unless method_defined?(action_name)
|
54
|
+
|
55
|
+
new(action_name, request, response).dispatch
|
18
56
|
end
|
19
57
|
end
|
20
58
|
end
|
@@ -1,69 +1,69 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveFunction
|
4
|
-
class MissingCallbackContext < Error
|
5
|
-
MESSAGE_TEMPLATE = "Missing callback context: %s"
|
6
|
-
|
7
|
-
attr_reader :message
|
8
|
-
|
9
|
-
def initialize(context)
|
10
|
-
@message = MESSAGE_TEMPLATE % context
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
4
|
module Functions
|
5
|
+
# Setups {before_action} and {after_action} callbacks around {ActiveFunction::SuperBase#process}
|
6
|
+
# using {ActiveFunctionCore::Plugins::Hooks}. Also provides {define_hooks_for} and {set_callback_options} for
|
7
|
+
# defining custom hooks & options.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# ActiveFunction.plugin :callbacks
|
11
|
+
#
|
12
|
+
# class MessagingApp < ActiveFunction::Base
|
13
|
+
# set_callback_options retries: ->(times, context:) { context.retry if context.retries < times }
|
14
|
+
# define_hooks_for :retry
|
15
|
+
#
|
16
|
+
# after_action :retry, if: :failed?, only: %i[send_message], retries: 3
|
17
|
+
# after_retry :increment_retries
|
18
|
+
#
|
19
|
+
# def send_message
|
20
|
+
# @response.status = 200 if SomeApi.send(@request[:message_content]).success?
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def retry
|
24
|
+
# @response.committed = false
|
25
|
+
# process
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# private def increment_retries = @response.body[:tries] += 1
|
29
|
+
# private def failed? = @response.status != 200
|
30
|
+
# private def retries = @response.body[:tries] ||= 0
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# MessagingApp.process(:send_message, { sender_name: "Alice", message_content: "How are you?" })
|
34
|
+
# defining custom hooks & options.
|
15
35
|
module Callbacks
|
16
|
-
|
17
|
-
base.extend(ClassMethods)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def process(*)
|
23
|
-
_run_callbacks :before
|
24
|
-
|
25
|
-
super
|
26
|
-
|
27
|
-
_run_callbacks :after
|
28
|
-
end
|
29
|
-
|
30
|
-
def _run_callbacks(type)
|
31
|
-
self.class.callbacks[type].each do |callback_method, options|
|
32
|
-
raise MissingCallbackContext, callback_method unless respond_to?(callback_method, true)
|
33
|
-
|
34
|
-
send(callback_method) if _executable?(options)
|
35
|
-
end
|
36
|
-
end
|
36
|
+
ActiveFunction.register_plugin :callbacks, self
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
# Setup callbacks around {ActiveFunction::Base#process} method using {ActiveFunctionCore::Plugins::Hooks}.
|
39
|
+
# Also provides :only option for filtering callbacks by action name.
|
40
|
+
def self.included(base)
|
41
|
+
base.include ActiveFunctionCore::Plugins::Hooks
|
42
|
+
base.define_hooks_for :process, name: :action
|
43
|
+
base.set_callback_options only: ->(args, context:) { args.to_set === context.action_name }
|
42
44
|
end
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
end
|
46
|
+
# @!method before_action(target, options)
|
47
|
+
# @param [Symbol, String] target - method name to call
|
48
|
+
# @option options [Symbol, String] :if - method name to check before executing the callback.
|
49
|
+
# @option options [Symbol, String] :unless - method name to check before executing the callback.
|
50
|
+
# @option options [Array<Symbol, String>] :only - array of action names.
|
51
|
+
# @see ActiveFunctionCore::Plugins::Hooks::ClassMethods#set_callback
|
52
|
+
# @!method after_action(target, options)
|
53
|
+
# @param [Symbol, String] target - method name to call
|
54
|
+
# @option options [Symbol, String] :if - method name to check before executing the callback.
|
55
|
+
# @option options [Symbol, String] :unless - method name to check before executing the callback.
|
56
|
+
# @option options [Array<Symbol, String>] :only - array of action names.
|
57
|
+
# @see ActiveFunctionCore::Plugins::Hooks::ClassMethods#set_callback
|
58
|
+
|
59
|
+
# @!method set_callback(type, hook_name, target, options)
|
60
|
+
# @see ActiveFunctionCore::Plugins::Hooks::ClassMethods#set_callback
|
61
|
+
|
62
|
+
# @!method define_hooks_for(method_name, name: method_name)
|
63
|
+
# @see ActiveFunctionCore::Plugins::Hooks::ClassMethods#define_hooks_for
|
64
|
+
|
65
|
+
# @!method set_callback_options(options)
|
66
|
+
# @see ActiveFunctionCore::Plugins::Hooks::ClassMethods#set_callback_options
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -3,20 +3,47 @@
|
|
3
3
|
require "json"
|
4
4
|
|
5
5
|
module ActiveFunction
|
6
|
-
|
7
|
-
|
6
|
+
module Functions
|
7
|
+
# Allows manipulations with {ActiveFunction::SuperBase#response} via {render} instance method.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# require "active_function"
|
11
|
+
#
|
12
|
+
# ActiveFunction.config do
|
13
|
+
# plugin :rendering
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# class PostsFunction < ActiveFunction::Base
|
17
|
+
# def index
|
18
|
+
# render json: {id: 1, name: "Pupa"}, status: 200, head: {"Some-Header" => "Some-Value"}
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# PostFunction.process(:index) # => { :statusCode=>200, :headers=> {"Content-Type"=>"application/json", "Some-Header" => "Some-Value"}, :body=>"{\"id\":1,\"name\":\"Pupa\"}" }
|
23
|
+
module Rendering
|
24
|
+
ActiveFunction.register_plugin :rendering, self
|
8
25
|
|
9
|
-
|
26
|
+
Error = Class.new(StandardError)
|
10
27
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
28
|
+
class DoubleRenderError < Error
|
29
|
+
MESSAGE_TEMPLATE = "#render was called multiple times in action: %s"
|
30
|
+
|
31
|
+
attr_reader :message
|
32
|
+
|
33
|
+
def initialize(context)
|
34
|
+
@message = MESSAGE_TEMPLATE % context
|
35
|
+
end
|
36
|
+
end
|
15
37
|
|
16
|
-
module Functions
|
17
|
-
module Rendering
|
18
38
|
DEFAULT_HEADER = {"Content-Type" => "application/json"}.freeze
|
19
39
|
|
40
|
+
# Render JSON response.
|
41
|
+
#
|
42
|
+
# @param status [Integer] HTTP status code (default is 200).
|
43
|
+
# @param json [Hash] JSON data to be rendered (default is an empty hash).
|
44
|
+
# @param head [Hash] Additional headers to be included in the response (default is an empty hash).
|
45
|
+
#
|
46
|
+
# @raise [DoubleRenderError] Raised if #render is called multiple times in the same action.
|
20
47
|
def render(status: 200, json: {}, head: {})
|
21
48
|
raise DoubleRenderError, @action_name if performed?
|
22
49
|
|
@@ -2,29 +2,48 @@
|
|
2
2
|
|
3
3
|
module ActiveFunction
|
4
4
|
module Functions
|
5
|
-
|
6
|
-
|
5
|
+
# The only required plugin for {ActiveFunction::Base} to work.
|
6
|
+
# Provides a simple {Response} object to manage response details.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# response = Response.new.tap do |r|
|
10
|
+
# r.body = "Hello World!"
|
11
|
+
# r.headers = {"Content-Type" => "text/plain"}
|
12
|
+
# r.commit!
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# response.performed? # => true
|
16
|
+
# response.to_h # => { statusCode: 200, headers: { "Content-Type" => "text/plain" }, body: "Hello World!" }
|
17
|
+
module Response
|
18
|
+
ActiveFunction.register_plugin :response, self
|
7
19
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
@
|
13
|
-
|
20
|
+
class Response < Struct.new(:status, :headers, :body, :committed)
|
21
|
+
# Initializes a new Response instance with default values.
|
22
|
+
#
|
23
|
+
# @param status [Integer] HTTP status code.
|
24
|
+
# @param headers [Hash] HTTP headers.
|
25
|
+
# @param body [Object] Response body.
|
26
|
+
# @param committed [Boolean] Indicates whether the response has been committed (default is false).
|
27
|
+
def initialize(status: 200, headers: {}, body: nil, committed: false) = super(status, headers, body, committed)
|
14
28
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
29
|
+
# Converts the Response instance to a hash for JSON serialization.
|
30
|
+
#
|
31
|
+
# @return [Hash{statusCode: Integer, headers: Hash, body: Object}]
|
32
|
+
def to_h
|
33
|
+
{
|
34
|
+
statusCode: status,
|
35
|
+
headers:,
|
36
|
+
body:
|
37
|
+
}
|
38
|
+
end
|
22
39
|
|
23
|
-
|
24
|
-
|
25
|
-
|
40
|
+
# Marks the response as committed.
|
41
|
+
def commit!
|
42
|
+
self.committed = true
|
43
|
+
end
|
26
44
|
|
27
|
-
|
45
|
+
alias_method :committed?, :committed
|
46
|
+
end
|
28
47
|
end
|
29
48
|
end
|
30
49
|
end
|
@@ -3,54 +3,80 @@
|
|
3
3
|
require "forwardable"
|
4
4
|
|
5
5
|
module ActiveFunction
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
module Functions
|
7
|
+
# Allows manipulations with {ActiveFunction::SuperBase#request} via {params} instance method and {Parameters} object.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# require "active_function"
|
11
|
+
#
|
12
|
+
# ActiveFunction.config do
|
13
|
+
# plugin :strong_parameters
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# class PostsFunction < ActiveFunction::Base
|
17
|
+
# def index
|
18
|
+
# @response.body = permitted_params
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def permitted_params
|
22
|
+
# params.require(:data).permit(:id, :name).to_h
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# PostsFunction.process(:index, data: { id: 1, name: "Pupa" })
|
27
|
+
module StrongParameters
|
28
|
+
ActiveFunction.register_plugin :strong_parameters, self
|
15
29
|
|
16
|
-
|
17
|
-
|
30
|
+
Error = Class.new(StandardError)
|
31
|
+
# The Parameters class encapsulates the parameter handling logic.
|
32
|
+
class Parameters < Data.define(:params, :permitted)
|
33
|
+
class ParameterMissingError < Error
|
34
|
+
MESSAGE_TEMPLATE = "Missing parameter: %s"
|
18
35
|
|
19
|
-
|
36
|
+
attr_reader :message
|
20
37
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
38
|
+
def initialize(param)
|
39
|
+
MESSAGE_TEMPLATE % param
|
40
|
+
end
|
41
|
+
end
|
25
42
|
|
26
|
-
|
27
|
-
|
28
|
-
def params
|
29
|
-
@_params ||= Parameters.new(@request)
|
30
|
-
end
|
43
|
+
class UnpermittedParameterError < Error
|
44
|
+
MESSAGE_TEMPLATE = "Unpermitted parameter: %s"
|
31
45
|
|
32
|
-
|
33
|
-
extend Forwardable
|
34
|
-
def_delegators :@parameters, :each, :map
|
35
|
-
include Enumerable
|
46
|
+
attr_reader :message
|
36
47
|
|
37
|
-
|
38
|
-
|
39
|
-
|
48
|
+
def initialize(param)
|
49
|
+
MESSAGE_TEMPLATE % param
|
50
|
+
end
|
40
51
|
end
|
41
52
|
|
53
|
+
protected :params
|
54
|
+
|
55
|
+
# Allows access to parameters by key.
|
56
|
+
#
|
57
|
+
# @param attribute [Symbol] The key of the parameter.
|
58
|
+
# @return [Parameters, Object] The value of the parameter.
|
42
59
|
def [](attribute)
|
43
|
-
nested_attribute(
|
60
|
+
nested_attribute(params[attribute])
|
44
61
|
end
|
45
62
|
|
63
|
+
# Requires the presence of a specific parameter.
|
64
|
+
#
|
65
|
+
# @param attribute [Symbol] The key of the required parameter.
|
66
|
+
# @return [Parameters, Object] The value of the required parameter.
|
67
|
+
# @raise [ParameterMissingError] if the required parameter is missing.
|
46
68
|
def require(attribute)
|
47
|
-
value = self[attribute]
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
69
|
+
if (value = self[attribute])
|
70
|
+
value
|
71
|
+
else
|
72
|
+
raise ParameterMissingError, attribute
|
73
|
+
end
|
52
74
|
end
|
53
75
|
|
76
|
+
# Specifies the allowed parameters.
|
77
|
+
#
|
78
|
+
# @param attributes [Array<Symbol, Hash<Symbol, Array<Symbol>>>] The attributes to permit.
|
79
|
+
# @return [Parameters] A new instance with permitted parameters.
|
54
80
|
def permit(*attributes)
|
55
81
|
pparams = {}
|
56
82
|
|
@@ -60,28 +86,40 @@ module ActiveFunction
|
|
60
86
|
pparams[k] = process_nested(self[k], :permit, v)
|
61
87
|
end
|
62
88
|
else
|
63
|
-
next unless
|
89
|
+
next unless params.key?(attribute)
|
64
90
|
|
65
91
|
pparams[attribute] = self[attribute]
|
66
92
|
end
|
67
93
|
end
|
68
94
|
|
69
|
-
|
95
|
+
with(params: pparams, permitted: true)
|
70
96
|
end
|
71
97
|
|
98
|
+
# Converts parameters to a hash.
|
99
|
+
#
|
100
|
+
# @return [Hash] The hash representation of the parameters.
|
101
|
+
# @raise [UnpermittedParameterError] if any parameters are unpermitted.
|
72
102
|
def to_h
|
73
|
-
raise UnpermittedParameterError,
|
103
|
+
raise UnpermittedParameterError, params.keys unless permitted
|
74
104
|
|
75
|
-
|
105
|
+
params.transform_values { process_nested(_1, :to_h) }
|
106
|
+
end
|
107
|
+
|
108
|
+
def hash
|
109
|
+
@attributes.to_h.hash
|
110
|
+
end
|
111
|
+
|
112
|
+
def with(params:, permitted: false)
|
113
|
+
self.class.new(params, permitted)
|
76
114
|
end
|
77
115
|
|
78
116
|
private
|
79
117
|
|
80
118
|
def nested_attribute(attribute)
|
81
119
|
if attribute.is_a? Hash
|
82
|
-
|
120
|
+
with(params: attribute)
|
83
121
|
elsif attribute.is_a?(Array) && attribute[0].is_a?(Hash)
|
84
|
-
attribute.map {
|
122
|
+
attribute.map { |it| with(params: it) }
|
85
123
|
else
|
86
124
|
attribute
|
87
125
|
end
|
@@ -96,8 +134,13 @@ module ActiveFunction
|
|
96
134
|
attribute
|
97
135
|
end
|
98
136
|
end
|
137
|
+
end
|
99
138
|
|
100
|
-
|
139
|
+
# Return params object with {ActiveFunction::SuperBase#request}.
|
140
|
+
#
|
141
|
+
# @return [Parameters] instance of {Parameters} class.
|
142
|
+
def params
|
143
|
+
@_params ||= Parameters.new(@request, false)
|
101
144
|
end
|
102
145
|
end
|
103
146
|
end
|