ixtlan-babel 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,15 +6,19 @@ PATH
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
+ backports (2.6.2)
9
10
  json_pure (1.6.1)
10
- minitest (2.11.3)
11
- rake (0.9.2.2)
11
+ minitest (4.3.2)
12
+ rake (10.0.2)
13
+ virtus (0.5.1)
14
+ backports (~> 2.6.1)
12
15
 
13
16
  PLATFORMS
14
17
  ruby
15
18
 
16
19
  DEPENDENCIES
17
20
  ixtlan-babel!
18
- json_pure (~> 1.6.1)
19
- minitest (= 2.11.3)
20
- rake (= 0.9.2.2)
21
+ json_pure (~> 1.6)
22
+ minitest (~> 4.3.0)
23
+ rake (~> 10.0.0)
24
+ virtus (~> 0.5.0)
data/README.md CHANGED
@@ -1,4 +1,8 @@
1
- # vellam [![Build Status](https://secure.travis-ci.org/mkristian/babel.png)](http://travis-ci.org/mkristian/babel) #
1
+ # babel #
2
+
3
+ * [![Build Status](https://secure.travis-ci.org/mkristian/babel.png)](http://travis-ci.org/mkristian/babel)
4
+ * [![Dependency Status](https://gemnasium.com/mkristian/ixtlan-babel.png)](https://gemnasium.com/mkristian/ixtlan-babel)
5
+ * [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/mkristian/ixtlan-babel)
2
6
 
3
7
  rails comes with `to_json` and `to_xml` on models and you can give them an option map to control how the whole object tree gets serialized.
4
8
 
@@ -0,0 +1,26 @@
1
+ require 'ixtlan/babel/context'
2
+ module Ixtlan
3
+ module Babel
4
+ class AbstractFilter
5
+
6
+ attr_accessor :options
7
+
8
+ def options
9
+ @options || {}
10
+ end
11
+
12
+ def add_custom_serializers( map )
13
+ @map = map
14
+ end
15
+
16
+ def serialize( data )
17
+ if @map && ser = @map[ data.class.to_s ]
18
+ ser.call(data)
19
+ else
20
+ data
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,111 @@
1
+ require 'ixtlan/babel/context'
2
+ module Ixtlan
3
+ module Babel
4
+ class HashFilter
5
+
6
+ def initialize(context_or_options = nil)
7
+ use(context_or_options)
8
+ end
9
+
10
+ private
11
+
12
+ # def context
13
+ # @context ||= {}
14
+ # end
15
+
16
+ public
17
+
18
+ def add_custom_serializers( map )
19
+ @map = map
20
+ end
21
+
22
+ # def default_context_key( single = :single,
23
+ # collection = :collection )
24
+ # @single, @collection = single, collection
25
+ # end
26
+
27
+ # def []=( key, options )
28
+ # context[ key.to_sym ] = options if key
29
+ # end
30
+
31
+ # def []( key )
32
+ # context[ key.to_sym ] if key
33
+ # end
34
+
35
+ def use( context_or_options )
36
+ # if context_or_options
37
+ # case context_or_options
38
+ # when Symbol
39
+ # if opts = context[ context_or_options ]
40
+ # @options = opts.dup
41
+ # end
42
+ # when Hash
43
+ @options = context_or_options
44
+ # end
45
+ # else
46
+ # @options = nil
47
+ # end
48
+ # self
49
+ end
50
+
51
+ def filter( data )
52
+ if data
53
+ filter_data( data,
54
+ Context.new( @options || {} ) )
55
+ end
56
+ end
57
+
58
+ # def single_options
59
+ # @options || context[default_context_key[0]] || {}
60
+ # end
61
+
62
+ # def collection_options
63
+ # @options || context[default_context_key[1]] || {}
64
+ # end
65
+
66
+ # def root
67
+ # @root ||= single_options.key?(:root) ? single_options[:root].to_s : nil
68
+ # end
69
+
70
+ # private
71
+
72
+ # def options_for( hash )
73
+ # @options || (hash.is_a?(Array) ? collection_options : single_options)
74
+ # end
75
+
76
+ def filter_array( array, options )
77
+ array.collect do |item|
78
+ if item.is_a?( Array ) || item.is_a?( Hash )
79
+ filter_data( item, options )
80
+ else
81
+ item
82
+ end
83
+ end
84
+ end
85
+
86
+ def serialize( data )
87
+ if @map && ser = @map[ data.class.to_s ]
88
+ ser.call(data)
89
+ else
90
+ data
91
+ end
92
+ end
93
+
94
+ def filter_data( data, context )
95
+ result = {}
96
+ data.each do |k,v|
97
+ k = k.to_s
98
+ case v
99
+ when Hash
100
+ result[ k ] = filter_data( v, context[ k ] ) if context.include?( k )
101
+ when Array
102
+ result[ k ] = filter_array( v, context[ k ] ) if context.include?( k )
103
+ else
104
+ result[ k ] = serialize( v ) if context.allowed?( k )
105
+ end
106
+ end
107
+ result
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,142 @@
1
+ module Ixtlan
2
+ module Babel
3
+ class HashFilter
4
+
5
+ def initialize(context_or_options = nil)
6
+ use(context_or_options)
7
+ end
8
+
9
+ private
10
+
11
+ def context
12
+ @context ||= {}
13
+ end
14
+
15
+ public
16
+
17
+ def add_custom_serializers(map)
18
+ @map = map
19
+ end
20
+
21
+ def default_context_key( single = :single,
22
+ collection = :collection )
23
+ @single, @collection = single, collection
24
+ end
25
+
26
+ def []=( key, options )
27
+ context[ key.to_sym ] = options if key
28
+ end
29
+
30
+ def []( key )
31
+ context[ key.to_sym ] if key
32
+ end
33
+
34
+ def use( context_or_options )
35
+ if context_or_options
36
+ case context_or_options
37
+ when Symbol
38
+ if opts = context[ context_or_options ]
39
+ @options = opts.dup
40
+ end
41
+ when Hash
42
+ @options = context_or_options
43
+ end
44
+ else
45
+ @options = nil
46
+ end
47
+ self
48
+ end
49
+
50
+ def filter(hash = {}, model = nil, &block)
51
+ if hash
52
+ filter_data( hash,
53
+ Config.new( options_for( hash ) ),
54
+ &block)
55
+ end
56
+ end
57
+
58
+ def options_for( hash )
59
+ @options || (hash.is_a?(Array) ? collection_options : single_options)
60
+ end
61
+
62
+ def single_options
63
+ @options || context[default_context_key[0]] || {}
64
+ end
65
+
66
+ def collection_options
67
+ @options || context[default_context_key[1]] || {}
68
+ end
69
+
70
+ def root
71
+ @root ||= single_options.key?(:root) ? single_options[:root].to_s : nil
72
+ end
73
+
74
+ private
75
+
76
+ class Config
77
+
78
+ def initialize( options )
79
+ @only = options[ :only ].collect { |o| o.to_s } if options[ :only ]
80
+ @except = ( options[:except] || [] ).collect { |e| e.to_s }
81
+
82
+ opts = options[ :include ]
83
+ @include =
84
+ case opts
85
+ when Array
86
+ opts.collect { |i| i.to_s }
87
+ when Hash
88
+ Hash[ opts.collect { |k,v| [ k.to_s, v ] } ]
89
+ else
90
+ []
91
+ end
92
+ end
93
+
94
+ def allowed?( key )
95
+ ( @only && @only.include?( key ) ) || ( @only.nil? && !@except.include?( key ) )
96
+ end
97
+
98
+ def include?( key )
99
+ @include.include? key
100
+ end
101
+
102
+ def []( key )
103
+ self.class.new( @include.is_a?( Array ) ? {} : @include[ key ] )
104
+ end
105
+ end
106
+
107
+ def filter_array( array, options )
108
+ array.collect do |item|
109
+ if item.is_a?( Array ) || item.is_a?( Hash )
110
+ filter_data( item, options )
111
+ else
112
+ item
113
+ end
114
+ end
115
+ end
116
+
117
+ def serialize( data )
118
+ if @map && ser = @map[ data.class.to_s ]
119
+ ser.call(data)
120
+ else
121
+ data
122
+ end
123
+ end
124
+
125
+ def filter_data( data, config )
126
+ result = {}
127
+ data.each do |k,v|
128
+ k = k.to_s
129
+ case v
130
+ when Hash
131
+ result[ k ] = filter_data( v, config[ k ] ) if config.include?( k )
132
+ when Array
133
+ result[ k ] = filter_array( v, config[ k ] ) if config.include?( k )
134
+ else
135
+ result[ k ] = serialize( v ) if config.allowed?( k )
136
+ end
137
+ end
138
+ result
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,43 @@
1
+ module Ixtlan
2
+ module Babel
3
+ class Context
4
+
5
+ def initialize( options )
6
+ @only = options[ :only ].collect { |o| o.to_s } if options[ :only ]
7
+ @except = ( options[:except] || [] ).collect { |e| e.to_s }
8
+
9
+ opts = options[ :include ]
10
+ @include = case opts
11
+ when Array
12
+ opts.collect { |i| i.to_s }
13
+ when Hash
14
+ Hash[ opts.collect { |k,v| [ k.to_s, v ] } ]
15
+ else
16
+ []
17
+ end
18
+ @methods = (options[:methods] || []).collect { |m| m.to_s }
19
+ end
20
+
21
+ def methods
22
+ @methods + ( @include.is_a?( Array ) ? @include : @include.keys )
23
+ end
24
+
25
+ def allowed?( key )
26
+ ( @only && @only.include?( key ) ) || ( @only.nil? && !@except.include?( key ) ) || @methods.include?( key )
27
+ end
28
+
29
+ def include?( key )
30
+ @include.include? key
31
+ end
32
+
33
+ def array?
34
+ @include.is_a?( Array )
35
+ end
36
+
37
+ def []( key )
38
+ self.class.new( @include.is_a?( Array ) ? {} : @include[ key ] )
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ module Ixtlan
2
+ module Babel
3
+ class Config
4
+
5
+ def initialize( options )
6
+ @only = options[ :only ].collect { |o| o.to_s } if options[ :only ]
7
+ @except = ( options[:except] || [] ).collect { |e| e.to_s }
8
+
9
+ opts = options[ :include ]
10
+ @include = case opts
11
+ when Array
12
+ opts.collect { |i| i.to_s }
13
+ when Hash
14
+ Hash[ opts.collect { |k,v| [ k.to_s, v ] } ]
15
+ else
16
+ []
17
+ end
18
+ @methods = (options[:methods] || []).collect { |m| m.to_s }
19
+ end
20
+
21
+ def methods
22
+ @methods + ( @include.is_a?( Array ) ? @include : @include.keys )
23
+ end
24
+
25
+ def allowed?( key )
26
+ ( @only && @only.include?( key ) ) || ( @only.nil? && !@except.include?( key ) ) || @methods.include?( key )
27
+ end
28
+
29
+ def include?( key )
30
+ @include.include? key
31
+ end
32
+
33
+ def array?
34
+ @include.is_a?( Array )
35
+ end
36
+
37
+ def []( key )
38
+ self.class.new( @include.is_a?( Array ) ? {} : @include[ key ] )
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -8,46 +8,48 @@ module Ixtlan
8
8
 
9
9
  private
10
10
 
11
- def self.filter
12
- @filter ||= HashFilter.new
11
+ def self.config
12
+ @config ||= FilterConfig.new
13
13
  end
14
14
 
15
15
  def filter
16
- @filter ||= self.class.filter.dup
16
+ @filter ||= HashFilter.new
17
17
  end
18
18
 
19
19
  protected
20
20
 
21
21
  def self.default_context_key(default)
22
- filter.default_context_key(default)
22
+ config.default_context_key(default)
23
23
  end
24
24
 
25
25
  def self.add_context(key, options = {})
26
- filter[key] = options
26
+ config[key] = options
27
27
  end
28
28
 
29
29
  public
30
30
 
31
31
  def use(context_or_options)
32
- filter.use(context_or_options)
32
+ @context_or_options = context_or_options
33
33
  self
34
34
  end
35
+
36
+ def from_array_hash( data )
37
+ if filter.options[:root]
38
+ data.collect{ |d| @model_class.new( filter.filter( d[ filter.options[:root] ] ) ) }
39
+ else
40
+ data.collect{ |d| @model_class.new( filter.filter( d ) ) }
41
+ end
42
+ end
43
+ private :from_array_hash
35
44
 
36
45
  def from_hash(data, options = nil)
37
- filter.use(options) if options
38
- if root = filter.options[:root]
39
- if data.is_a? Array
40
- root = root.to_s
41
- data.collect{ |d| @model_class.new(filter.filter(d[root])) }
42
- else
43
- @model_class.new(filter.filter(data[root.to_s]))
44
- end
46
+ filter.options = options || {}
47
+ filter.options[:root] ||= self.class.config.root
48
+ if data.is_a? Array
49
+ from_array_hash( data )
45
50
  else
46
- if data.is_a? Array
47
- data.collect{ |d| @model_class.new(filter.filter(d)) }
48
- else
49
- @model_class.new(filter.filter(data))
50
- end
51
+ data = data[ filter.options[:root] ] if filter.options[:root]
52
+ @model_class.new( filter.filter( data ) )
51
53
  end
52
54
  end
53
55