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.
@@ -4,13 +4,9 @@ module Ixtlan
4
4
  class NoTimestampSerializer < Serializer
5
5
 
6
6
  def self.add_defaults(root = nil)
7
- if root
8
- add_context(:default, :root => root)
9
- add_no_timestamp_context(:collection, :root => root)
10
- else
11
- add_context(:default)
12
- add_no_timestamp_context(:collection)
13
- end
7
+ self.root root
8
+ add_context(:default)
9
+ add_no_timestamp_context(:collection)
14
10
  end
15
11
 
16
12
  def self.add_no_timestamp_context(key, options = {})
@@ -1,4 +1,6 @@
1
1
  require 'ixtlan/babel/hash_filter'
2
+ require 'ixtlan/babel/model_filter'
3
+ require 'ixtlan/babel/filter_config'
2
4
  module Ixtlan
3
5
  module Babel
4
6
  class Serializer
@@ -29,12 +31,12 @@ module Ixtlan
29
31
 
30
32
  private
31
33
 
32
- def self.filter
33
- @filter ||= HashFilter.new
34
+ def self.config
35
+ @config ||= FilterConfig.new
34
36
  end
35
37
 
36
38
  def filter
37
- @filter ||= self.class.filter.dup
39
+ @filter ||= @model_or_models.is_a?( Hash ) ? HashFilter.new : ModelFilter.new
38
40
  end
39
41
 
40
42
  protected
@@ -50,29 +52,33 @@ module Ixtlan
50
52
  model.model_name
51
53
  end
52
54
 
53
- def self.default_context_key(default)
54
- filter.default_context_key(default)
55
+ def self.default_context_key(single = :single, collection = :collection)
56
+ config.default_context_key(single, collection)
55
57
  end
56
58
 
57
59
  def self.add_context(key, options = {})
58
- filter[key] = options
60
+ config[key] = options
61
+ end
62
+
63
+ def self.root( root )
64
+ config.root = root
59
65
  end
60
66
 
61
67
  public
62
68
 
63
- def use(context_or_options)
64
- filter.use(context_or_options)
69
+ def use( context_or_options )
70
+ @context_or_options = context_or_options
65
71
  self
66
72
  end
67
73
 
68
74
  def to_hash(options = nil)
69
- filter.use(filter.options.dup.merge!(options)) if options
70
- if @model_or_models.respond_to?(:collect) && ! @model_or_models.is_a?(Hash)
75
+ setup_filter( options )
76
+ if collection?
71
77
  @model_or_models.collect do |m|
72
- filter_model(attr(m), m)
78
+ filter_model( m )
73
79
  end
74
80
  else
75
- filter_model(attr(@model_or_models), @model_or_models)
81
+ filter_model( @model_or_models )
76
82
  end
77
83
  end
78
84
 
@@ -80,13 +86,31 @@ module Ixtlan
80
86
  to_hash(options).to_json
81
87
  end
82
88
 
83
- def to_xml(options = {})
84
- opts = filter.options.dup.merge!(options)
85
- root = opts.delete :root
86
- fitler.use(opts)
89
+ def setup_filter(options)
90
+ o = if collection?
91
+ self.class.config.collection_options( @context_or_options )
92
+ else
93
+ self.class.config.single_options( @context_or_options )
94
+ end
95
+ filter.options = o.merge!( options || {} )
96
+ filter.options[:root] ||= self.class.config.root
97
+ end
98
+ private :setup_filter
99
+
100
+ def collection?
101
+ @is_collection ||= @model_or_models.respond_to?(:collect) && ! @model_or_models.is_a?(Hash)
102
+ end
103
+ private :collection?
104
+
105
+ def to_xml(options = nil)
106
+ setup_filter
107
+
87
108
  result = to_hash
109
+
110
+ root = config.root
111
+
88
112
  if root && result.is_a?(Array) && root.respond_to?(:pluralize)
89
- root = root.to_s.pluralize
113
+ root = root.pluralize
90
114
  end
91
115
  result.to_xml :root => root
92
116
  end
@@ -103,11 +127,11 @@ module Ixtlan
103
127
 
104
128
  private
105
129
 
106
- def filter_model(model, data)
130
+ def filter_model( model )
107
131
  if root = filter.options[:root]
108
- {root.to_s => filter.filter(model, data){ |model| attr(model) } }
132
+ { root.to_s => filter.filter( model ){ |model| attr(model) } }
109
133
  else
110
- filter.filter(model, data){ |model| attr(model) }
134
+ filter.filter( model ){ |model| attr(model) }
111
135
  end
112
136
  end
113
137
  end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ class Hash
4
+ def attributes
5
+ self
6
+ end
7
+ def method_missing(method)
8
+ self[method.to_s]
9
+ end
10
+ end
11
+
12
+ describe Ixtlan::Babel::HashFilter do
13
+ let(:data) do
14
+ data = {
15
+ 'id' => 987,
16
+ 'name' => 'me and the corner',
17
+ 'address' => { 'street' => 'Foo 12', 'zipcode' => '12345' },
18
+ 'phone_numbers' => {
19
+ 'prefix' => 12,
20
+ 'number' => '123',
21
+ 'area' => { 'code' => '001', 'iso' => 'us'}
22
+ }
23
+ }
24
+ class Hash
25
+ def self.new(hash = nil, &block)
26
+ if hash
27
+ self[hash]
28
+ else
29
+ super &block
30
+ end
31
+ end
32
+ end
33
+ data
34
+ end
35
+
36
+ let(:serializer) { Ixtlan::Babel::Serializer.new(data) }
37
+ let(:deserializer) { Ixtlan::Babel::Deserializer.new(Hash) }
38
+
39
+ it 'should serialize and deserialize a hash' do
40
+ json = serializer.to_json
41
+ result = deserializer.from_json(json)
42
+ result.must_equal Hash['id' => data['id'], 'name' => data['name']]
43
+ end
44
+
45
+ it 'should serialize and deserialize a hash with root' do
46
+ json = serializer.to_json :root => 'my'
47
+ result = deserializer.from_json(json, :root => 'my')
48
+ result.must_equal Hash['id' => data['id'], 'name' => data['name']]
49
+ end
50
+
51
+ it 'should serialize and deserialize a hash with include list' do
52
+ json = serializer.to_json(:include => ['address', 'phone_numbers'])
53
+ result = deserializer.from_json(json, :include => ['address', 'phone_numbers'])
54
+ data['phone_numbers'].delete('area')
55
+ result.must_equal Hash[data]
56
+ end
57
+
58
+ it 'should serialize and deserialize a hash with except' do
59
+ json = serializer.to_json(:except => ['id'])
60
+ result = deserializer.from_json(json, :except => ['id'])
61
+ result.must_equal Hash['name' => data['name']]
62
+ result = deserializer.from_json(json)
63
+ result.must_equal Hash['name' => data['name']]
64
+ end
65
+
66
+ it 'should serialize and deserialize a hash with only' do
67
+ json = serializer.to_json(:only => ['name'])
68
+ result = deserializer.from_json(json, :only => ['name'])
69
+ result.must_equal Hash['name' => data['name']]
70
+ result = deserializer.from_json(json)
71
+ result.must_equal Hash['name' => data['name']]
72
+ end
73
+
74
+ it 'should serialize and deserialize a hash with nested only' do
75
+ json = serializer.to_json(:include => { 'address' => {:only => ['street']}})
76
+ data.delete('phone_numbers')
77
+ data['address'].delete('zipcode')
78
+ result = deserializer.from_json(json, :include => { 'address' => {:only => ['street']}})
79
+ result.must_equal data
80
+ result = deserializer.from_json(json, :include => ['address'])
81
+ result.must_equal data
82
+ end
83
+
84
+ it 'should serialize and deserialize a hash with nested except' do
85
+ json = serializer.to_json(:include => { 'address' => {:except => ['zipcode']}})
86
+ data.delete('phone_numbers')
87
+ data['address'].delete('zipcode')
88
+ result = deserializer.from_json(json, :include => { 'address' => {:except => ['zipcode']}})
89
+ result.must_equal data
90
+ result = deserializer.from_json(json, :include => ['address'])
91
+ result.must_equal data
92
+ end
93
+
94
+ it 'should serialize and deserialize a hash with nested include' do
95
+ json = serializer.to_json(:include => { 'address' => {}, 'phone_numbers' => { :include => ['area']}})
96
+ result = deserializer.from_json(json, :include => { 'address' => {}, 'phone_numbers' => { :include => ['area']}})
97
+ result.must_equal data
98
+ end
99
+ end
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+ require 'virtus'
3
+
4
+ class Address
5
+ include Virtus
6
+
7
+ attribute :street, String
8
+ attribute :zipcode, String
9
+ end
10
+ class Area
11
+ include Virtus
12
+
13
+ attribute :code, String
14
+ attribute :iso, String
15
+ end
16
+ class PhoneNumber
17
+ include Virtus
18
+
19
+ attribute :prefix, Integer
20
+ attribute :number, String
21
+ attribute :area, Area
22
+ end
23
+ class Person
24
+ include Virtus
25
+
26
+ attribute :id, String
27
+ attribute :name, String
28
+ attribute :address, Address
29
+ attribute :phone_numbers, Array[PhoneNumber]
30
+ end
31
+
32
+ describe Ixtlan::Babel::ModelFilter do
33
+ let( :person ) do
34
+ Person.new(
35
+ :id => 987,
36
+ :name => 'me and the corner',
37
+ :address => Address.new( :street => 'Foo 12', :zipcode => '12345' ),
38
+ :phone_numbers => [PhoneNumber.new(
39
+ :prefix => 12,
40
+ :number => '123',
41
+ :area => Area.new( :code => '001', :iso => 'us' )
42
+ )]
43
+ )
44
+ end
45
+
46
+ let(:serializer) { Ixtlan::Babel::Serializer.new( person ) }
47
+ let(:deserializer) { Ixtlan::Babel::Deserializer.new( Person ) }
48
+
49
+ it 'should serialize and deserialize without root' do
50
+ json = serializer.to_json
51
+ result = deserializer.from_json(json)
52
+ attributes = result.attributes.delete_if { |k,v| v.nil? }
53
+ attributes.must_equal Hash[:id => person['id'], :name => person['name']]
54
+ end
55
+
56
+ it 'should serialize and deserialize with root' do
57
+ json = serializer.to_json :root => 'my'
58
+ result = deserializer.from_json(json, :root => 'my')
59
+ attributes = result.attributes.delete_if { |k,v| v.nil? }
60
+ attributes.must_equal Hash[:id => person['id'], :name => person['name']]
61
+ end
62
+
63
+ it 'should serialize and deserialize a hash with include list' do
64
+ json = serializer.to_json(:include => ['address', 'phone_numbers'])
65
+ result = deserializer.from_json(json, :include => ['address', 'phone_numbers'])
66
+ result.object_id.wont_equal person.object_id
67
+ result.address.attributes.must_equal person.address.attributes
68
+ result.phone_numbers[0].area.must_be_nil
69
+ person.phone_numbers[0].area = nil
70
+ result.phone_numbers[0].attributes.must_equal person.phone_numbers[0].attributes
71
+ result.name.must_equal person.name
72
+ result.id.must_equal person.id
73
+ end
74
+
75
+ it 'shouldserialize and deserialize with except' do
76
+ json = serializer.to_json(:except => ['id'])
77
+ result = deserializer.from_json(json, :except => ['id'])
78
+ result.attributes.must_equal Hash[:name => person['name'], :address=>nil, :phone_numbers=>nil, :id => nil]
79
+ result = deserializer.from_json(json)
80
+ result.attributes.must_equal Hash[:name => person['name'], :address=>nil, :phone_numbers=>nil, :id => nil]
81
+ end
82
+
83
+ it 'should serialize and deserialize with only' do
84
+ json = serializer.to_json(:only => ['name'])
85
+ result = deserializer.from_json(json, :only => ['name'])
86
+ result.attributes.must_equal Hash[:name => person['name'], :address=>nil, :phone_numbers=>nil, :id => nil]
87
+ result = deserializer.from_json(json)
88
+ result.attributes.must_equal Hash[:name => person['name'], :address=>nil, :phone_numbers=>nil, :id => nil]
89
+ end
90
+
91
+ it 'should serialize and deserialize with nested only' do
92
+ json = serializer.to_json(:include => { 'address' => {:only => ['street']}})
93
+ result = deserializer.from_json(json, :include => { 'address' => {:only => ['street']}})
94
+
95
+ json['phone_numbers'].must_be_nil
96
+ json['address']['zipcode'].must_be_nil
97
+
98
+ result.phone_numbers.must_be_nil
99
+
100
+ result.address.zipcode.must_be_nil
101
+
102
+ result.name.must_equal person.name
103
+ result.id.must_equal person.id
104
+ end
105
+
106
+ it 'should serialize and deserialize with nested only (array includes)' do
107
+ json = serializer.to_json(:include => { 'address' => {:only => ['street']}})
108
+ result = deserializer.from_json(json, :include => ['address'])
109
+
110
+ json['phone_numbers'].must_be_nil
111
+ json['address']['zipcode'].must_be_nil
112
+
113
+ result.phone_numbers.must_be_nil
114
+
115
+ result.address.zipcode.must_be_nil
116
+
117
+ result.name.must_equal person.name
118
+ result.id.must_equal person.id
119
+ end
120
+
121
+ it 'should serialize and deserialize with nested except' do
122
+ json = serializer.to_json(:include => { 'address' => {:except => ['zipcode']}})
123
+ result = deserializer.from_json(json, :include => { 'address' => {:except => ['zipcode']}})
124
+
125
+ json['phone_numbers'].must_be_nil
126
+ json['address']['zipcode'].must_be_nil
127
+
128
+ result.phone_numbers.must_be_nil
129
+
130
+ result.address.zipcode.must_be_nil
131
+
132
+ result.name.must_equal person.name
133
+ result.id.must_equal person.id
134
+ end
135
+
136
+ it 'should serialize and deserialize with nested except (array includes)' do
137
+ json = serializer.to_json(:include => { 'address' => {:except => ['zipcode']}})
138
+ result = deserializer.from_json(json, :include => ['address'])
139
+
140
+ json['phone_numbers'].must_be_nil
141
+ json['address']['zipcode'].must_be_nil
142
+
143
+ result.phone_numbers.must_be_nil
144
+
145
+ result.address.zipcode.must_be_nil
146
+
147
+ result.name.must_equal person.name
148
+ result.id.must_equal person.id
149
+ end
150
+
151
+ it 'should serialize and deserialize with nested include' do
152
+ json = serializer.to_json(:include => { 'address' => {}, 'phone_numbers' => { :include => ['area']}})
153
+ result = deserializer.from_json(json, :include => { 'address' => {}, 'phone_numbers' => { :include => ['area']}})
154
+
155
+ result.object_id.wont_equal person.object_id
156
+ result.address.attributes.must_equal person.address.attributes
157
+ result.phone_numbers[0].area.attributes.must_equal person.phone_numbers[0].area.attributes
158
+ result.phone_numbers[0].prefix.must_equal person.phone_numbers[0].prefix
159
+ result.phone_numbers[0].number.must_equal person.phone_numbers[0].number
160
+ result.name.must_equal person.name
161
+ result.id.must_equal person.id
162
+ end
163
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ class Hash
4
+ def attributes
5
+ self
6
+ end
7
+ def method_missing(method)
8
+ self[method.to_s]
9
+ end
10
+ end
11
+
12
+ describe Ixtlan::Babel do
13
+ let(:data) do
14
+ data = {
15
+ 'id' => 987,
16
+ 'name' => 'me and the corner',
17
+ 'address' => { 'street' => 'Foo 12', 'zipcode' => '12345' },
18
+ 'phone_numbers' => {
19
+ 'prefix' => 12,
20
+ 'number' => '123',
21
+ 'area' => { 'code' => '001', 'iso' => 'us'}
22
+ }
23
+ }
24
+ class Hash
25
+ def self.new(hash = nil, &block)
26
+ if hash
27
+ self[hash]
28
+ else
29
+ super &block
30
+ end
31
+ end
32
+ end
33
+ data
34
+ end
35
+
36
+ let(:serializer) { Ixtlan::Babel::Serializer.new(data) }
37
+ let(:deserializer) { Ixtlan::Babel::Deserializer.new(Hash) }
38
+
39
+ it 'should serialize and deserialize a hash' do
40
+ json = serializer.to_json
41
+ result = deserializer.from_json(json)
42
+ result.must_equal Hash['id' => data['id'], 'name' => data['name']]
43
+ end
44
+
45
+ it 'should serialize and deserialize a hash with root' do
46
+ json = serializer.to_json :root => :my
47
+ result = deserializer.from_json(json, :root => :my)
48
+ result.must_equal Hash['id' => data['id'], 'name' => data['name']]
49
+ end
50
+
51
+ it 'should serialize and deserialize a hash with include list' do
52
+ json = serializer.to_json(:include => ['address', 'phone_numbers'])
53
+ result = deserializer.from_json(json, :include => ['address', 'phone_numbers'])
54
+ data['phone_numbers'].delete('area')
55
+ result.must_equal Hash[data]
56
+ end
57
+
58
+ it 'should serialize and deserialize a hash with except' do
59
+ json = serializer.to_json(:except => ['id'])
60
+ result = deserializer.from_json(json, :except => ['id'])
61
+ result.must_equal Hash['name' => data['name']]
62
+ result = deserializer.from_json(json)
63
+ result.must_equal Hash['name' => data['name']]
64
+ end
65
+
66
+ it 'should serialize and deserialize a hash with only' do
67
+ json = serializer.to_json(:only => ['name'])
68
+ result = deserializer.from_json(json, :only => ['name'])
69
+ result.must_equal Hash['name' => data['name']]
70
+ result = deserializer.from_json(json)
71
+ result.must_equal Hash['name' => data['name']]
72
+ end
73
+
74
+ it 'should serialize and deserialize a hash with nested only' do
75
+ json = serializer.to_json(:include => { 'address' => {:only => ['street']}})
76
+ data.delete('phone_numbers')
77
+ data['address'].delete('zipcode')
78
+ result = deserializer.from_json(json, :include => { 'address' => {:only => ['street']}})
79
+ result.must_equal data
80
+ result = deserializer.from_json(json, :include => ['address'])
81
+ result.must_equal data
82
+ end
83
+
84
+ it 'should serialize and deserialize a hash with nested except' do
85
+ json = serializer.to_json(:include => { 'address' => {:except => ['zipcode']}})
86
+ data.delete('phone_numbers')
87
+ data['address'].delete('zipcode')
88
+ result = deserializer.from_json(json, :include => { 'address' => {:except => ['zipcode']}})
89
+ result.must_equal data
90
+ result = deserializer.from_json(json, :include => ['address'])
91
+ result.must_equal data
92
+ end
93
+
94
+ it 'should serialize and deserialize a hash with nested include' do
95
+ json = serializer.to_json(:include => { 'address' => {}, 'phone_numbers' => { :include => ['area']}})
96
+ result = deserializer.from_json(json, :include => { 'address' => {}, 'phone_numbers' => { :include => ['area']}})
97
+ result.must_equal data
98
+ end
99
+ end