representable 2.3.0 → 2.4.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +47 -0
- data/Gemfile +5 -0
- data/README.md +33 -0
- data/lib/representable.rb +60 -73
- data/lib/representable/binding.rb +37 -194
- data/lib/representable/cached.rb +10 -46
- data/lib/representable/coercion.rb +8 -8
- data/lib/representable/config.rb +15 -75
- data/lib/representable/debug.rb +41 -59
- data/lib/representable/declarative.rb +34 -53
- data/lib/representable/decorator.rb +11 -40
- data/lib/representable/definition.rb +14 -15
- data/lib/representable/deprecations.rb +90 -0
- data/lib/representable/deserializer.rb +87 -82
- data/lib/representable/for_collection.rb +5 -3
- data/lib/representable/hash.rb +5 -3
- data/lib/representable/hash/binding.rb +6 -15
- data/lib/representable/hash/collection.rb +10 -6
- data/lib/representable/hash_methods.rb +5 -5
- data/lib/representable/insert.rb +31 -0
- data/lib/representable/json.rb +7 -3
- data/lib/representable/json/hash.rb +1 -1
- data/lib/representable/object/binding.rb +5 -5
- data/lib/representable/parse_strategies.rb +37 -3
- data/lib/representable/pipeline.rb +37 -5
- data/lib/representable/pipeline_factories.rb +88 -0
- data/lib/representable/serializer.rb +38 -44
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml.rb +4 -0
- data/lib/representable/xml/binding.rb +25 -31
- data/lib/representable/xml/collection.rb +5 -3
- data/lib/representable/xml/hash.rb +7 -2
- data/lib/representable/yaml.rb +6 -3
- data/lib/representable/yaml/binding.rb +4 -4
- data/representable.gemspec +3 -3
- data/test/---deserialize-pipeline_test.rb +37 -0
- data/test/binding_test.rb +7 -7
- data/test/cached_test.rb +31 -19
- data/test/coercion_test.rb +2 -2
- data/test/config/inherit_test.rb +13 -12
- data/test/config_test.rb +12 -67
- data/test/decorator_test.rb +4 -5
- data/test/default_test.rb +34 -0
- data/test/defaults_options_test.rb +93 -0
- data/test/definition_test.rb +19 -39
- data/test/exec_context_test.rb +1 -1
- data/test/filter_test.rb +18 -20
- data/test/getter_setter_test.rb +1 -8
- data/test/hash_bindings_test.rb +13 -13
- data/test/heritage_test.rb +62 -0
- data/test/if_test.rb +1 -0
- data/test/inherit_test.rb +5 -3
- data/test/instance_test.rb +3 -4
- data/test/json_test.rb +3 -59
- data/test/lonely_test.rb +47 -3
- data/test/nested_test.rb +8 -2
- data/test/pipeline_test.rb +259 -0
- data/test/populator_test.rb +76 -0
- data/test/realistic_benchmark.rb +39 -7
- data/test/render_nil_test.rb +21 -0
- data/test/represent_test.rb +2 -2
- data/test/representable_test.rb +33 -103
- data/test/schema_test.rb +5 -15
- data/test/serialize_deserialize_test.rb +2 -2
- data/test/skip_test.rb +1 -1
- data/test/test_helper.rb +6 -0
- data/test/uncategorized_test.rb +67 -0
- data/test/xml_bindings_test.rb +6 -6
- data/test/xml_test.rb +6 -6
- metadata +33 -13
- data/lib/representable/apply.rb +0 -13
- data/lib/representable/inheritable.rb +0 -71
- data/lib/representable/mapper.rb +0 -83
- data/lib/representable/populator.rb +0 -56
- data/test/inheritable_test.rb +0 -97
data/lib/representable/hash.rb
CHANGED
@@ -14,14 +14,16 @@ module Representable
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
17
|
module ClassMethods
|
18
|
+
def format_engine
|
19
|
+
Representable::Hash
|
20
|
+
end
|
21
|
+
|
19
22
|
def collection_representer_class
|
20
23
|
Collection
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
24
|
-
|
25
27
|
def from_hash(data, options={}, binding_builder=Binding)
|
26
28
|
data = filter_wrap(data, options)
|
27
29
|
|
@@ -31,7 +33,7 @@ module Representable
|
|
31
33
|
def to_hash(options={}, binding_builder=Binding)
|
32
34
|
hash = create_representation_with({}, options, binding_builder)
|
33
35
|
|
34
|
-
return hash if options[:wrap] == false
|
36
|
+
return hash if options[:wrap] == false
|
35
37
|
return hash unless wrap = options[:wrap] || representation_wrap(options)
|
36
38
|
|
37
39
|
{wrap => hash}
|
@@ -3,20 +3,16 @@ require 'representable/binding'
|
|
3
3
|
module Representable
|
4
4
|
module Hash
|
5
5
|
class Binding < Representable::Binding
|
6
|
-
def self.build_for(definition
|
7
|
-
|
8
|
-
|
9
|
-
return Hash.new(definition, *args) if definition.hash?
|
10
|
-
new(definition, *args)
|
6
|
+
def self.build_for(definition)
|
7
|
+
return Collection.new(definition) if definition.array?
|
8
|
+
new(definition)
|
11
9
|
end
|
12
10
|
|
13
|
-
def read(hash)
|
14
|
-
|
15
|
-
|
16
|
-
hash[as] # fragment
|
11
|
+
def read(hash, as)
|
12
|
+
hash.has_key?(as) ? hash[as] : FragmentNotFound
|
17
13
|
end
|
18
14
|
|
19
|
-
def write(hash, fragment)
|
15
|
+
def write(hash, fragment, as)
|
20
16
|
hash[as] = fragment
|
21
17
|
end
|
22
18
|
|
@@ -31,11 +27,6 @@ module Representable
|
|
31
27
|
class Collection < self
|
32
28
|
include Representable::Binding::Collection
|
33
29
|
end
|
34
|
-
|
35
|
-
|
36
|
-
class Hash < self
|
37
|
-
include Representable::Binding::Hash
|
38
|
-
end
|
39
30
|
end
|
40
31
|
end
|
41
32
|
end
|
@@ -6,7 +6,7 @@ module Representable::Hash
|
|
6
6
|
base.class_eval do
|
7
7
|
include Representable::Hash
|
8
8
|
extend ClassMethods
|
9
|
-
|
9
|
+
property(:_self, {:collection => true})
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -19,14 +19,18 @@ module Representable::Hash
|
|
19
19
|
|
20
20
|
|
21
21
|
def create_representation_with(doc, options, format)
|
22
|
-
bin =
|
23
|
-
|
22
|
+
bin = representable_bindings_for(format, options).first
|
23
|
+
|
24
|
+
Collect[*bin.default_render_fragment_functions].
|
25
|
+
(represented, {doc: doc, fragment: represented, user_options: options, binding: bin, represented: represented})
|
24
26
|
end
|
25
27
|
|
26
28
|
def update_properties_from(doc, options, format)
|
27
|
-
bin =
|
28
|
-
|
29
|
-
value =
|
29
|
+
bin = representable_bindings_for(format, options).first
|
30
|
+
|
31
|
+
value = Collect[*bin.default_parse_fragment_functions].
|
32
|
+
(doc, fragment: doc, document: doc, user_options: options, binding: bin, represented: represented)
|
33
|
+
|
30
34
|
represented.replace(value)
|
31
35
|
end
|
32
36
|
end
|
@@ -2,17 +2,17 @@ module Representable
|
|
2
2
|
module HashMethods
|
3
3
|
def create_representation_with(doc, options, format)
|
4
4
|
hash = filter_keys_for!(represented, options) # FIXME: this modifies options and replicates logic from Representable.
|
5
|
-
bin =
|
5
|
+
bin = representable_map(options, format).first
|
6
6
|
|
7
|
-
bin.
|
7
|
+
Collect::Hash[*bin.default_render_fragment_functions].extend(Pipeline::Debug).(hash, {doc: doc, user_options: options, binding: bin, represented: represented, decorator: self})
|
8
8
|
end
|
9
9
|
|
10
10
|
def update_properties_from(doc, options, format)
|
11
11
|
hash = filter_keys_for!(doc, options)
|
12
|
-
bin =
|
12
|
+
bin = representable_map(options, format).first
|
13
|
+
|
14
|
+
value = Collect::Hash[*bin.default_parse_fragment_functions].(hash, fragment: hash, document: doc, binding: bin, represented: represented, user_options: options, decorator: self)
|
13
15
|
|
14
|
-
value = Deserializer::Hash.new(bin).call(hash)
|
15
|
-
# value = bin.deserialize_from(hash)
|
16
16
|
represented.replace(value)
|
17
17
|
end
|
18
18
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Representable
|
2
|
+
Pipeline.class_eval do # FIXME: this doesn't define Function in Pipeline.
|
3
|
+
module Function
|
4
|
+
class Insert
|
5
|
+
def call(arr, func, options)
|
6
|
+
arr = arr.dup
|
7
|
+
delete!(arr, func) if options[:delete]
|
8
|
+
replace!(arr, options[:replace], func) if options[:replace]
|
9
|
+
arr
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def replace!(arr, old_func, new_func)
|
14
|
+
arr.each_with_index { |func, index|
|
15
|
+
if func.is_a?(Collect)
|
16
|
+
arr[index] = Collect[*Pipeline::Insert.(func, new_func, replace: old_func)]
|
17
|
+
end
|
18
|
+
|
19
|
+
arr[index] = new_func if old_func.is_a?(Proc)? (func==old_func) : old_func.instance_of?(func.class)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete!(arr, func)
|
24
|
+
arr.delete(func)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Pipeline::Insert = Function::Insert.new
|
31
|
+
end
|
data/lib/representable/json.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "representable/hash"
|
2
|
+
require "representable/json/collection"
|
3
3
|
|
4
4
|
begin
|
5
|
-
require
|
5
|
+
require "multi_json"
|
6
6
|
rescue LoadError => _
|
7
7
|
abort "Missing dependency 'multi_json' for Representable::JSON. See dependencies section in README.md for details."
|
8
8
|
end
|
@@ -23,6 +23,10 @@ module Representable
|
|
23
23
|
|
24
24
|
|
25
25
|
module ClassMethods
|
26
|
+
def format_engine
|
27
|
+
Representable::Hash
|
28
|
+
end
|
29
|
+
|
26
30
|
def collection_representer_class
|
27
31
|
JSON::Collection
|
28
32
|
end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
module Representable
|
2
2
|
module Object
|
3
3
|
class Binding < Representable::Binding
|
4
|
-
def self.build_for(definition
|
5
|
-
return Collection.new(definition
|
6
|
-
new(definition
|
4
|
+
def self.build_for(definition) # TODO: remove default arg.
|
5
|
+
return Collection.new(definition) if definition.array?
|
6
|
+
new(definition)
|
7
7
|
end
|
8
8
|
|
9
|
-
def read(hash)
|
9
|
+
def read(hash, as)
|
10
10
|
fragment = hash.send(as) # :getter? no, that's for parsing!
|
11
11
|
|
12
12
|
return FragmentNotFound if fragment.nil? and typed?
|
13
13
|
fragment
|
14
14
|
end
|
15
15
|
|
16
|
-
def write(hash, fragment)
|
16
|
+
def write(hash, fragment, as)
|
17
17
|
true
|
18
18
|
end
|
19
19
|
|
@@ -1,4 +1,36 @@
|
|
1
1
|
module Representable
|
2
|
+
class Populator
|
3
|
+
FindOrInstantiate = ->(input, options) {
|
4
|
+
AssignFragment.(input, options)
|
5
|
+
|
6
|
+
binding = options[:binding]
|
7
|
+
|
8
|
+
object_class = binding[:class].(input, options)
|
9
|
+
object = object_class.find_by(id: input["id"]) || object_class.new
|
10
|
+
if options[:binding].array?
|
11
|
+
# represented.songs[i] = model
|
12
|
+
options[:represented].send(binding.getter)[options[:index]] = object
|
13
|
+
else
|
14
|
+
# represented.song = model
|
15
|
+
options[:represented].send(binding.setter, object)
|
16
|
+
end
|
17
|
+
|
18
|
+
object
|
19
|
+
}
|
20
|
+
|
21
|
+
def self.apply!(options)
|
22
|
+
return unless populator = options[:populator]
|
23
|
+
|
24
|
+
options[:parse_pipeline] = ->(input, options) do
|
25
|
+
pipeline = Pipeline[*parse_functions] # TODO: AssignFragment
|
26
|
+
pipeline = Pipeline::Insert.(pipeline, Set, delete: true) # remove the setter function.
|
27
|
+
pipeline = Pipeline::Insert.(pipeline, populator, replace: CreateObject) # let the populator do CreateObject's job.
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
FindOrInstantiate = Populator::FindOrInstantiate
|
33
|
+
|
2
34
|
# Parse strategies are just a combination of representable's options. They save you from memoizing the
|
3
35
|
# necessary parameters.
|
4
36
|
#
|
@@ -7,6 +39,8 @@ module Representable
|
|
7
39
|
def self.apply!(options)
|
8
40
|
return unless strategy = options[:parse_strategy]
|
9
41
|
|
42
|
+
warn "[Representable] :parse_strategy is deprecated. Please use a populator."
|
43
|
+
|
10
44
|
strategy = :proc if strategy.is_a?(::Proc)
|
11
45
|
|
12
46
|
parse_strategies[strategy].apply!(name, options)
|
@@ -33,11 +67,11 @@ module Representable
|
|
33
67
|
|
34
68
|
class Sync
|
35
69
|
def self.apply!(name, options)
|
36
|
-
options[:setter] = lambda {
|
70
|
+
options[:setter] = lambda { |*args| }
|
37
71
|
options[:pass_options] = true
|
38
72
|
options[:instance] = options[:collection] ?
|
39
|
-
lambda { |fragment, i, options| options.binding.get[i] } :
|
40
|
-
lambda { |fragment, options| options.binding.get }
|
73
|
+
lambda { |fragment, i, options| options.binding.get(represented: options.represented)[i] } :
|
74
|
+
lambda { |fragment, options| options.binding.get(represented: options.represented) }
|
41
75
|
end
|
42
76
|
end
|
43
77
|
|
@@ -1,14 +1,46 @@
|
|
1
1
|
module Representable
|
2
2
|
# Allows to implement a pipeline of filters where a value gets passed in and the result gets
|
3
3
|
# passed to the next callable object.
|
4
|
-
#
|
5
|
-
# Note: this is still experimental.
|
6
4
|
class Pipeline < Array
|
7
5
|
include Uber::Callable
|
8
|
-
# include Representable::Cloneable
|
9
6
|
|
10
|
-
|
11
|
-
|
7
|
+
Stop = Class.new
|
8
|
+
|
9
|
+
# options is mutuable.
|
10
|
+
def call(input, options)
|
11
|
+
inject(input) do |memo, block|
|
12
|
+
res = evaluate(block, memo, options)
|
13
|
+
return(Stop)if Stop == res
|
14
|
+
res
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def evaluate(block, input, options)
|
20
|
+
block.call(input, options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Collect applies a pipeline to each element of input.
|
26
|
+
class Collect < Pipeline
|
27
|
+
# when stop, the element is skipped. (should that be Skip then?)
|
28
|
+
def call(input, options)
|
29
|
+
arr = []
|
30
|
+
input.each_with_index do |item_fragment, i|
|
31
|
+
result = super(item_fragment, options.merge(index: i)) # DISCUSS: NO :fragment set.
|
32
|
+
Pipeline::Stop == result ? next : arr << result
|
33
|
+
end
|
34
|
+
arr
|
35
|
+
end
|
36
|
+
|
37
|
+
class Hash < Pipeline
|
38
|
+
def call(input, options)
|
39
|
+
{}.tap do |hsh|
|
40
|
+
input.each { |key, item_fragment|
|
41
|
+
hsh[key] = super(item_fragment, options) }# DISCUSS: NO :fragment set.
|
42
|
+
end
|
43
|
+
end
|
12
44
|
end
|
13
45
|
end
|
14
46
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# NOTE: this might become a separate class, that's why it's in a separate file.
|
2
|
+
module Representable
|
3
|
+
module Binding::Factories
|
4
|
+
def pipeline_for(name, input, options)
|
5
|
+
return yield unless proc = @definition[name]
|
6
|
+
# proc.(self, options)
|
7
|
+
instance_exec(input, options, &proc)
|
8
|
+
end
|
9
|
+
|
10
|
+
# i decided not to use polymorphism here for the sake of clarity.
|
11
|
+
def collect_for(item_functions)
|
12
|
+
return [Collect[*item_functions]] if array?
|
13
|
+
return [Collect::Hash[*item_functions]] if self[:hash]
|
14
|
+
item_functions
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_functions
|
18
|
+
[*default_parse_init_functions, *collect_for(default_parse_fragment_functions), *default_post_functions]
|
19
|
+
end
|
20
|
+
|
21
|
+
# DISCUSS: StopOnNil, before collect
|
22
|
+
def render_functions
|
23
|
+
[*default_render_init_functions, *collect_for(default_render_fragment_functions), WriteFragment]
|
24
|
+
end
|
25
|
+
|
26
|
+
def default_render_fragment_functions
|
27
|
+
functions = []
|
28
|
+
functions << SkipRender if self[:skip_render]
|
29
|
+
if typed? # TODO: allow prepare regardless of :extend, which makes it independent of typed?
|
30
|
+
if self[:prepare]
|
31
|
+
functions << Prepare
|
32
|
+
end
|
33
|
+
# functions << (self[:prepare] ? Prepare : Decorate)
|
34
|
+
end
|
35
|
+
functions << Decorate if self[:extend] and !self[:prepare]
|
36
|
+
if representable?
|
37
|
+
functions << (self[:serialize] ? Serializer : Serialize)
|
38
|
+
end
|
39
|
+
functions
|
40
|
+
end
|
41
|
+
|
42
|
+
def default_render_init_functions
|
43
|
+
functions = []
|
44
|
+
functions << Stop if self[:readable]==false
|
45
|
+
functions << StopOnExcluded
|
46
|
+
functions << If if self[:if]
|
47
|
+
functions << (self[:getter] ? Getter : Get)
|
48
|
+
functions << Writer if self[:writer]
|
49
|
+
functions << RenderFilter if self[:render_filter].any?
|
50
|
+
functions << RenderDefault if has_default?
|
51
|
+
functions << StopOnSkipable
|
52
|
+
functions << (self[:as] ? AssignAs : AssignName)
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_parse_init_functions
|
56
|
+
functions = []
|
57
|
+
functions << Stop if self[:writeable]==false
|
58
|
+
functions << StopOnExcluded
|
59
|
+
functions << If if self[:if]
|
60
|
+
functions << (self[:as] ? AssignAs : AssignName)
|
61
|
+
functions << (self[:reader] ? Reader : ReadFragment)
|
62
|
+
functions << (has_default? ? Default : StopOnNotFound)
|
63
|
+
functions << OverwriteOnNil # include StopOnNil if you don't want to erase things.
|
64
|
+
end
|
65
|
+
|
66
|
+
def default_parse_fragment_functions
|
67
|
+
functions = []
|
68
|
+
functions << SkipParse if self[:skip_parse]
|
69
|
+
|
70
|
+
if typed?
|
71
|
+
functions << CreateObject
|
72
|
+
functions << Prepare if self[:prepare]
|
73
|
+
functions << Decorate if self[:extend]
|
74
|
+
if representable?
|
75
|
+
functions << (self[:deserialize] ? Deserializer : Deserialize)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
functions
|
80
|
+
end
|
81
|
+
|
82
|
+
def default_post_functions
|
83
|
+
funcs = []
|
84
|
+
funcs << ParseFilter if self[:parse_filter].any?
|
85
|
+
funcs << (self[:setter] ? Setter : Set)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -1,60 +1,54 @@
|
|
1
|
-
require "representable/deserializer"
|
2
|
-
|
3
1
|
module Representable
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
return object if object.nil? # DISCUSS: move to Object#serialize ?
|
2
|
+
Getter = ->(input, options) do
|
3
|
+
options[:binding].evaluate_option(:getter, input, options)
|
4
|
+
end
|
8
5
|
|
9
|
-
|
10
|
-
end
|
6
|
+
Get = ->(input, options) { options[:binding].send(:exec_context, options).send(options[:binding].getter) }
|
11
7
|
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
Writer = ->(input, options) do
|
9
|
+
options[:binding].evaluate_option(:writer, input, options)
|
10
|
+
Pipeline::Stop
|
11
|
+
end
|
15
12
|
|
16
|
-
|
17
|
-
|
13
|
+
# TODO: evaluate this, if we need this.
|
14
|
+
RenderDefault = ->(input, options) do
|
15
|
+
binding = options[:binding]
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
object = prepare(object)
|
17
|
+
binding.skipable_empty_value?(input) ? binding[:default] : input
|
18
|
+
end
|
22
19
|
|
23
|
-
|
20
|
+
StopOnSkipable = ->(input, options) do
|
21
|
+
options[:binding].send(:skipable_empty_value?, input) ? Pipeline::Stop : input
|
22
|
+
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
24
|
+
RenderFilter = ->(input, options) do
|
25
|
+
options[:binding][:render_filter].(input, options)
|
26
|
+
end
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
object.send(@binding.serialize_method, user_options)
|
34
|
-
end
|
28
|
+
SkipRender = ->(input, options) do
|
29
|
+
options[:binding].evaluate_option(:skip_render, input, options) ? Pipeline::Stop : input
|
30
|
+
end
|
35
31
|
|
32
|
+
Serializer = ->(input, options) do
|
33
|
+
return if input.nil? # DISCUSS: how can we prevent that?
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
collection = [] # TODO: unify with Deserializer::Collection.
|
35
|
+
options[:binding].evaluate_option(:serialize, input, options)
|
36
|
+
end
|
40
37
|
|
41
|
-
|
42
|
-
|
38
|
+
Serialize = ->(input, options) do
|
39
|
+
return if input.nil? # DISCUSS: how can we prevent that?
|
40
|
+
binding, user_options = options[:binding], options[:user_options]
|
43
41
|
|
44
|
-
|
45
|
-
end # TODO: i don't want Array but Forms here - what now?
|
42
|
+
user_options = user_options.merge(wrap: binding[:wrap]) unless binding[:wrap].nil? # DISCUSS: can we leave that here?
|
46
43
|
|
47
|
-
|
48
|
-
|
49
|
-
end
|
44
|
+
input.send(binding.serialize_method, user_options)
|
45
|
+
end
|
50
46
|
|
47
|
+
WriteFragment = ->(input, options) { options[:binding].write(options[:doc], input, options[:as]) }
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
49
|
+
As = ->(input, options) { options[:binding].evaluate_option(:as, input, options) }
|
50
|
+
|
51
|
+
# Warning: don't rely on AssignAs/AssignName, i am not sure if i leave that as functions.
|
52
|
+
AssignAs = ->(input, options) { options[:as] = As.(input, options); input }
|
53
|
+
AssignName = ->(input, options) { options[:as] = options[:binding].name; input }
|
60
54
|
end
|