serialbox 1.0.0

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.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.8.7@serialbox --create
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source :rubygems
2
+
3
+ gem 'json'
4
+ gem 'activesupport'
5
+
6
+ group :development do
7
+ # SPECS
8
+ gem 'rspec'
9
+
10
+ # DOCS
11
+ gem 'yard'
12
+ gem 'redcarpet'
13
+
14
+ # DEVELOPMENT
15
+ gem 'bundler'
16
+ gem 'jeweler'
17
+ end
@@ -0,0 +1,41 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.10)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ diff-lcs (1.1.3)
8
+ git (1.2.5)
9
+ i18n (0.6.1)
10
+ jeweler (1.8.4)
11
+ bundler (~> 1.0)
12
+ git (>= 1.2.5)
13
+ rake
14
+ rdoc
15
+ json (1.7.6)
16
+ multi_json (1.5.0)
17
+ rake (10.0.3)
18
+ rdoc (3.12)
19
+ json (~> 1.4)
20
+ redcarpet (2.2.2)
21
+ rspec (2.12.0)
22
+ rspec-core (~> 2.12.0)
23
+ rspec-expectations (~> 2.12.0)
24
+ rspec-mocks (~> 2.12.0)
25
+ rspec-core (2.12.2)
26
+ rspec-expectations (2.12.1)
27
+ diff-lcs (~> 1.1.3)
28
+ rspec-mocks (2.12.1)
29
+ yard (0.8.3)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ activesupport
36
+ bundler
37
+ jeweler
38
+ json
39
+ redcarpet
40
+ rspec
41
+ yard
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Tim Morgan
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.
@@ -0,0 +1,100 @@
1
+ # SerialBox
2
+
3
+ Provides a simple, well-defined way to specify how your objects are serialized
4
+ and deserialized into primitive types (say, for JSON serialization). Here's an
5
+ example object:
6
+
7
+ ```` ruby
8
+ class Car
9
+ attr_accessor :seats, :color
10
+
11
+ include SerialBox
12
+ serialize_with :JSON
13
+ serialize_fields do |s|
14
+ s.serialize :seats
15
+ s.serialize :color
16
+ end
17
+ end
18
+ ````
19
+
20
+ By calling `serialize_with :JSON`, your class now gets `#to_json`, `#as_json`,
21
+ and `.json_create` methods making it work seamlessly with the `json` gem. If you
22
+ have more complicated data structures or accessors, this gem works with that
23
+ too:
24
+
25
+ ```` ruby
26
+ class Color
27
+ attr_accessor :r, :g, :b
28
+
29
+ include SerialBox
30
+ serialize_with :JSON
31
+ serialize_fields do |s|
32
+ s.serialize :r, :g, :b
33
+ end
34
+ end
35
+
36
+ class Car
37
+ attr_accessor :color # string
38
+
39
+ include SerialBox
40
+ serialize_with :JSON
41
+ serialize_fields do |s|
42
+ s.serializer 'color', :get_color
43
+ s.deserializer 'color', :set_color
44
+ end
45
+
46
+ def get_color
47
+ if color.r == 255 && color.g == 0 && color.b == 0
48
+ 'red'
49
+ elsif color.r == 0 && color.g == 255 && color.b == 0
50
+ 'green'
51
+ elsif color.r == 0 && color.g == 0 && color.b == 255
52
+ 'blue'
53
+ end
54
+ end
55
+
56
+ def set_color(name)
57
+ case name
58
+ when 'red' then Color.new(255, 0, 0)
59
+ when 'green' then Color.new(0, 255, 0)
60
+ when 'blue' then Color.new(0, 0, 255)
61
+ end
62
+ end
63
+ end
64
+ ````
65
+
66
+ The `.serialize_fields` method lets you define serializers and deserializers
67
+ using simple to complex syntax, depending on your needs. Here are the supported
68
+ syntaxes:
69
+
70
+ ```` ruby
71
+ serialize_fields do |s|
72
+ s.serialize :foo # uses #foo and #foo=, JSON field named "foo"
73
+ s.serialize :foo, :into => 'bar' # uses #foo and #foo=, JSON field named "bar"
74
+ s.serialize :@foo # reads and writes directly using @foo
75
+
76
+ s.serializer 'foo', :bar # the JSON field "foo" will have the value returned by #bar
77
+ s.deserializer 'foo', :bar= # the value in JSON field "foo" will be sent to #bar=
78
+
79
+ s.serializer('foo') { bar.to_s } # the JSON field "foo" will have the value returned by the block
80
+ s.deserializer('foo') { |value| self.bar = value.to_sym } # the block will be passed the value stored in JSON field "foo"; you must write it to your object
81
+ end
82
+ ````
83
+
84
+ **Important Note:** Right now the only serializer implemented is `:JSON`. Other
85
+ serializers should be easy to write by following its example.
86
+
87
+ ## Installation
88
+
89
+ To use, add this gem to your Gemfile:
90
+
91
+ ```` ruby
92
+ gem 'serialbox'
93
+ ````
94
+
95
+ then include the `SerialBox` module in your class, following one of the examples
96
+ above.
97
+
98
+ ## Documentation
99
+
100
+ Comprehensive documentation is available by running `rake doc`.
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "serialbox"
18
+ gem.homepage = "http://github.com/riscfuture/serialbox"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Define how your object is serialized and deserialized, and this gem handles the rest.}
21
+ gem.description = %Q{This gem allows you to define how your object is serialized and deserialized. Then it's a simple matter of telling it which formats you want to support, and the serialization methods are automatically created for you.}
22
+ gem.email = "rubygems@timothymorgan.info"
23
+ gem.authors = ["Tim Morgan"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ task :default => :spec
35
+
36
+ require 'yard'
37
+
38
+ # bring sexy back (sexy == tables)
39
+ module YARD::Templates::Helpers::HtmlHelper
40
+ def html_markup_markdown(text)
41
+ markup_class(:markdown).new(text, :gh_blockcode, :fenced_code, :autolink, :tables).to_html
42
+ end
43
+ end
44
+
45
+ YARD::Rake::YardocTask.new('doc') do |doc|
46
+ doc.options << '-m' << 'markdown' << '-M' << 'redcarpet'
47
+ doc.options << '--protected' << '--no-private'
48
+ doc.options << '-r' << 'README.md'
49
+ doc.options << '-o' << 'doc'
50
+ doc.options << '--title' << "SerialBox Documentation"
51
+
52
+ doc.files = %w( lib/**/*.rb README.md )
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,191 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/array/extract_options'
3
+ Dir.glob(File.dirname(__FILE__) + '/serializers/*').each { |f| require f }
4
+
5
+ # Mixin that adds the ability for you to define a serializable representation of
6
+ # your object. `include` this module into your class and call
7
+ # {ClassMethods#serialize_fields} and {ClassMethods#serialize_with} to
8
+ # configure.
9
+
10
+ module SerialBox
11
+ extend ActiveSupport::Concern
12
+
13
+ # Methods added to the class that this module is mixed into.
14
+
15
+ module ClassMethods
16
+
17
+ # Call this method to define how your object is serialized. This method
18
+ # yields an object on which you call methods to define your serialization.
19
+ #
20
+ # @yield [serializer] A block where you can define how your object is
21
+ # serialized.
22
+ # @yieldparam [SerialBox::Serializer] serializer An object you can use to
23
+ # define your serialization strategy.
24
+
25
+ def serialize_fields
26
+ @_serialbox_serializer = Serializer.new(self)
27
+ yield @_serialbox_serializer
28
+ end
29
+
30
+ # @overload serialize_with(serializer, ...)
31
+ # Call this method to specify which serialization formats to use.
32
+ #
33
+ # @param [Symbol, Class] serializer A serialization format adapter or the
34
+ # name of such adapter under the `SerialBox::Serializers` namespace. See
35
+ # the classes under {SerialBox::Serializers} for a list of possible
36
+ # values.
37
+
38
+ def serialize_with(*serializers)
39
+ serializers.map! do |s|
40
+ case s
41
+ when Class
42
+ s
43
+ when Symbol, String
44
+ SerialBox::Serializers.const_get(s.to_sym)
45
+ else
46
+ raise ArgumentError, "Unknown serializer #{s.inspect}"
47
+ end
48
+ end
49
+
50
+ serializers.each { |serializer| include serializer }
51
+ end
52
+
53
+ # @private
54
+ def _serialbox_serializer() @_serialbox_serializer end
55
+ end
56
+
57
+
58
+ # An object that is used to define how a class is serialized. The methods of
59
+ # this object can be called within a block given to
60
+ # {SerialBox::ClassMethods#serialize_fields}.
61
+
62
+ class Serializer
63
+ # @private
64
+ attr_reader :serialization_operations, :deserialization_operations, :object
65
+
66
+ # @private
67
+ def initialize(object)
68
+ @serialization_operations = Array.new
69
+ @deserialization_operations = Array.new
70
+ @object = object
71
+ end
72
+
73
+ # @overload serialize(field, ..., options={})
74
+ #
75
+ # Specifies that one or more fields should be serialized in the most
76
+ # obvious manner. This is suitable when serializing a simple getter/setter
77
+ # pair or an instance variable.
78
+ #
79
+ # @param [Symbol] field The name of a method (or instance variable with
80
+ # "@" sigil) that will be serialized.
81
+ # @param [Hash] options Additional options controlling how the field is
82
+ # serialized.
83
+ # @option options [String] :into If given, specifies that the field should
84
+ # be serialized into a key with a different name. Can only be provided
85
+ # if a single field is given.
86
+
87
+ def serialize(*fields)
88
+ options = fields.extract_options!
89
+ if options[:into] && fields.size > 1
90
+ raise ArgumentError, "Can't specify :into option with multiple fields"
91
+ end
92
+
93
+ fields.each do |field|
94
+ if field.to_s[0, 1] == '@'
95
+ field = field.to_s[1..-1]
96
+ json_field = options[:into] || field
97
+ serializer(json_field) { instance_variable_get :"@#{field}" }
98
+ deserializer(json_field) { |value| instance_variable_set :"@#{field}", value }
99
+ else
100
+ json_field = options[:into] || field
101
+ serializer json_field, field
102
+ deserializer json_field, :"#{field}="
103
+ end
104
+ end
105
+ end
106
+
107
+ # Defines how a field is handled when an object is prepared for
108
+ # serialization.
109
+ #
110
+ # @overload serializer(json_field, object_method)
111
+ # Specifies that the method `object_method` should be called and its
112
+ # result should be stored in a field named `json_field` as part of
113
+ # serialization.
114
+ # @param [String] json_field The field to store the resulting value in.
115
+ # @param [Symbol] object_method The method to call to retrieve a value.
116
+ #
117
+ # @overload serializer(json_field)
118
+ # Specifies that a block should be called in the context of the instance
119
+ # being serialized, and the result should be stored in a field named
120
+ # `json_field`.
121
+ # @param [String] json_field The field to store the resulting value in in
122
+ # the JSON representation.
123
+ # @yield A block that returns the value to serialize.
124
+ # @yieldreturn The value to serialize into `json_field`.
125
+
126
+ def serializer(json_field, object_method=nil, &block)
127
+ if block_given?
128
+ @serialization_operations << BlockSerialization.new(json_field, block)
129
+ elsif object_method
130
+ @serialization_operations << BlockSerialization.new(json_field, lambda { send object_method })
131
+ else
132
+ raise ArgumentError, "Must provide the name of a method or a block that returns a value to serialize"
133
+ end
134
+ end
135
+
136
+ # Defines how a field is handled when an object is deserialized from its
137
+ # primitive representation.
138
+ #
139
+ # @overload deserializer(json_field, object_method)
140
+ # Specifies that the value in `json_field` should be passed to
141
+ # `object_method` during deserialization.
142
+ # @param [String] json_field The field to retrieve the value from.
143
+ # @param [Symbol] object_method The method to call to store the value
144
+ # into the object.
145
+ #
146
+ # @overload deserializer(json_field)
147
+ # Specifies that the value stored in `json_field` should be passed to the
148
+ # block provided, which will store that value into the object being
149
+ # deserialized.
150
+ # @param [String] json_field The field to retrieve the value from in the
151
+ # JSON representation.
152
+ # @yield [value] A block that stores the value into the object. This block
153
+ # is executed in the context of the object.
154
+ # @yieldparam value The value to store.
155
+
156
+ def deserializer(json_field, object_method=nil, &block)
157
+ if block_given?
158
+ @deserialization_operations << BlockDeserialization.new(json_field, block, object)
159
+ elsif object_method
160
+ @deserialization_operations << BlockDeserialization.new(json_field, lambda { |value| send object_method, value }, object)
161
+ else
162
+ raise ArgumentError, "Must provide the name of a method or a block that sets a field from a deserialized value"
163
+ end
164
+ end
165
+
166
+ # @private
167
+ class BlockSerialization
168
+ def initialize(field, block)
169
+ @field = field
170
+ @block = block
171
+ end
172
+
173
+ def apply(caller, json)
174
+ json[@field] = caller.instance_eval(&@block)
175
+ end
176
+ end
177
+
178
+ # @private
179
+ class BlockDeserialization
180
+ def initialize(field, block, klass)
181
+ @field = field
182
+ @method_name = "_block_deserialization_#{object_id}"
183
+ klass.send :define_method, @method_name, &block
184
+ end
185
+
186
+ def apply(caller, json)
187
+ caller.send @method_name, json[@field.to_s]
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,65 @@
1
+ require 'json'
2
+
3
+ module SerialBox
4
+
5
+ # Container module for all {SerialBox} serializers.
6
+
7
+ module Serializers
8
+
9
+ # JSON adapter for {SerialBox}. Defines the following methods when included
10
+ # in a class:
11
+ #
12
+ # * `#as_json`
13
+ # * `#to_json`
14
+ # * `.json_create`
15
+ #
16
+ # This gives the class total ability to work with `JSON.parse` and
17
+ # `#to_json`.
18
+
19
+ module JSON
20
+ extend ActiveSupport::Concern
21
+
22
+ # @private
23
+ JSON_CREATE_ID = JSON.respond_to?(:create_id) ? JSON.create_id : 'json_class'
24
+
25
+ # Converts this object into primitives suitable for JSON serialization.
26
+ #
27
+ # @return [Hash, Array] A JSON-serializable object.
28
+
29
+ def as_json(*)
30
+ hsh = {SerialBox::Serializers::JSON::JSON_CREATE_ID => self.class.name}
31
+ self.class._serialbox_serializer.serialization_operations.each do |operation|
32
+ operation.apply self, hsh
33
+ end
34
+ return hsh
35
+ end
36
+
37
+ # Serializes this object as JSON.
38
+ #
39
+ # @return [String] The JSON representation of this object.
40
+
41
+ def to_json(*args) as_json.to_json(*args) end
42
+
43
+ module ClassMethods
44
+
45
+ # Converts a primitive object (deserialized from JSON) into an instance
46
+ # of this class.
47
+ #
48
+ # **Note:** You should not call this method directly. You should use
49
+ # `JSON.parse` to ensure recursive deserialization works properly.
50
+ #
51
+ # @param [Array, Hash] object The JSON-ready primitive represnetation of
52
+ # an instance of this class.
53
+ # @return An instance of this class derived from the JSON.
54
+
55
+ def json_create(object)
56
+ instance = allocate
57
+ _serialbox_serializer.deserialization_operations.each do |operation|
58
+ operation.apply instance, object
59
+ end
60
+ return instance
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,70 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "serialbox"
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tim Morgan"]
12
+ s.date = "2013-01-08"
13
+ s.description = "This gem allows you to define how your object is serialized and deserialized. Then it's a simple matter of telling it which formats you want to support, and the serialization methods are automatically created for you."
14
+ s.email = "rubygems@timothymorgan.info"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ ".rvmrc",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.md",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "lib/serialbox.rb",
30
+ "lib/serializers/json.rb",
31
+ "spec/json_spec.rb",
32
+ "spec/spec_helper.rb"
33
+ ]
34
+ s.homepage = "http://github.com/riscfuture/serialbox"
35
+ s.licenses = ["MIT"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = "1.8.24"
38
+ s.summary = "Define how your object is serialized and deserialized, and this gem handles the rest."
39
+
40
+ if s.respond_to? :specification_version then
41
+ s.specification_version = 3
42
+
43
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
+ s.add_runtime_dependency(%q<json>, [">= 0"])
45
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
46
+ s.add_development_dependency(%q<rspec>, [">= 0"])
47
+ s.add_development_dependency(%q<yard>, [">= 0"])
48
+ s.add_development_dependency(%q<redcarpet>, [">= 0"])
49
+ s.add_development_dependency(%q<bundler>, [">= 0"])
50
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
51
+ else
52
+ s.add_dependency(%q<json>, [">= 0"])
53
+ s.add_dependency(%q<activesupport>, [">= 0"])
54
+ s.add_dependency(%q<rspec>, [">= 0"])
55
+ s.add_dependency(%q<yard>, [">= 0"])
56
+ s.add_dependency(%q<redcarpet>, [">= 0"])
57
+ s.add_dependency(%q<bundler>, [">= 0"])
58
+ s.add_dependency(%q<jeweler>, [">= 0"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<json>, [">= 0"])
62
+ s.add_dependency(%q<activesupport>, [">= 0"])
63
+ s.add_dependency(%q<rspec>, [">= 0"])
64
+ s.add_dependency(%q<yard>, [">= 0"])
65
+ s.add_dependency(%q<redcarpet>, [">= 0"])
66
+ s.add_dependency(%q<bundler>, [">= 0"])
67
+ s.add_dependency(%q<jeweler>, [">= 0"])
68
+ end
69
+ end
70
+
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ generate_tester_classes 'JSON', :JSON
4
+
5
+ describe SerialBox::Serializers::JSON do
6
+ context "[basic schema]" do
7
+ it "should serialize using #serialize with a method" do
8
+ obj = JSONSerializeMethodTester.new('value')
9
+ JSON.parse(obj.to_json, :create_additions => false).should eql({'json_class' => 'JSONSerializeMethodTester', 'var' => 'value'})
10
+
11
+ obj = JSON.parse('{"json_class":"JSONSerializeMethodTester","var":"value"}')
12
+ obj.var.should eql('value')
13
+ end
14
+
15
+ it "should serialize using #serialize with an instance variable" do
16
+ obj = JSONSerializeIvarTester.new('value')
17
+ JSON.parse(obj.to_json, :create_additions => false).should eql({'json_class' => 'JSONSerializeIvarTester', 'var' => 'value'})
18
+
19
+ obj = JSON.parse('{"json_class":"JSONSerializeIvarTester","var":"value"}')
20
+ obj.instance_variable_get(:@var).should eql('value')
21
+ end
22
+
23
+ it "should serialize into a custom JSON key" do
24
+ obj = JSONSerializeIntoTester.new('value')
25
+ JSON.parse(obj.to_json, :create_additions => false).should eql({'json_class' => 'JSONSerializeIntoTester', 'custom' => 'value'})
26
+
27
+ obj = JSON.parse('{"json_class":"JSONSerializeIntoTester","custom":"value"}')
28
+ obj.var.should eql('value')
29
+ end
30
+
31
+ it "should serialize using #serializer and #deserializer with object methods" do
32
+ obj = JSONSerializerMethodTester.new('value')
33
+ JSON.parse(obj.to_json, :create_additions => false).should eql({'json_class' => 'JSONSerializerMethodTester', 'var_json' => 'value'})
34
+
35
+ obj = JSON.parse('{"json_class":"JSONSerializerMethodTester","var_json":"value"}')
36
+ obj.var_getter.should eql('value')
37
+ end
38
+
39
+ it "should serialize using #serializer and #deserializer with blocks" do
40
+ obj = JSONSerializerBlockTester.new('value')
41
+ JSON.parse(obj.to_json, :create_additions => false).should eql({'json_class' => 'JSONSerializerBlockTester', 'var_json' => 'value'})
42
+
43
+ obj = JSON.parse('{"json_class":"JSONSerializerBlockTester","var_json":"value"}')
44
+ obj.instance_variable_get(:@var).should eql('value')
45
+ end
46
+ end
47
+
48
+ context "[sub-objects]" do
49
+ it "should correctly serialize and deserialize sub-objects" do
50
+ subobj = JSONSerializeMethodTester.new('value')
51
+ obj = JSONSerializeMethodTester.new(subobj)
52
+ JSON.parse(obj.to_json, :create_additions => false).should eql({
53
+ 'json_class' => 'JSONSerializeMethodTester',
54
+ 'var' => {'json_class' => 'JSONSerializeMethodTester',
55
+ 'var' => 'value'}})
56
+
57
+ obj = JSON.parse('{"json_class":"JSONSerializeMethodTester","var":{"json_class":"JSONSerializeMethodTester","var":"value"}}')
58
+ obj.var.should be_kind_of(JSONSerializeMethodTester)
59
+ obj.var.var.should eql('value')
60
+ end
61
+
62
+ it "should correctly serialize and deserialize special objects in generic objects" do
63
+ obj = [JSONSerializeMethodTester.new('value')]
64
+ JSON.parse(obj.to_json, :create_additions => false).should eql([{'json_class' => 'JSONSerializeMethodTester',
65
+ 'var' => 'value'}])
66
+
67
+ obj = JSON.parse('[{"json_class":"JSONSerializeMethodTester","var":"value"}]')
68
+ obj.should be_kind_of(Array)
69
+ obj.first.should be_kind_of(JSONSerializeMethodTester)
70
+ obj.first.var.should eql('value')
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,67 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'serialbox'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
13
+
14
+ def generate_tester_classes(prefix, serialize_with)
15
+ eval <<-RUBY
16
+ class #{prefix}SerializeMethodTester
17
+ attr_accessor :var
18
+ def initialize(var) self.var = var end
19
+
20
+ include SerialBox
21
+ serialize_with #{serialize_with.inspect}
22
+ serialize_fields { |s| s.serialize :var }
23
+ end
24
+
25
+ class #{prefix}SerializeIvarTester
26
+ def initialize(var) @var = var end
27
+
28
+ include SerialBox
29
+ serialize_with #{serialize_with.inspect}
30
+ serialize_fields { |s| s.serialize :@var }
31
+ end
32
+
33
+ class #{prefix}SerializeIntoTester
34
+ attr_accessor :var
35
+ def initialize(var) self.var = var end
36
+
37
+ include SerialBox
38
+ serialize_with #{serialize_with.inspect}
39
+ serialize_fields { |s| s.serialize :var, :into => :custom }
40
+ end
41
+
42
+
43
+ class #{prefix}SerializerMethodTester
44
+ def initialize(var) @var = var end
45
+ def var_setter(val) @var = val end
46
+ def var_getter() @var end
47
+
48
+ include SerialBox
49
+ serialize_with #{serialize_with.inspect}
50
+ serialize_fields do |s|
51
+ s.serializer 'var_json', :var_getter
52
+ s.deserializer 'var_json', :var_setter
53
+ end
54
+ end
55
+
56
+ class #{prefix}SerializerBlockTester
57
+ def initialize(var) @var = var end
58
+
59
+ include SerialBox
60
+ serialize_with #{serialize_with.inspect}
61
+ serialize_fields do |s|
62
+ s.serializer('var_json') { @var }
63
+ s.deserializer('var_json') { |val| @var = val }
64
+ end
65
+ end
66
+ RUBY
67
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serialbox
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Tim Morgan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-01-08 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ requirement: &id001 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ hash: 3
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ version_requirements: *id001
31
+ name: json
32
+ prerelease: false
33
+ type: :runtime
34
+ - !ruby/object:Gem::Dependency
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ hash: 3
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ version_requirements: *id002
45
+ name: activesupport
46
+ prerelease: false
47
+ type: :runtime
48
+ - !ruby/object:Gem::Dependency
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ version_requirements: *id003
59
+ name: rspec
60
+ prerelease: false
61
+ type: :development
62
+ - !ruby/object:Gem::Dependency
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ version_requirements: *id004
73
+ name: yard
74
+ prerelease: false
75
+ type: :development
76
+ - !ruby/object:Gem::Dependency
77
+ requirement: &id005 !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ hash: 3
83
+ segments:
84
+ - 0
85
+ version: "0"
86
+ version_requirements: *id005
87
+ name: redcarpet
88
+ prerelease: false
89
+ type: :development
90
+ - !ruby/object:Gem::Dependency
91
+ requirement: &id006 !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 3
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ version_requirements: *id006
101
+ name: bundler
102
+ prerelease: false
103
+ type: :development
104
+ - !ruby/object:Gem::Dependency
105
+ requirement: &id007 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ version_requirements: *id007
115
+ name: jeweler
116
+ prerelease: false
117
+ type: :development
118
+ description: This gem allows you to define how your object is serialized and deserialized. Then it's a simple matter of telling it which formats you want to support, and the serialization methods are automatically created for you.
119
+ email: rubygems@timothymorgan.info
120
+ executables: []
121
+
122
+ extensions: []
123
+
124
+ extra_rdoc_files:
125
+ - LICENSE.txt
126
+ - README.md
127
+ files:
128
+ - .document
129
+ - .rspec
130
+ - .rvmrc
131
+ - Gemfile
132
+ - Gemfile.lock
133
+ - LICENSE.txt
134
+ - README.md
135
+ - Rakefile
136
+ - VERSION
137
+ - lib/serialbox.rb
138
+ - lib/serializers/json.rb
139
+ - serialbox.gemspec
140
+ - spec/json_spec.rb
141
+ - spec/spec_helper.rb
142
+ homepage: http://github.com/riscfuture/serialbox
143
+ licenses:
144
+ - MIT
145
+ post_install_message:
146
+ rdoc_options: []
147
+
148
+ require_paths:
149
+ - lib
150
+ required_ruby_version: !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ hash: 3
156
+ segments:
157
+ - 0
158
+ version: "0"
159
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
+ none: false
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ hash: 3
165
+ segments:
166
+ - 0
167
+ version: "0"
168
+ requirements: []
169
+
170
+ rubyforge_project:
171
+ rubygems_version: 1.8.24
172
+ signing_key:
173
+ specification_version: 3
174
+ summary: Define how your object is serialized and deserialized, and this gem handles the rest.
175
+ test_files: []
176
+