ixtlan-babel 0.5.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -1
- data/MIT-LICENSE +1 -1
- data/README.md +3 -14
- data/Rakefile +27 -0
- data/lib/ixtlan-babel.rb +0 -21
- data/lib/ixtlan-babel.rb~ +1 -0
- data/lib/ixtlan/babel/common_filters.rb +21 -0
- data/lib/ixtlan/babel/common_filters.rb~ +14 -0
- data/lib/ixtlan/babel/factory.rb +36 -56
- data/lib/ixtlan/babel/factory.rb~ +39 -59
- data/lib/ixtlan/babel/hash_filter.rb +125 -44
- data/lib/ixtlan/babel/hash_filter.rb~ +149 -40
- data/lib/ixtlan/babel/model_filter.rb~ +114 -52
- data/lib/ixtlan/babel/model_serializer.rb +103 -0
- data/lib/ixtlan/babel/model_serializer.rb~ +104 -0
- data/spec/hash_filter_spec.rb +71 -102
- data/spec/model_serializer_spec.rb +159 -0
- data/spec/model_serializer_spec.rb~ +158 -0
- data/spec/spec_helper.rb +5 -3
- data/spec/spec_helper.rb~ +8 -0
- metadata +53 -72
- data/lib/ixtlan/babel/abstract_filter.rb +0 -46
- data/lib/ixtlan/babel/context.rb +0 -67
- data/lib/ixtlan/babel/dm_validation_errors_serializer.rb +0 -8
- data/lib/ixtlan/babel/filter_config.rb +0 -74
- data/lib/ixtlan/babel/model_filter.rb +0 -79
- data/lib/ixtlan/babel/params_filter.rb +0 -149
- data/lib/ixtlan/babel/serializer.rb +0 -186
- data/spec/model_filter_spec.rb +0 -131
- data/spec/model_filter_with_dsl_spec.rb +0 -173
- data/spec/model_filter_with_methods_spec.rb +0 -151
- data/spec/params_filter_dsl_spec.rb +0 -134
- data/spec/params_filter_spec.rb +0 -113
@@ -1,74 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (C) 2013 Christian Meier
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
-
# this software and associated documentation files (the "Software"), to deal in
|
6
|
-
# the Software without restriction, including without limitation the rights to
|
7
|
-
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
-
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
-
# subject to the following conditions:
|
10
|
-
#
|
11
|
-
# The above copyright notice and this permission notice shall be included in all
|
12
|
-
# copies or substantial portions of the Software.
|
13
|
-
#
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
-
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
-
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
-
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
-
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
-
#
|
21
|
-
require 'ixtlan/babel/context'
|
22
|
-
module Ixtlan
|
23
|
-
module Babel
|
24
|
-
class FilterConfig
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def context
|
29
|
-
@context ||= {}
|
30
|
-
end
|
31
|
-
|
32
|
-
def context_options( context_or_options )
|
33
|
-
if context_or_options
|
34
|
-
case context_or_options
|
35
|
-
when Symbol
|
36
|
-
if opts = context[ context_or_options ]
|
37
|
-
opts.dup
|
38
|
-
end
|
39
|
-
when Hash
|
40
|
-
context_or_options
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
public
|
46
|
-
|
47
|
-
def default_context_key( single = :single,
|
48
|
-
collection = :collection )
|
49
|
-
@single, @collection = single, collection
|
50
|
-
end
|
51
|
-
|
52
|
-
def []=( key, options )
|
53
|
-
context[ key.to_sym ] = options if key
|
54
|
-
end
|
55
|
-
|
56
|
-
def []( key )
|
57
|
-
context[ key.to_sym ] if key
|
58
|
-
end
|
59
|
-
|
60
|
-
def single_options( context_or_options )
|
61
|
-
context_options( context_or_options ) ||
|
62
|
-
context[ default_context_key[ 0 ] ] || {}
|
63
|
-
end
|
64
|
-
|
65
|
-
def collection_options( context_or_options )
|
66
|
-
context_options( context_or_options ) ||
|
67
|
-
context[ default_context_key[ 1 ] ] || {}
|
68
|
-
end
|
69
|
-
|
70
|
-
attr_accessor :root
|
71
|
-
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,79 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (C) 2013 Christian Meier
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
-
# this software and associated documentation files (the "Software"), to deal in
|
6
|
-
# the Software without restriction, including without limitation the rights to
|
7
|
-
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
-
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
-
# subject to the following conditions:
|
10
|
-
#
|
11
|
-
# The above copyright notice and this permission notice shall be included in all
|
12
|
-
# copies or substantial portions of the Software.
|
13
|
-
#
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
-
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
-
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
-
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
-
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
-
#
|
21
|
-
require 'ixtlan/babel/abstract_filter'
|
22
|
-
module Ixtlan
|
23
|
-
module Babel
|
24
|
-
class ModelFilter < AbstractFilter
|
25
|
-
|
26
|
-
def filter( model, &block )
|
27
|
-
if model
|
28
|
-
data = block.call( model )
|
29
|
-
filter_data( model, data,
|
30
|
-
Context.new( options ),
|
31
|
-
&block )
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def filter_array( models, options, &block )
|
38
|
-
models.collect do |i|
|
39
|
-
if i.respond_to? :attributes
|
40
|
-
filter_data(i, block.call(i), options, &block)
|
41
|
-
else
|
42
|
-
serialize( i )
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def setup_data(model, data, context)
|
48
|
-
context.methods.each do |m|
|
49
|
-
unless data.include?(m)
|
50
|
-
data[ m ] = model.send( m.to_sym )
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def filter_data(model, data, context, &block)
|
56
|
-
setup_data(model, data, context)
|
57
|
-
|
58
|
-
result = {}
|
59
|
-
data.each do |k,v|
|
60
|
-
k = k.to_s
|
61
|
-
if v.respond_to? :attributes
|
62
|
-
result[ k ] = filter_data( v,
|
63
|
-
block.call(v),
|
64
|
-
context[ k ],
|
65
|
-
&block ) if context.include?( k )
|
66
|
-
elsif v.is_a? Array
|
67
|
-
result[ k ] = filter_array( v,
|
68
|
-
context[ k ],
|
69
|
-
&block ) if context.include?( k )
|
70
|
-
else
|
71
|
-
result[ k ] = serialize( v ) if context.allowed?( k ) &&
|
72
|
-
! v.respond_to?( :attributes )
|
73
|
-
end
|
74
|
-
end
|
75
|
-
result
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
@@ -1,149 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (C) 2013 Christian Meier
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
-
# this software and associated documentation files (the "Software"), to deal in
|
6
|
-
# the Software without restriction, including without limitation the rights to
|
7
|
-
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
-
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
-
# subject to the following conditions:
|
10
|
-
#
|
11
|
-
# The above copyright notice and this permission notice shall be included in all
|
12
|
-
# copies or substantial portions of the Software.
|
13
|
-
#
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
-
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
-
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
-
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
-
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
-
#
|
21
|
-
require 'ixtlan/babel/hash_filter'
|
22
|
-
require 'ixtlan/babel/filter_config'
|
23
|
-
|
24
|
-
module Ixtlan
|
25
|
-
module Babel
|
26
|
-
class ParamsFilter
|
27
|
-
|
28
|
-
def initialize( model_class )
|
29
|
-
@model_class = model_class
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def self.config
|
35
|
-
@config ||= FilterConfig.new
|
36
|
-
end
|
37
|
-
|
38
|
-
def filter
|
39
|
-
@filter ||= HashFilter.new
|
40
|
-
end
|
41
|
-
|
42
|
-
protected
|
43
|
-
|
44
|
-
def self.default_context_key(default)
|
45
|
-
config.default_context_key(default)
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.add_context( key = :single, options = nil, &block )
|
49
|
-
current = config[key] = options || { :only => [] }
|
50
|
-
@context = key
|
51
|
-
yield if block
|
52
|
-
current[ :keep ] = @keep if @keep
|
53
|
-
current.merge!( @allow ) if @allow
|
54
|
-
current[ :root ] = @root
|
55
|
-
ensure
|
56
|
-
@context = nil
|
57
|
-
@allow = nil
|
58
|
-
@keep = nil
|
59
|
-
@root = nil
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.root( root )
|
63
|
-
if @context
|
64
|
-
@root = root
|
65
|
-
else
|
66
|
-
config.root = root
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.keep( *args )
|
71
|
-
@keep = *args
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.only( *args )
|
75
|
-
result = {}
|
76
|
-
if args.last.is_a? Hash
|
77
|
-
result[ :include ] = args.last
|
78
|
-
result[ :only ] = args[ 0..-2 ]
|
79
|
-
else
|
80
|
-
result[ :only ] = args
|
81
|
-
end
|
82
|
-
@allow = result
|
83
|
-
result
|
84
|
-
end
|
85
|
-
|
86
|
-
public
|
87
|
-
|
88
|
-
def use(context_or_options)
|
89
|
-
@context_or_options = context_or_options
|
90
|
-
self
|
91
|
-
end
|
92
|
-
|
93
|
-
class FilterResult
|
94
|
-
|
95
|
-
def initialize( model, params, keeps )
|
96
|
-
@model = model
|
97
|
-
@data = keeps
|
98
|
-
@data[ :params ] = params
|
99
|
-
end
|
100
|
-
|
101
|
-
def new_model
|
102
|
-
@model.send( :new, params )
|
103
|
-
end
|
104
|
-
|
105
|
-
def []( key )
|
106
|
-
params[ key ]
|
107
|
-
end
|
108
|
-
|
109
|
-
def params
|
110
|
-
@data[ :params ]
|
111
|
-
end
|
112
|
-
|
113
|
-
def method_missing( method, *args )
|
114
|
-
if respond_to?( method )
|
115
|
-
@data[ method ] || @data[ method.to_s ]
|
116
|
-
elsif @data.respond_to?( method )
|
117
|
-
@data.send( method, *args )
|
118
|
-
else
|
119
|
-
super
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def respond_to?( method )
|
124
|
-
@data.key?( method ) || @data.key?( method.to_s )
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def filter_it( data )
|
129
|
-
filter.options = self.class.config.single_options( @context_or_options )
|
130
|
-
data = data.dup
|
131
|
-
data = data[ filter.options[ :root ] ] if filter.options[ :root ]
|
132
|
-
keeps = {}
|
133
|
-
( filter.options[ :keep ] || [] ).each do |k|
|
134
|
-
keep = data[ k.to_s ] || data[ k.to_sym ]
|
135
|
-
keeps[ k.to_s ] = data.delete( k.to_s ) ||
|
136
|
-
data.delete( k.to_sym ) unless keep.is_a? Hash
|
137
|
-
end
|
138
|
-
filtered_data = filter.filter( data )
|
139
|
-
( filter.options[ :keep ] || [] ).each do |k|
|
140
|
-
keeps[ k.to_s ] = filtered_data.delete( k.to_s ) ||
|
141
|
-
filtered_data.delete( k.to_sym ) unless keeps.member?( k.to_s )
|
142
|
-
# just make sure we have an entry for each keeps key
|
143
|
-
keeps[ k.to_s ] ||= nil
|
144
|
-
end
|
145
|
-
FilterResult.new( @model_class, filtered_data, keeps )
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
@@ -1,186 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (C) 2013 Christian Meier
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
-
# this software and associated documentation files (the "Software"), to deal in
|
6
|
-
# the Software without restriction, including without limitation the rights to
|
7
|
-
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
-
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
-
# subject to the following conditions:
|
10
|
-
#
|
11
|
-
# The above copyright notice and this permission notice shall be included in all
|
12
|
-
# copies or substantial portions of the Software.
|
13
|
-
#
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
-
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
-
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
-
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
-
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
-
#
|
21
|
-
require 'multi_json'
|
22
|
-
require 'ixtlan/babel/hash_filter'
|
23
|
-
require 'ixtlan/babel/model_filter'
|
24
|
-
require 'ixtlan/babel/filter_config'
|
25
|
-
module Ixtlan
|
26
|
-
module Babel
|
27
|
-
class Serializer
|
28
|
-
|
29
|
-
def id
|
30
|
-
if @model_or_models.is_a? Array
|
31
|
-
super
|
32
|
-
else
|
33
|
-
@model_or_models.id
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def initialize(model_or_models)
|
38
|
-
@model_or_models = model_or_models
|
39
|
-
end
|
40
|
-
|
41
|
-
def respond_to?(method)
|
42
|
-
@model_or_models.respond_to?(method)
|
43
|
-
end
|
44
|
-
|
45
|
-
def method_missing(method, *args, &block)
|
46
|
-
@model_or_models.send(method, *args, &block)
|
47
|
-
end
|
48
|
-
|
49
|
-
def add_custom_serializers(map)
|
50
|
-
filter.add_custom_serializers(map)
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def self.config
|
56
|
-
@config ||= FilterConfig.new
|
57
|
-
end
|
58
|
-
|
59
|
-
def filter
|
60
|
-
@filter ||= ModelFilter.new
|
61
|
-
end
|
62
|
-
|
63
|
-
protected
|
64
|
-
|
65
|
-
# for rails
|
66
|
-
def self.model(model = nil)
|
67
|
-
@model_class = model if model
|
68
|
-
@model_class ||= self.to_s.sub(/Serializer$/, '').constantize
|
69
|
-
end
|
70
|
-
|
71
|
-
# for rails
|
72
|
-
def self.model_name
|
73
|
-
model.model_name
|
74
|
-
end
|
75
|
-
|
76
|
-
def self.default_context_key(single = :single, collection = :collection)
|
77
|
-
config.default_context_key(single, collection)
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.add_context(key = :single, options = nil, &block)
|
81
|
-
current = config[key] = options || { :only => Array.new }
|
82
|
-
@only = nil
|
83
|
-
@root = nil
|
84
|
-
@context = key
|
85
|
-
yield if block
|
86
|
-
current.merge!( @only ) if @only
|
87
|
-
current[ :root ] = @root
|
88
|
-
ensure
|
89
|
-
@context = nil
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.only( *args )
|
93
|
-
args.flatten!
|
94
|
-
result = { :only => Array.new }
|
95
|
-
if args.last.is_a? Hash
|
96
|
-
result[ :include ] = args.last
|
97
|
-
result[ :methods ] = args[ 0..-2 ]
|
98
|
-
else
|
99
|
-
result[ :methods ] = args
|
100
|
-
end
|
101
|
-
@only = result
|
102
|
-
result
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.root( root )
|
106
|
-
if @context
|
107
|
-
@root = root
|
108
|
-
else
|
109
|
-
config.root = root
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
public
|
114
|
-
|
115
|
-
def use( context_or_options )
|
116
|
-
@context_or_options = context_or_options
|
117
|
-
self
|
118
|
-
end
|
119
|
-
|
120
|
-
def to_hash(options = nil)
|
121
|
-
setup_filter( options )
|
122
|
-
if collection?
|
123
|
-
@model_or_models.collect do |m|
|
124
|
-
filter_model( m )
|
125
|
-
end
|
126
|
-
else
|
127
|
-
filter_model( @model_or_models )
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def to_json(options = nil)
|
132
|
-
to_hash(options).to_json
|
133
|
-
end
|
134
|
-
|
135
|
-
def setup_filter(options)
|
136
|
-
o = if collection?
|
137
|
-
self.class.config.collection_options( @context_or_options )
|
138
|
-
else
|
139
|
-
self.class.config.single_options( @context_or_options )
|
140
|
-
end
|
141
|
-
filter.options = o.merge!( options || {} )
|
142
|
-
filter.options[:root] ||= self.class.config.root
|
143
|
-
end
|
144
|
-
private :setup_filter
|
145
|
-
|
146
|
-
def collection?
|
147
|
-
@is_collection ||= @model_or_models.respond_to?(:collect) &&
|
148
|
-
! @model_or_models.is_a?(Hash)
|
149
|
-
end
|
150
|
-
private :collection?
|
151
|
-
|
152
|
-
def to_xml(options = nil)
|
153
|
-
setup_filter
|
154
|
-
|
155
|
-
result = to_hash
|
156
|
-
|
157
|
-
root = config.root
|
158
|
-
|
159
|
-
if root && result.is_a?(Array) && root.respond_to?(:pluralize)
|
160
|
-
root = root.pluralize
|
161
|
-
end
|
162
|
-
result.to_xml :root => root
|
163
|
-
end
|
164
|
-
|
165
|
-
def to_yaml(options = nil)
|
166
|
-
to_hash(options).to_yaml
|
167
|
-
end
|
168
|
-
|
169
|
-
protected
|
170
|
-
|
171
|
-
def attr(model)
|
172
|
-
model.attributes if model
|
173
|
-
end
|
174
|
-
|
175
|
-
private
|
176
|
-
|
177
|
-
def filter_model( model )
|
178
|
-
if root = filter.options[:root]
|
179
|
-
{ root.to_s => filter.filter( model ){ |model| attr(model) } }
|
180
|
-
else
|
181
|
-
filter.filter( model ){ |model| attr(model) }
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|