representable 2.3.0 → 2.4.0.rc1
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/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/xml.rb
CHANGED
@@ -4,34 +4,34 @@ require 'representable/hash/binding.rb'
|
|
4
4
|
module Representable
|
5
5
|
module XML
|
6
6
|
class Binding < Representable::Binding
|
7
|
-
def self.build_for(definition
|
8
|
-
return Collection.new(definition
|
9
|
-
return Hash.new(definition
|
10
|
-
return AttributeHash.new(definition
|
11
|
-
return Attribute.new(definition
|
12
|
-
return Content.new(definition
|
13
|
-
new(definition
|
7
|
+
def self.build_for(definition)
|
8
|
+
return Collection.new(definition) if definition.array?
|
9
|
+
return Hash.new(definition) if definition.hash? and not definition[:use_attributes] # FIXME: hate this.
|
10
|
+
return AttributeHash.new(definition) if definition.hash? and definition[:use_attributes]
|
11
|
+
return Attribute.new(definition) if definition[:attribute]
|
12
|
+
return Content.new(definition) if definition[:content]
|
13
|
+
new(definition)
|
14
14
|
end
|
15
15
|
|
16
|
-
def write(parent, fragments)
|
16
|
+
def write(parent, fragments, as)
|
17
17
|
wrap_node = parent
|
18
18
|
|
19
19
|
if wrap = self[:wrap]
|
20
20
|
parent << wrap_node = node_for(parent, wrap)
|
21
21
|
end
|
22
22
|
|
23
|
-
wrap_node << serialize_for(fragments, parent)
|
23
|
+
wrap_node << serialize_for(fragments, parent, as)
|
24
24
|
end
|
25
25
|
|
26
|
-
def read(node)
|
27
|
-
nodes = find_nodes(node)
|
26
|
+
def read(node, as)
|
27
|
+
nodes = find_nodes(node, as)
|
28
28
|
return FragmentNotFound if nodes.size == 0 # TODO: write dedicated test!
|
29
29
|
|
30
30
|
deserialize_from(nodes)
|
31
31
|
end
|
32
32
|
|
33
33
|
# Creates wrapped node for the property.
|
34
|
-
def serialize_for(value, parent)
|
34
|
+
def serialize_for(value, parent, as)
|
35
35
|
node = node_for(parent, as)
|
36
36
|
serialize_node(node, value)
|
37
37
|
end
|
@@ -57,13 +57,9 @@ module Representable
|
|
57
57
|
end
|
58
58
|
|
59
59
|
private
|
60
|
-
def
|
61
|
-
as
|
62
|
-
|
63
|
-
|
64
|
-
def find_nodes(doc)
|
65
|
-
selector = xpath
|
66
|
-
selector = "#{self[:wrap]}/#{xpath}" if self[:wrap]
|
60
|
+
def find_nodes(doc, as)
|
61
|
+
selector = as
|
62
|
+
selector = "#{self[:wrap]}/#{as}" if self[:wrap]
|
67
63
|
nodes = doc.xpath(selector)
|
68
64
|
end
|
69
65
|
|
@@ -81,9 +77,9 @@ module Representable
|
|
81
77
|
class Collection < self
|
82
78
|
include Representable::Binding::Collection
|
83
79
|
|
84
|
-
def serialize_for(value, parent)
|
80
|
+
def serialize_for(value, parent, as)
|
85
81
|
# return NodeSet so << works.
|
86
|
-
set_for(parent, value.collect { |item| super(item, parent) })
|
82
|
+
set_for(parent, value.collect { |item| super(item, parent, as) })
|
87
83
|
end
|
88
84
|
|
89
85
|
def deserialize_from(nodes)
|
@@ -102,9 +98,7 @@ module Representable
|
|
102
98
|
|
103
99
|
|
104
100
|
class Hash < Collection
|
105
|
-
|
106
|
-
|
107
|
-
def serialize_for(value, parent)
|
101
|
+
def serialize_for(value, parent, as)
|
108
102
|
set_for(parent, value.collect do |k, v|
|
109
103
|
node = node_for(parent, k)
|
110
104
|
serialize_node(node, v)
|
@@ -123,7 +117,7 @@ module Representable
|
|
123
117
|
|
124
118
|
class AttributeHash < Collection
|
125
119
|
# DISCUSS: use AttributeBinding here?
|
126
|
-
def write(parent, value) # DISCUSS: is it correct overriding #write here?
|
120
|
+
def write(parent, value, as) # DISCUSS: is it correct overriding #write here?
|
127
121
|
value.collect do |k, v|
|
128
122
|
parent[k] = v.to_s
|
129
123
|
end
|
@@ -139,22 +133,22 @@ module Representable
|
|
139
133
|
|
140
134
|
# Represents a tag attribute. Currently this only works on the top-level tag.
|
141
135
|
class Attribute < self
|
142
|
-
def read(node)
|
136
|
+
def read(node, as)
|
143
137
|
node[as]
|
144
138
|
end
|
145
139
|
|
146
|
-
def serialize_for(value, parent)
|
140
|
+
def serialize_for(value, parent, as)
|
147
141
|
parent[as] = value.to_s
|
148
142
|
end
|
149
143
|
|
150
|
-
def write(parent, value)
|
151
|
-
serialize_for(value, parent)
|
144
|
+
def write(parent, value, as)
|
145
|
+
serialize_for(value, parent, as)
|
152
146
|
end
|
153
147
|
end
|
154
148
|
|
155
149
|
# Represents tag content.
|
156
150
|
class Content < self
|
157
|
-
def read(node)
|
151
|
+
def read(node, as)
|
158
152
|
node.content
|
159
153
|
end
|
160
154
|
|
@@ -162,7 +156,7 @@ module Representable
|
|
162
156
|
parent.content = value.to_s
|
163
157
|
end
|
164
158
|
|
165
|
-
def write(parent, value)
|
159
|
+
def write(parent, value, as)
|
166
160
|
serialize_for(value, parent)
|
167
161
|
end
|
168
162
|
end
|
@@ -1,15 +1,17 @@
|
|
1
1
|
module Representable::XML
|
2
2
|
module Collection
|
3
|
-
include Representable::XML
|
4
|
-
|
5
3
|
def self.included(base)
|
6
4
|
base.send :include, Representable::XML
|
7
5
|
base.send :include, Representable::Hash::Collection
|
8
6
|
base.send :include, Methods
|
9
7
|
end
|
10
8
|
|
11
|
-
|
12
9
|
module Methods
|
10
|
+
def create_representation_with(doc, options, format)
|
11
|
+
bin = representable_map(options, format).first
|
12
|
+
bin.write(doc, super, bin.name)
|
13
|
+
end
|
14
|
+
|
13
15
|
def update_properties_from(doc, *args)
|
14
16
|
super(doc.search("./*"), *args) # pass the list of collection items to Hash::Collection#update_properties_from.
|
15
17
|
end
|
@@ -10,7 +10,7 @@ module Representable::XML
|
|
10
10
|
base.class_eval do
|
11
11
|
include Representable
|
12
12
|
extend ClassMethods
|
13
|
-
|
13
|
+
property(:_self, hash: true, use_attributes: true)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -20,6 +20,11 @@ module Representable::XML
|
|
20
20
|
hash :_self, options.merge!(:use_attributes => true)
|
21
21
|
end
|
22
22
|
end
|
23
|
+
|
24
|
+
def create_representation_with(doc, options, format)
|
25
|
+
bin = representable_bindings_for(format, options).first
|
26
|
+
bin.write(doc, super, options)
|
27
|
+
end
|
23
28
|
end
|
24
29
|
|
25
30
|
module Hash
|
@@ -30,7 +35,7 @@ module Representable::XML
|
|
30
35
|
base.class_eval do
|
31
36
|
include Representable
|
32
37
|
extend ClassMethods
|
33
|
-
|
38
|
+
property(:_self, {:hash => true})
|
34
39
|
end
|
35
40
|
end
|
36
41
|
|
data/lib/representable/yaml.rb
CHANGED
@@ -8,11 +8,16 @@ module Representable
|
|
8
8
|
def self.included(base)
|
9
9
|
base.class_eval do
|
10
10
|
include Representable
|
11
|
-
#self.representation_wrap = true # let representable compute it.
|
12
11
|
register_feature Representable::YAML
|
12
|
+
extend ClassMethods
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
module ClassMethods
|
17
|
+
def format_engine
|
18
|
+
Representable::YAML
|
19
|
+
end
|
20
|
+
end
|
16
21
|
|
17
22
|
def from_yaml(doc, options={})
|
18
23
|
hash = Psych.load(doc)
|
@@ -21,8 +26,6 @@ module Representable
|
|
21
26
|
|
22
27
|
# Returns a Nokogiri::XML object representing this object.
|
23
28
|
def to_ast(options={})
|
24
|
-
#root_tag = options[:wrap] || representation_wrap
|
25
|
-
|
26
29
|
Psych::Nodes::Mapping.new.tap do |map|
|
27
30
|
create_representation_with(map, options, Binding)
|
28
31
|
end
|
@@ -3,12 +3,12 @@ require 'representable/hash/binding'
|
|
3
3
|
module Representable
|
4
4
|
module YAML
|
5
5
|
class Binding < Representable::Hash::Binding
|
6
|
-
def self.build_for(definition
|
7
|
-
return Collection.new(definition
|
8
|
-
new(definition
|
6
|
+
def self.build_for(definition)
|
7
|
+
return Collection.new(definition) if definition.array?
|
8
|
+
new(definition)
|
9
9
|
end
|
10
10
|
|
11
|
-
def write(map, fragment)
|
11
|
+
def write(map, fragment, as)
|
12
12
|
map.children << Psych::Nodes::Scalar.new(as)
|
13
13
|
map.children << node_for(fragment) # FIXME: should be serialize.
|
14
14
|
end
|
data/representable.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
lib = File.expand_path('../lib/', __FILE__)
|
3
2
|
$:.unshift lib unless $:.include?(lib)
|
4
3
|
|
@@ -20,11 +19,12 @@ Gem::Specification.new do |s|
|
|
20
19
|
s.require_paths = ["lib"]
|
21
20
|
s.license = "MIT"
|
22
21
|
|
23
|
-
s.add_dependency "uber", "~> 0.0.
|
22
|
+
s.add_dependency "uber", "~> 0.0.15"
|
23
|
+
s.add_dependency "declarative", "~> 0.0.4"
|
24
24
|
|
25
25
|
s.add_development_dependency "rake"
|
26
26
|
s.add_development_dependency "test_xml", "0.1.6"
|
27
|
-
s.add_development_dependency "minitest"
|
27
|
+
s.add_development_dependency "minitest"
|
28
28
|
s.add_development_dependency "mongoid"
|
29
29
|
s.add_development_dependency "virtus"
|
30
30
|
s.add_development_dependency "json", '>= 1.7.7'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class DeserializePipelineTest < MiniTest::Spec
|
4
|
+
Album = Struct.new(:artist, :songs)
|
5
|
+
Artist = Struct.new(:email)
|
6
|
+
Song = Struct.new(:title)
|
7
|
+
|
8
|
+
# tests [Collect[Instance, Prepare, Deserialize], Setter]
|
9
|
+
class Representer < Representable::Decorator
|
10
|
+
include Representable::Hash
|
11
|
+
|
12
|
+
# property :artist, populator: Uber::Options::Value.new(ArtistPopulator.new), pass_options:true do
|
13
|
+
# property :email
|
14
|
+
# end
|
15
|
+
# DISCUSS: rename to populator_pipeline ?
|
16
|
+
collection :songs, parse_pipeline: ->(*) { [Collect[Instance, Prepare, Deserialize], Setter] }, instance: :instance!, exec_context: :decorator, pass_options: true do
|
17
|
+
property :title
|
18
|
+
end
|
19
|
+
|
20
|
+
def instance!(*options)
|
21
|
+
puts "@@@@@ #{options.inspect}"
|
22
|
+
Song.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def songs=(array)
|
26
|
+
represented.songs=array
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it do
|
31
|
+
skip "TODO: implement :parse_pipeline and :render_pipeline, and before/after/replace semantics"
|
32
|
+
album = Album.new
|
33
|
+
Representer.new(album).from_hash({"artist"=>{"email"=>"yo"}, "songs"=>[{"title"=>"Affliction"}, {"title"=>"Dream Beater"}]})
|
34
|
+
album.songs.must_equal([Song.new("Affliction"), Song.new("Dream Beater")])
|
35
|
+
puts album.inspect
|
36
|
+
end
|
37
|
+
end
|
data/test/binding_test.rb
CHANGED
@@ -5,7 +5,7 @@ class BindingTest < MiniTest::Spec
|
|
5
5
|
let (:render_nil_definition) { Representable::Definition.new(:song, :render_nil => true) }
|
6
6
|
|
7
7
|
describe "#skipable_empty_value?" do
|
8
|
-
let (:binding) { Binding.new(render_nil_definition
|
8
|
+
let (:binding) { Binding.new(render_nil_definition) }
|
9
9
|
|
10
10
|
# don't skip when present.
|
11
11
|
it { binding.skipable_empty_value?("Disconnect, Disconnect").must_equal false }
|
@@ -14,16 +14,16 @@ class BindingTest < MiniTest::Spec
|
|
14
14
|
it { binding.skipable_empty_value?(nil).must_equal false }
|
15
15
|
|
16
16
|
# skip when nil and :render_nil undefined.
|
17
|
-
it { Binding.new(Representable::Definition.new(:song)
|
17
|
+
it { Binding.new(Representable::Definition.new(:song)).skipable_empty_value?(nil).must_equal true }
|
18
18
|
|
19
19
|
# don't skip when nil and :render_nil undefined.
|
20
|
-
it { Binding.new(Representable::Definition.new(:song)
|
20
|
+
it { Binding.new(Representable::Definition.new(:song)).skipable_empty_value?("Fatal Flu").must_equal false }
|
21
21
|
end
|
22
22
|
|
23
23
|
|
24
24
|
describe "#default_for" do
|
25
25
|
let (:definition) { Representable::Definition.new(:song, :default => "Insider") }
|
26
|
-
let (:binding) { Binding.new(definition
|
26
|
+
let (:binding) { Binding.new(definition) }
|
27
27
|
|
28
28
|
# return value when value present.
|
29
29
|
it { binding.default_for("Black And Blue").must_equal "Black And Blue" }
|
@@ -35,12 +35,12 @@ class BindingTest < MiniTest::Spec
|
|
35
35
|
it { binding.default_for(nil).must_equal "Insider" }
|
36
36
|
|
37
37
|
# return nil when value nil and render_nil: true.
|
38
|
-
it { Binding.new(render_nil_definition
|
38
|
+
it { Binding.new(render_nil_definition).default_for(nil).must_equal nil }
|
39
39
|
|
40
40
|
# return nil when value nil and render_nil: true, even when :default is set" do
|
41
|
-
it { Binding.new(Representable::Definition.new(:song, :render_nil => true, :default => "The Quest")
|
41
|
+
it { Binding.new(Representable::Definition.new(:song, :render_nil => true, :default => "The Quest")).default_for(nil).must_equal nil }
|
42
42
|
|
43
43
|
# return nil if no :default
|
44
|
-
it { Binding.new(Representable::Definition.new(:song)
|
44
|
+
it { Binding.new(Representable::Definition.new(:song)).default_for(nil).must_equal nil }
|
45
45
|
end
|
46
46
|
end
|
data/test/cached_test.rb
CHANGED
@@ -14,7 +14,7 @@ class CachedTest < MiniTest::Spec
|
|
14
14
|
include Representable::Hash
|
15
15
|
feature Representable::Cached
|
16
16
|
|
17
|
-
property :title, render_filter: lambda { |
|
17
|
+
property :title, render_filter: lambda { |input, options| "#{input}:#{options[:user_options]}" }, pass_options: true
|
18
18
|
property :composer, class: Model::Artist do
|
19
19
|
property :name
|
20
20
|
end
|
@@ -45,14 +45,16 @@ class CachedTest < MiniTest::Spec
|
|
45
45
|
"songs"=>[{"title"=>"Jailbreak:{:volume=>9}"}, {"title"=>"Southbound:{:volume=>9}"}, {"title"=>"Emerald:{:volume=>9}"}]}) # called in Deserializer/Serializer
|
46
46
|
|
47
47
|
# representer becomes reusable as it is stateless.
|
48
|
-
representer.update!(album2)
|
48
|
+
# representer.update!(album2)
|
49
49
|
|
50
50
|
# makes sure options are passed correctly.
|
51
|
-
representer.to_hash(volume:10).must_equal(album_hash)
|
51
|
+
# representer.to_hash(volume:10).must_equal(album_hash)
|
52
52
|
end
|
53
53
|
|
54
54
|
# profiling
|
55
|
-
it
|
55
|
+
it do
|
56
|
+
representer.to_hash
|
57
|
+
|
56
58
|
RubyProf.start
|
57
59
|
representer.to_hash
|
58
60
|
res = RubyProf.stop
|
@@ -65,14 +67,18 @@ class CachedTest < MiniTest::Spec
|
|
65
67
|
|
66
68
|
printer.print(STDOUT)
|
67
69
|
|
68
|
-
#
|
69
|
-
data.must_match "
|
70
|
-
#
|
71
|
-
data.must_match "
|
70
|
+
# 3 songs get decorated.
|
71
|
+
data.must_match "3 Representable::Function::Decorate#call"
|
72
|
+
# 3 nested decorator is instantiated for 3 Songs, though.
|
73
|
+
data.must_match "3 <Class::Representable::Decorator>#prepare"
|
74
|
+
# no Binding is instantiated at runtime.
|
75
|
+
data.wont_match "Representable::Binding#initialize"
|
72
76
|
# 2 mappers for Album, Song
|
73
|
-
data.must_match "2 Representable::Mapper::Methods#initialize"
|
74
|
-
#
|
75
|
-
data.must_match "
|
77
|
+
# data.must_match "2 Representable::Mapper::Methods#initialize"
|
78
|
+
# title, songs, 3x title, composer
|
79
|
+
data.must_match "8 Representable::Binding#render_pipeline"
|
80
|
+
data.wont_match "render_functions"
|
81
|
+
data.wont_match "Representable::Binding::Factories#render_functions"
|
76
82
|
end
|
77
83
|
end
|
78
84
|
|
@@ -106,10 +112,12 @@ class CachedTest < MiniTest::Spec
|
|
106
112
|
# TODO: test options.
|
107
113
|
end
|
108
114
|
|
109
|
-
it do
|
115
|
+
it "xxx" do
|
110
116
|
representer = AlbumRepresenter.new(Model::Album.new)
|
117
|
+
representer.from_hash(album_hash)
|
111
118
|
|
112
119
|
RubyProf.start
|
120
|
+
# puts "#{representer.class.representable_attrs.get(:songs).representer_module.representable_attrs.inspect}"
|
113
121
|
representer.from_hash(album_hash)
|
114
122
|
res = RubyProf.stop
|
115
123
|
|
@@ -120,15 +128,19 @@ class CachedTest < MiniTest::Spec
|
|
120
128
|
data = data.string
|
121
129
|
|
122
130
|
# only 2 nested decorators are instantiated, Song, and Artist.
|
123
|
-
data.must_match "
|
131
|
+
data.must_match "5 <Class::Representable::Decorator>#prepare"
|
124
132
|
# a total of 5 properties in the object graph.
|
125
|
-
data.
|
133
|
+
data.wont_match "Representable::Binding#initialize"
|
134
|
+
|
135
|
+
|
136
|
+
data.wont_match "parse_functions" # no pipeline creation.
|
137
|
+
data.must_match "10 Representable::Binding#parse_pipeline"
|
126
138
|
# three mappers for Album, Song, composer
|
127
|
-
data.must_match "3 Representable::Mapper::Methods#initialize"
|
128
|
-
# 6 deserializers as the songs collection uses 2.
|
129
|
-
data.must_match "6 Representable::Deserializer#initialize"
|
130
|
-
# one populater for every property.
|
131
|
-
data.must_match "5 Representable::Populator#initialize"
|
139
|
+
# data.must_match "3 Representable::Mapper::Methods#initialize"
|
140
|
+
# # 6 deserializers as the songs collection uses 2.
|
141
|
+
# data.must_match "6 Representable::Deserializer#initialize"
|
142
|
+
# # one populater for every property.
|
143
|
+
# data.must_match "5 Representable::Populator#initialize"
|
132
144
|
# printer.print(STDOUT)
|
133
145
|
end
|
134
146
|
end
|
data/test/coercion_test.rb
CHANGED
@@ -40,8 +40,8 @@ class VirtusCoercionTest < MiniTest::Spec
|
|
40
40
|
include Representable::Coercion
|
41
41
|
|
42
42
|
property :length, :type => Float,
|
43
|
-
:parse_filter => lambda { |
|
44
|
-
:render_filter => lambda { |fragment
|
43
|
+
:parse_filter => lambda { |input, options| "#{input}.1" }, # happens BEFORE coercer.
|
44
|
+
:render_filter => lambda { |fragment,*| "#{fragment}.1" }
|
45
45
|
end
|
46
46
|
|
47
47
|
# user's :parse_filter(s) are run before coercion.
|