vellam 0.1

Sign up to get free protection for your applications and to get access to all the features.
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