vellam 0.1

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.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ vellam (0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ json_pure (1.6.1)
10
+ minitest (2.11.3)
11
+ rake (0.9.2.2)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ json_pure (~> 1.6.1)
18
+ minitest (= 2.11.3)
19
+ rake (= 0.9.2.2)
20
+ vellam!
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Kristian Meier
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ [![Build Status](https://secure.travis-ci.org/mkristian/babel.png)](http://travis-ci.org/mkristian/babel)
2
+
3
+ # babel #
4
+
5
+ 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.
6
+
7
+ the first problem I had was that I needed serveral options map at different controllers/actions so I needed a place to store them. the model itself felt to be the wrong place.
8
+
9
+ the next problem was that I could include the result of a given method with `:methods => ['age']` but only on the root level of the object tree. but if I wanted to `age` method to be part of the serialization somewhere deep inside the object tree, it is not possible.
10
+
11
+ please have a look at **spec/filter_spec.rb** how to use it :)
data/lib/babel.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'babel/serializer'
2
+ require 'babel/deserializer'
data/lib/babel.rb~ ADDED
@@ -0,0 +1,2 @@
1
+ require 'babel/serializer'
2
+ require 'babel/factory'
@@ -0,0 +1,63 @@
1
+ module Babel
2
+ class Deserializer
3
+
4
+ def initialize(model_class)
5
+ @model_class = model_class
6
+ end
7
+
8
+ private
9
+
10
+ def self.filter
11
+ @filter ||= HashFilter.new
12
+ end
13
+
14
+ def filter
15
+ @filter ||= self.class.filter.dup
16
+ end
17
+
18
+ protected
19
+
20
+ def self.default_context_key(default)
21
+ filter.default_context_key(default)
22
+ end
23
+
24
+ def self.add_context(key, options = {})
25
+ filter[key] = options
26
+ end
27
+
28
+ public
29
+
30
+ def use(context_or_options)
31
+ filter.use(context_or_options)
32
+ self
33
+ end
34
+
35
+ def from_hash(data, options = nil)
36
+ filter.use(options) if options
37
+ if root = filter.options[:root]
38
+ if data.is_a? Array
39
+ root = root.to_s
40
+ data.collect{ |d| @model_class.new(filter.filter(d[root])) }
41
+ else
42
+ @model_class.new(filter.filter(data[root.to_s]))
43
+ end
44
+ else
45
+ if data.is_a? Array
46
+ data.collect{ |d| @model_class.new(filter.filter(d)) }
47
+ else
48
+ @model_class.new(filter.filter(data))
49
+ end
50
+ end
51
+ end
52
+
53
+ def from_json(json, options = nil)
54
+ data = JSON.parse(json)
55
+ from_hash(data, options)
56
+ end
57
+
58
+ def from_yaml(yaml, options = nil)
59
+ data = YAML.load_stream(StringIO.new(yaml)).documents
60
+ from_hash(data, options)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,16 @@
1
+ class Babel::Deserializer
2
+
3
+ def initialize(model_class)
4
+ @model_class = model_class
5
+ end
6
+
7
+ def from_json(json)
8
+ data = JSON.parse(json)
9
+ if data.is_a? Array
10
+ data.collect{ |d| @model_class.new(d) }
11
+ else
12
+ @model_class.new(data)
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,27 @@
1
+ class Babel::Factory
2
+
3
+ def initialize(options = {})
4
+ @options = options
5
+ end
6
+
7
+ def serializer(model_class, serializer_class = nil)
8
+ @serializers[model_class] = serializer_class if serializer_class
9
+ @serializers[model_class] ||= ("#{model_class}Serializer".to_const rescue Babel::Serializer)
10
+ end
11
+
12
+ def deserializer(model_class, deserializer_class = nil)
13
+ @deserializers[model_class] = deserializer_class if deserializer_class
14
+ @serializers[model_class] ||= Deserializer.new(model_class)
15
+ end
16
+
17
+ def to_json(model_or_models, options = {})
18
+ if model_or_models.is_a? Array
19
+ json = model_or_models.collect do |m|
20
+ serializer(m.class).new(m).to_json(@options.merge(options))
21
+ end
22
+ "[#{json.join(',')}]"
23
+ else
24
+ serializer(model_or_models.class).new(model_or_models).to_json(@options.merge(options))
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,126 @@
1
+ module Babel
2
+ class HashFilter
3
+
4
+ def initialize(context_or_options = nil)
5
+ use(context_or_options)
6
+ end
7
+
8
+ private
9
+
10
+ def context
11
+ @context ||= {}
12
+ end
13
+
14
+ public
15
+
16
+ def default_context_key(default = nil)
17
+ @default = default if default
18
+ @default
19
+ end
20
+
21
+ def []=(key, options)
22
+ context[key.to_sym] = options if key
23
+ end
24
+
25
+ def [](key)
26
+ context[key.to_sym] if key
27
+ end
28
+
29
+ def use(context_or_options)
30
+ if context_or_options
31
+ case context_or_options
32
+ when Symbol
33
+ if opts = context[context_or_options]
34
+ @options = opts.dup
35
+ end
36
+ when Hash
37
+ @options = context_or_options
38
+ end
39
+ else
40
+ @options = nil
41
+ end
42
+ self
43
+ end
44
+
45
+ NO_MODEL = Object.new
46
+ def NO_MODEL.send(*args)
47
+ self
48
+ end
49
+
50
+ def filter(hash = {}, model = NO_MODEL, &block)
51
+ filter_data(model, hash, options, &block) if hash
52
+ end
53
+
54
+ def options
55
+ @options || context[default_context_key] || {}
56
+ end
57
+
58
+ private
59
+
60
+ def filter_data(model, data, options = {}, &block)
61
+ only = options[:only].collect { |o| o.to_s } if options[:only]
62
+ except = (options[:except] || []).collect { |e| e.to_s }
63
+
64
+ include =
65
+ case options[:include]
66
+ when Array
67
+ options[:include].collect { |i| i.to_s }
68
+ when Hash
69
+ Hash[options[:include].collect {|k,v| [k.to_s, v]}]
70
+ else
71
+ []
72
+ end
73
+ if model != NO_MODEL
74
+ methods = (options[:methods] || []).collect { |e| e.to_s }
75
+ methods.each do |m|
76
+ data[m] = model.send(m.to_sym)
77
+ end
78
+
79
+ include_methods = include.is_a?(Array) ? include : include.keys
80
+ include_methods.each do |m|
81
+ unless data.include?(m)
82
+ raise "no block given to calculate the attributes from model" unless block
83
+ models_or_model = model.send(m)
84
+ if models_or_model.respond_to?(:collect)
85
+ data[m] = models_or_model.collect { |i| block.call(i) }
86
+ else
87
+ data[m]= block.call(model.send(m))
88
+ end
89
+ end
90
+ end
91
+ end
92
+ methods ||= []
93
+
94
+ result = {}
95
+ data.each do |k,v|
96
+ case v
97
+ when Hash
98
+ if include.include?(k)
99
+ case include
100
+ when Array
101
+ result[k] = filter_data(model.send(k), v, &block)
102
+ when Hash
103
+ result[k] = filter_data(model.send(k), v, include[k], &block)
104
+ end
105
+ end
106
+ when Array
107
+ if include.include?(k)
108
+ models = model.send(k)
109
+ case include
110
+ when Array
111
+ result[k] = v.enum_with_index.collect { |i, j| filter_data(models[j], i, &block) }
112
+ when Hash
113
+ opts = include[k]
114
+ result[k] = v.enum_with_index.collect { |i, j| filter_data(models[j], i, opts, &block) }
115
+ end
116
+ end
117
+ else
118
+ if methods.include?(k) || (only && only.include?(k)) || (only.nil? && !except.include?(k))
119
+ result[k] = v
120
+ end
121
+ end
122
+ end
123
+ result
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,120 @@
1
+ class HashFilter
2
+
3
+ def initialize(flavor = nil)
4
+ use(flavor)
5
+ end
6
+
7
+ private
8
+
9
+ def context
10
+ @context ||= {}
11
+ end
12
+
13
+ public
14
+
15
+ def default_key(default = nil)
16
+ @default = default if default
17
+ @default
18
+ end
19
+
20
+ def []=(key, options)
21
+ context[key.to_sym] = options if key
22
+ end
23
+
24
+ def [](key)
25
+ context[key.to_sym] if key
26
+ end
27
+
28
+ def use(context_or_options)
29
+ case context_or_options
30
+ when Symbol
31
+ if opts = context[context_or_options]
32
+ @options = opts.dup
33
+ end
34
+ when Hash
35
+ @options = context_or_options
36
+ end
37
+ self
38
+ end
39
+
40
+ NO_MODEL = Object.new
41
+ def NO_MODEL.send(*args)
42
+ self
43
+ end
44
+
45
+ def filter(params = {}, model = NO_MODEL, &block)
46
+ filter_data(model, params, options, &block) if params
47
+ end
48
+
49
+ def options
50
+ @options || context[default_key] || {}
51
+ end
52
+
53
+ private
54
+
55
+ def filter_data(model, data, options = {}, &block)
56
+ only = options[:only].collect { |o| o.to_s } if options[:only]
57
+ except = (options[:except] || []).collect { |e| e.to_s }
58
+
59
+ include =
60
+ case options[:include]
61
+ when Array
62
+ options[:include].collect { |i| i.to_s }
63
+ when Hash
64
+ Hash[options[:include].collect {|k,v| [k.to_s, v]}]
65
+ else
66
+ []
67
+ end
68
+ if model != NO_MODEL
69
+ methods = (options[:methods] || []).collect { |e| e.to_s }
70
+ methods.each do |m|
71
+ data[m] = model.send(m.to_sym)
72
+ end
73
+
74
+ include_methods = include.is_a?(Array) ? include : include.keys
75
+ include_methods.each do |m|
76
+ unless data.include?(m)
77
+ raise "no block given to calculate the attributes from model" unless block
78
+ models_or_model = model.send(m)
79
+ if models_or_model.respond_to?(:collect)
80
+ data[m] = models_or_model.collect { |i| block.call(i) }
81
+ else
82
+ data[m]= block.call(model.send(m))
83
+ end
84
+ end
85
+ end
86
+ end
87
+ methods ||= []
88
+
89
+ result = {}
90
+ data.each do |k,v|
91
+ case v
92
+ when Hash
93
+ if include.include?(k)
94
+ case include
95
+ when Array
96
+ result[k] = filter_data(model.send(k), v, &block)
97
+ when Hash
98
+ result[k] = filter_data(model.send(k), v, include[k], &block)
99
+ end
100
+ end
101
+ when Array
102
+ if include.include?(k)
103
+ models = model.send(k)
104
+ case include
105
+ when Array
106
+ result[k] = v.enum_with_index.collect { |i, j| filter_data(models[j], i, &block) }
107
+ when Hash
108
+ opts = include[k]
109
+ result[k] = v.enum_with_index.collect { |i, j| filter_data(models[j], i, opts, &block) }
110
+ end
111
+ end
112
+ else
113
+ if methods.include?(k) || (only && only.include?(k)) || (only.nil? && !except.include?(k))
114
+ result[k] = v
115
+ end
116
+ end
117
+ end
118
+ result
119
+ end
120
+ end
@@ -0,0 +1,102 @@
1
+ require 'babel/hash_filter'
2
+ module Babel
3
+ class Serializer
4
+
5
+ def initialize(model_or_models)
6
+ @model_or_models = model_or_models
7
+ end
8
+
9
+ def respond_to?(method)
10
+ @model_or_models.respond_to?(method)
11
+ end
12
+
13
+ def method_missing(method, *args, &block)
14
+ @model_or_models.send(method, *args, &block)
15
+ end
16
+
17
+ private
18
+
19
+ def self.filter
20
+ @filter ||= HashFilter.new
21
+ end
22
+
23
+ def filter
24
+ @filter ||= self.class.filter.dup
25
+ end
26
+
27
+ protected
28
+
29
+ # for rails
30
+ def self.model(model = nil)
31
+ @model_class = model if model
32
+ @model_class ||= self.to_s.sub(/Serializer$/, '').constantize
33
+ end
34
+
35
+ # for rails
36
+ def self.model_name
37
+ model.model_name
38
+ end
39
+
40
+ def self.default_context_key(default)
41
+ filter.default_context_key(default)
42
+ end
43
+
44
+ def self.add_context(key, options = {})
45
+ filter[key] = options
46
+ end
47
+
48
+ public
49
+
50
+ def use(context_or_options)
51
+ filter.use(context_or_options)
52
+ self
53
+ end
54
+
55
+ def to_hash(options = nil)
56
+ filter.use(options) if options
57
+ case @model_or_models
58
+ when Array
59
+ @model_or_models.collect do |m|
60
+ filter_model(attr(m), m)
61
+ end
62
+ else
63
+ filter_model(attr(@model_or_models), @model_or_models)
64
+ end
65
+ end
66
+
67
+ def to_json(options = nil)
68
+ to_hash(options).to_json
69
+ end
70
+
71
+ def to_xml(options = nil)
72
+ opts = fitler.options.dup
73
+ root = opts.delete :root
74
+ fitler.use(opts)
75
+ result = to_hash
76
+ if root && result.is_a?(Array) && root.respond_to?(:pluralize)
77
+ root = root.to_s.pluralize
78
+ end
79
+ result.to_xml :root => root
80
+ end
81
+
82
+ def to_yaml(options = nil)
83
+ to_hash(options).to_yaml
84
+ end
85
+
86
+ protected
87
+
88
+ def attr(model)
89
+ model.attributes if model
90
+ end
91
+
92
+ private
93
+
94
+ def filter_model(model, data)
95
+ if root = filter.options[:root]
96
+ {root.to_s => filter.filter(model, data){ |model| attr(model) } }
97
+ else
98
+ filter.filter(model, data){ |model| attr(model) }
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,101 @@
1
+ require 'hash_filter'
2
+ class Serializer
3
+
4
+ def initialize(model_or_models)
5
+ @model_or_models = model_or_models
6
+ end
7
+
8
+ def respond_to?(method)
9
+ @model_or_models.respond_to?(method)
10
+ end
11
+
12
+ def method_missing(method, *args, &block)
13
+ @model_or_models.send(method, *args, &block)
14
+ end
15
+
16
+ private
17
+
18
+ def self.filter
19
+ @filter ||= HashFilter.new
20
+ end
21
+
22
+ def filter
23
+ self.class.filter
24
+ end
25
+
26
+ def self.views
27
+ @views ||= {}
28
+ end
29
+
30
+ protected
31
+
32
+ def self.model(model = nil)
33
+ @model_class = model if model
34
+ @model_class ||= self.to_s.sub(/Presenter$/, '').constantize
35
+ end
36
+
37
+ def self.model_name
38
+ model.model_name
39
+ end
40
+
41
+ def self.default(default)
42
+ filter.default_key(default)
43
+ end
44
+
45
+ def self.add_view(key, options = {})
46
+ filter[key] = options
47
+ end
48
+
49
+ public
50
+
51
+ def use(flavor)
52
+ filter.use(flavor)
53
+ self
54
+ end
55
+
56
+ def to_hash(options = nil)
57
+ case @model_or_models
58
+ when Array
59
+ @model_or_models.collect do |m|
60
+ filter_model(attr(m), m)
61
+ end
62
+ else
63
+ filter_model(attr(@model_or_models), @model_or_models)
64
+ end
65
+ end
66
+
67
+ def to_json(options = nil)
68
+ to_hash(options).to_json
69
+ end
70
+
71
+ def to_xml(options = nil)
72
+ opts = fitler.options.dup
73
+ root = opts.delete :root
74
+ fitler.use(opts)
75
+ result = to_hash
76
+ if root && result.is_a?(Array) && root.respond_to?(:pluralize)
77
+ root = root.to_s.pluralize
78
+ end
79
+ result.to_xml :root => root
80
+ end
81
+
82
+ def to_yaml(options = nil)
83
+ to_hash(options).to_yaml
84
+ end
85
+
86
+ protected
87
+
88
+ def attr(model)
89
+ model.attributes if model
90
+ end
91
+
92
+ private
93
+
94
+ def filter_model(model, data)
95
+ if root = filter.options[:root]
96
+ {root.to_s => filter.filter(model, data){ |model| attr(model) } }
97
+ else
98
+ filter.filter(model, data){ |model| attr(model) }
99
+ end
100
+ end
101
+ 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 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) { Babel::Serializer.new(data) }
37
+ let(:deserializer) { 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,89 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+ $LOAD_PATH << File.expand_path(File.join(__FILE__, '..', '..', 'lib'))
3
+
4
+ require 'spec_helper'
5
+ require 'babel'
6
+
7
+ describe Babel::Serializer do
8
+ before do
9
+ @data = {
10
+ 'id' => 987,
11
+ 'name' => 'me and the corner',
12
+ 'address' => { 'street' => 'Foo 12', 'zipcode' => '12345' },
13
+ 'phone_numbers' => {
14
+ 'prefix' => 12,
15
+ 'number' => '123',
16
+ 'area' => { 'code' => '001', 'iso' => 'us'}
17
+ }
18
+ }
19
+ # make the hash behave like a model
20
+ def @data.to_hash
21
+ self
22
+ end
23
+ class Hash
24
+ def self.new(hash)
25
+ self[hash]
26
+ end
27
+ end
28
+ end
29
+
30
+ it 'should serialize and deserialize a hash' do
31
+ json_data = Babel::Serializer.new(@data)
32
+ json = json_data.to_json
33
+ data = Babel::Factory.from_json(Hash, json)
34
+ data.must_equal Hash['id' => @data['id'], 'name' => @data['name']]
35
+ end
36
+
37
+ it 'should serialize and deserialize a hash with root' do
38
+ json_data = Babel::Serializer.new(@data)
39
+ json = json_data.to_json :root => :my
40
+ data = Babel::Factory.from_json(Hash, json)
41
+ data['my'].must_equal Hash['id' => @data['id'], 'name' => @data['name']]
42
+ end
43
+
44
+ it 'should serialize and deserialize a hash with include list' do
45
+ json_data = Babel::Serializer.new(@data)
46
+ json = json_data.to_json(:include => ['address', 'phone_numbers'])
47
+ data = Babel::Factory.from_json(Hash, json)
48
+ @data['phone_numbers'].delete('area')
49
+ data.must_equal Hash[@data]
50
+ end
51
+
52
+ it 'should serialize and deserialize a hash with except' do
53
+ json_data = Babel::Serializer.new(@data)
54
+ json = json_data.to_json(:except => ['id'])
55
+ data = Babel::Factory.from_json(Hash, json)
56
+ data.must_equal Hash['name' => @data['name']]
57
+ end
58
+
59
+ it 'should serialize and deserialize a hash with only' do
60
+ json_data = Babel::Serializer.new(@data)
61
+ json = json_data.to_json(:only => ['name'])
62
+ data = Babel::Factory.from_json(Hash, json)
63
+ data.must_equal Hash['name' => @data['name']]
64
+ end
65
+
66
+ it 'should serialize and deserialize a hash with nested only' do
67
+ json_data = Babel::Serializer.new(@data)
68
+ json = json_data.to_json(:include => { 'address' => {:only => ['street']}})
69
+ data = Babel::Factory.from_json(Hash, json)
70
+ @data.delete('phone_numbers')
71
+ @data['address'].delete('zipcode')
72
+ data.must_equal @data
73
+ end
74
+ it 'should serialize and deserialize a hash with nested except' do
75
+ json_data = Babel::Serializer.new(@data)
76
+ json = json_data.to_json(:include => { 'address' => {:except => ['zipcode']}})
77
+ data = Babel::Factory.from_json(Hash, json)
78
+ @data.delete('phone_numbers')
79
+ @data['address'].delete('zipcode')
80
+ data.must_equal @data
81
+ end
82
+
83
+ it 'should serialize and deserialize a hash with nested include' do
84
+ json_data = Babel::Serializer.new(@data)
85
+ json = json_data.to_json(:include => { 'address' => {}, 'phone_numbers' => { :include => ['area']}})
86
+ data = Babel::Factory.from_json(Hash, json)
87
+ data.must_equal @data
88
+ end
89
+ end
data/spec/resty.rb~ ADDED
@@ -0,0 +1,76 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+ $LOAD_PATH << File.expand_path(File.join(__FILE__, '..', '..', 'lib'))
3
+
4
+ require 'spec_helper'
5
+ require 'babel'
6
+
7
+ class Babel::RemoteService
8
+
9
+ def initialize(url, options = {})
10
+ @url = url
11
+ @options = options
12
+ @urls = []
13
+ end
14
+
15
+ def resource(subject_class)
16
+ Resource.new(subject_class, url(subject_class), @options)
17
+ end
18
+
19
+ def url(subject_class, path = nil)
20
+ @urls[subject_class] = "#{@url}/#{path}" if path
21
+ @urls[subject_class] || "#{@url}/#{subject_class.to_s.downcase}s"
22
+ end
23
+ end
24
+
25
+ class Babel::Resource
26
+
27
+ def initialize(subject_class, url, options = {})
28
+ @options = options.dup
29
+ @options[:accept] ||= :json
30
+ @factory = Factory.new(subject_class)
31
+ @resource = RestClient::Resource.new(url:, @options)
32
+ end
33
+
34
+ def member_resource(model_or_id)
35
+ id = case model_or_id
36
+ when String
37
+ model_or_id
38
+ when Fixnum
39
+ model_or_id.to_s
40
+ else
41
+ model_or_id.id.to_s
42
+ end
43
+ @resource[id]
44
+ end
45
+
46
+ def get(model_or_params)
47
+ case model_or_params
48
+ when Hash
49
+ @resource.get(:params => model_or_params) do |res|
50
+ @factory.from_json(res)
51
+ end
52
+ else
53
+ model_resource(model_or_params).get do |res|
54
+ @factory.from_json(res)
55
+ end
56
+ end
57
+ end
58
+
59
+ def post(model)
60
+ member_resource(model).post(@factory.to_json(model)) do |res|
61
+ @factory.from_json(res)
62
+ end
63
+ end
64
+
65
+ def put(model)
66
+ member_resource(model).put(@factory.to_json(model)) do |res|
67
+ @factory.from_json(res)
68
+ end
69
+ end
70
+
71
+ def delete(model)
72
+ member_resource(model).delete( @factory.to_json(model))
73
+ end
74
+ end
75
+
76
+ user_service.resource(User).get
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH << File.expand_path(File.join(__FILE__, '..', '..', 'lib'))
2
+ require 'minitest/autorun'
3
+ require 'json'
4
+ require 'babel'
@@ -0,0 +1 @@
1
+ require 'minitest/autorun'
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vellam
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Kristian Meier
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-05-12 00:00:00 Z
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rake
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - "="
26
+ - !ruby/object:Gem::Version
27
+ hash: 11
28
+ segments:
29
+ - 0
30
+ - 9
31
+ - 2
32
+ - 2
33
+ version: 0.9.2.2
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: json_pure
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 13
45
+ segments:
46
+ - 1
47
+ - 6
48
+ - 1
49
+ version: 1.6.1
50
+ type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: minitest
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - "="
59
+ - !ruby/object:Gem::Version
60
+ hash: 37
61
+ segments:
62
+ - 2
63
+ - 11
64
+ - 3
65
+ version: 2.11.3
66
+ type: :development
67
+ version_requirements: *id003
68
+ description: babel offers a filter for hashes and with that comes json/yaml/xml de/serialization of models which provides a hash representationi. possible models are activerecord, activemodel, resources from datamapper, virtus
69
+ email:
70
+ - m.kristian@web.de
71
+ executables: []
72
+
73
+ extensions: []
74
+
75
+ extra_rdoc_files: []
76
+
77
+ files:
78
+ - lib/babel.rb~
79
+ - lib/babel/deserializer.rb
80
+ - lib/babel/hash_filter.rb
81
+ - lib/babel/serializer.rb~
82
+ - lib/babel/deserializer.rb~
83
+ - lib/babel/hash_filter.rb~
84
+ - lib/babel/factory.rb~
85
+ - lib/babel/serializer.rb
86
+ - lib/babel.rb
87
+ - spec/spec_helper.rb~
88
+ - spec/spec_helper.rb
89
+ - spec/resty.rb~
90
+ - spec/filter_spec.rb
91
+ - spec/filter_spec.rb~
92
+ - MIT-LICENSE
93
+ - README.md
94
+ - Gemfile
95
+ - Gemfile.lock
96
+ homepage: https://github.com/mkristian/babel
97
+ licenses: []
98
+
99
+ post_install_message:
100
+ rdoc_options: []
101
+
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 3
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ hash: 3
119
+ segments:
120
+ - 0
121
+ version: "0"
122
+ requirements: []
123
+
124
+ rubyforge_project:
125
+ rubygems_version: 1.8.21
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: babel offers a filter for hashes and with that comes json/yaml/xml de/serialization of models which provides a hash representation
129
+ test_files:
130
+ - spec/filter_spec.rb