trick_serial 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ coverage
2
+ rdoc
3
+ doc
4
+ .yardoc
5
+ .bundle
6
+ pkg
7
+ rails_test
8
+ tct
9
+ *~
data/.rspec CHANGED
@@ -1 +1 @@
1
- --color
1
+ -f d --color
data/Gemfile CHANGED
@@ -1,17 +1,5 @@
1
- source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in trick_serial.gemspec
4
+ gemspec
5
5
 
6
- # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
- group :development do
9
- gem "rspec", "~> 2.3.0"
10
- gem "yard", "~> 0.6.0"
11
- gem "bundler", "~> 1.1.0"
12
- gem "jeweler", "~> 1.8.0"
13
- gem "rcov", ">= 0"
14
- gem 'ruby-debug', ">= 0"
15
- gem 'rails', "~> 1.2.6"
16
- gem 'memcache-client', ">= 1.7.0"
17
- end
data/Rakefile CHANGED
@@ -1,43 +1,24 @@
1
- require 'rubygems'
2
- require 'bundler'
3
- begin
4
- Bundler.setup(:default, :development)
5
- rescue Bundler::BundlerError => e
6
- $stderr.puts e.message
7
- $stderr.puts "Run `bundle install` to install missing gems"
8
- exit e.status_code
9
- end
10
- require 'rake'
11
-
12
- require 'jeweler'
13
- Jeweler::Tasks.new do |gem|
14
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
- gem.name = "trick_serial"
16
- gem.homepage = "http://github.com/kstephens/trick_serial"
17
- gem.license = "MIT"
18
- gem.summary = %Q{A Serialization Framework.}
19
- gem.description = %Q{Trick Serializers using Proxies.}
20
- gem.email = "ks.github@kurtstephens.com"
21
- gem.authors = ["Kurt Stephens"]
22
- # Include your dependencies below. Runtime dependencies are required when using your gem,
23
- # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
- # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
- # gem.add_development_dependency 'rspec', '> 1.2.3'
26
- end
27
- Jeweler::RubygemsDotOrgTasks.new
1
+ require "bundler/gem_tasks"
28
2
 
29
- require 'rspec/core'
3
+ gem 'rspec'
30
4
  require 'rspec/core/rake_task'
31
- RSpec::Core::RakeTask.new(:spec) do |spec|
32
- spec.pattern = FileList['spec/**/*_spec.rb']
5
+
6
+ desc "Run specs"
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
9
+ # Put spec opts in a file named .rspec in root
33
10
  end
34
11
 
35
- RSpec::Core::RakeTask.new(:rcov) do |spec|
36
- spec.pattern = 'spec/**/*_spec.rb'
37
- spec.rcov = true
12
+ desc "Generate code coverage"
13
+ RSpec::Core::RakeTask.new(:coverage) do |t|
14
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
15
+ t.rcov = true
16
+ t.rcov_opts = ['--exclude', 'spec']
38
17
  end
39
18
 
40
- task :default => :spec
19
+ desc "default => test"
20
+ task :default => :test
21
+
22
+ desc "test => spec"
23
+ task :test => :spec
41
24
 
42
- require 'yard'
43
- YARD::Rake::YardocTask.new
data/lib/trick_serial.rb CHANGED
@@ -1,3 +1,5 @@
1
1
  module TrickSerial
2
2
  EMPTY_Hash = { }.freeze
3
3
  end
4
+
5
+ require 'trick_serial/version'
@@ -1,5 +1,7 @@
1
1
  require 'trick_serial'
2
2
 
3
+ require 'ostruct' # OpenStruct
4
+
3
5
  module TrickSerial
4
6
  # Serializes objects using proxies for classes defined in #proxy_class_map.
5
7
  # Instances of the keys in #proxy_class_map are replaced by proxies if
@@ -110,7 +112,7 @@ module TrickSerial
110
112
  def proxyable
111
113
  unless @proxyable
112
114
  @proxyable = @class_option_map.keys.select{|cls| ! @class_option_map[cls][:do_not_traverse]}
113
- @do_not_traverse ||= @class_option_map.keys.select{|cls| @class_option_map[cls][:do_not_traverse]} << ObjectProxy
115
+ @do_not_traverse ||= @class_option_map.keys.select{|cls| @class_option_map[cls][:do_not_traverse]}
114
116
  @class_option_cache ||= { }
115
117
  @proxyable.freeze
116
118
  end
@@ -138,7 +140,6 @@ module TrickSerial
138
140
  o = x
139
141
  x = _copy_with_extensions(x)
140
142
  @visited[o.object_id] = [ x, o ]
141
- x = o
142
143
  x.class.members.each do | m |
143
144
  v = x.send(m)
144
145
  v = _encode! v
@@ -152,10 +153,16 @@ module TrickSerial
152
153
  o = x
153
154
  x = _copy_with_extensions(x)
154
155
  @visited[o.object_id] = [ x, o ]
155
- x = o
156
+ extended = false
156
157
  t = x.instance_variable_get("@table")
157
- t.each do | k, v |
158
- t[k] = _encode! v
158
+ t.keys.to_a.each do | k |
159
+ v = t._get_without_trick_serial(k)
160
+ v = _encode! v
161
+ if ! extended && ObjectProxy === v
162
+ t.extend ProxySwizzlingHash
163
+ extended = true
164
+ end
165
+ x.send(:"#{k}=", v)
159
166
  end
160
167
 
161
168
  when Array
@@ -166,13 +173,14 @@ module TrickSerial
166
173
  x = _copy_with_extensions(x)
167
174
  @visited[o.object_id] = [ x, o ]
168
175
  extended = false
169
- x.map! do | v |
176
+ x.size.times do | i |
177
+ v = x._get_without_trick_serial(i)
170
178
  v = _encode! v
171
179
  if ! extended && ObjectProxy === v
172
180
  x.extend ProxySwizzlingArray
173
181
  extended = true
174
182
  end
175
- v
183
+ x[i] = v
176
184
  end
177
185
 
178
186
  when Hash
@@ -185,7 +193,7 @@ module TrickSerial
185
193
  extended = false
186
194
  x.keys.to_a.each do | k |
187
195
  # pp [ :Hash_key, k ] if @debug >= 1
188
- v = x[k] = _encode!(x[k])
196
+ v = x[k] = _encode!(x._get_without_trick_serial(k))
189
197
  if ! extended && ObjectProxy === v
190
198
  x.extend ProxySwizzlingHash
191
199
  extended = true
@@ -297,7 +305,7 @@ module TrickSerial
297
305
 
298
306
  def resolve_class
299
307
  @resolve_class ||=
300
- eval("::#{@cls.to_s}")
308
+ @cls.to_s.split('::').inject(Object){|m, n| m.const_get(n)}
301
309
  end
302
310
 
303
311
  def object= x
@@ -335,13 +343,15 @@ module TrickSerial
335
343
  def class
336
344
  method_missing :class
337
345
  end
338
-
346
+
339
347
  alias :_proxy_object_id :object_id
340
348
  def object_id
341
349
  method_missing :object_id
342
350
  end
343
351
 
344
- alias :_proxy_id :id
352
+ if respond_to?(:id)
353
+ alias :_proxy_id :id
354
+ end
345
355
  def id
346
356
  method_missing :id
347
357
  end
@@ -424,4 +434,13 @@ module TrickSerial
424
434
  end # class
425
435
  end # module
426
436
 
437
+ class Array
438
+ alias :_get_without_trick_serial :[]
439
+ end
440
+
441
+ # Get values without triggering ProxySwizzling.
442
+ class Hash
443
+ alias :_get_without_trick_serial :[]
444
+ end
445
+
427
446
 
@@ -118,7 +118,7 @@ module TrickSerial
118
118
  end
119
119
 
120
120
  def delete
121
- _log { "#{self} close" }
121
+ _log { "#{self} delete" }
122
122
  _dbman.delete
123
123
  end
124
124
 
@@ -9,119 +9,109 @@ class Serializer
9
9
  # Ivar swizzling is not used.
10
10
  class Simple < self
11
11
  def _encode! x
12
- # pp [ :_encode!, x.class, x ]
12
+ @traverse_mode = :_encode!
13
+ _traverse! x
14
+ end
15
+
16
+ def _decode! x
17
+ @traverse_mode = :_decode!
18
+ _traverse! x
19
+ end
20
+
21
+ def _traverse! x
22
+ # pp [ :_traverse!, @traverse_mode, x.class, x ] if @debug >= 1
13
23
 
14
24
  case x
25
+ when *@do_not_traverse
26
+ # NOTHING
27
+
15
28
  when ObjectProxy
16
- x
29
+ if @traverse_mode == :_decode!
30
+ x = x.object
31
+ end
17
32
 
18
- when Array
33
+ when Struct
19
34
  if o = @visited[x.object_id]
20
35
  return o.first
21
36
  end
22
- extended = false
23
37
  o = x
24
- x = x.dup if @copy
38
+ x = _copy_with_extensions(x)
25
39
  @visited[o.object_id] = [ x, o ]
26
- x.map! do | v |
27
- _encode! v
40
+ x.class.members.each do | m |
41
+ v = x.send(m)
42
+ v = _traverse! v
43
+ x.send(:"#{m}=", v)
28
44
  end
29
45
 
30
- when Hash
46
+ when OpenStruct
31
47
  if o = @visited[x.object_id]
32
48
  return o.first
33
49
  end
34
- extended = false
35
50
  o = x
36
- x = x.dup if @copy
51
+ x = _copy_with_extensions(x)
37
52
  @visited[o.object_id] = [ x, o ]
38
- x.keys.to_a.each do | k |
39
- x[k] = _encode!(x[k])
53
+ t = x.instance_variable_get("@table")
54
+ t.keys.to_a.each do | k |
55
+ v = t._get_without_trick_serial(k)
56
+ v = _traverse! v
57
+ x.send(:"#{k}=", v)
40
58
  end
41
59
 
42
- when *@proxyable
43
- if proxy = @object_to_proxy_map[x.object_id]
44
- return proxy.first
45
- end
46
- # debugger
47
- o = x
48
- proxy_cls = nil
49
- if class_option = self._class_option(x)
50
- proxy_cls = class_option[:proxy_class]
51
- # Deeply encode instance vars?
52
- if ivs = class_option[:instance_vars]
53
- ivs = x.instance_variables if ivs == true
54
- x = x.dup if @copy
55
- @object_to_proxy_map[o.object_id] = [ x, o ]
56
- ivs.each do | ivar |
57
- v = x.instance_variable_get(ivar)
58
- v = _encode!(v)
59
- x.instance_variable_set(ivar, v)
60
- end
61
- end
62
- end
63
-
64
- x = _make_proxy o, x, proxy_cls
65
- end
66
-
67
- x
68
- end # def
69
-
70
- def _decode! x
71
- case x
72
- when ObjectProxy
73
- x = x.object
74
-
75
60
  when Array
76
61
  if o = @visited[x.object_id]
77
62
  return o.first
78
63
  end
79
- extended = false
80
64
  o = x
81
- x = x.dup if @copy
65
+ x = _copy_with_extensions(x)
82
66
  @visited[o.object_id] = [ x, o ]
83
67
  x.map! do | v |
84
- _decode! v
68
+ _traverse! v
85
69
  end
86
-
70
+
87
71
  when Hash
88
72
  if o = @visited[x.object_id]
89
73
  return o.first
90
74
  end
91
- extended = false
92
75
  o = x
93
- x = x.dup if @copy
76
+ x = _copy_with_extensions(x)
94
77
  @visited[o.object_id] = [ x, o ]
95
78
  x.keys.to_a.each do | k |
96
- x[k] = _decode!(x[k])
79
+ x[k] = _traverse!(x[k])
97
80
  end
98
-
81
+
99
82
  when *@proxyable
100
83
  if proxy = @object_to_proxy_map[x.object_id]
101
84
  return proxy.first
102
85
  end
103
86
  # debugger
104
87
  o = x
105
- if class_option = _class_option(x)
88
+ proxy_cls = nil
89
+ if class_option = self._class_option(x)
90
+ proxy_cls = class_option[:proxy_class]
106
91
  # Deeply encode instance vars?
107
92
  if ivs = class_option[:instance_vars]
108
93
  ivs = x.instance_variables if ivs == true
109
- x = x.dup if @copy
94
+ x = _copy_with_extensions(x)
110
95
  @object_to_proxy_map[o.object_id] = [ x, o ]
111
96
  ivs.each do | ivar |
112
97
  v = x.instance_variable_get(ivar)
113
- # $stderr.puts "\n#{x.class} #{x.object_id} ivar #{ivar} #{v.inspect}" if @debug
114
- v = _decode!(v)
98
+ v = _traverse!(v)
115
99
  x.instance_variable_set(ivar, v)
116
100
  end
117
101
  end
118
102
  end
119
- @object_to_proxy_map[o.object_id] ||= [ x, o ]
103
+ if @traverse_mode == :_decode!
104
+ @object_to_proxy_map[o.object_id] ||= [ x, o ]
105
+ else
106
+ x = _make_proxy o, x, proxy_cls
107
+ end
120
108
  end # case
121
-
109
+
110
+ # pp [ :_traverse!, @traverse_mode, :RESULT, x.class, x ] if @debug >= 2
111
+
122
112
  x
123
113
  end # def
124
-
114
+
125
115
  end # class
126
116
  end # class
127
117
  end # module
@@ -0,0 +1,3 @@
1
+ module TrickSerial
2
+ VERSION = "0.3.0"
3
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,24 +1,8 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- $LOAD_PATH.unshift(File.dirname(__FILE__))
1
+ $:.unshift(File.expand_path('../../lib', __FILE__))
2
+ $:.unshift(File.dirname(__FILE__))
3
3
  require 'rspec'
4
4
  require 'trick_serial'
5
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
- =begin
11
- if $DEBUG || ENV['DEBUG']
12
- require 'rubygems'
13
- gem 'ruby-debug'
14
- require 'ruby-debug'
15
- end
16
- =end
17
-
18
- RSpec.configure do |config|
19
-
20
- end
21
-
22
6
  ######################################################################
23
7
  # Common test helpers
24
8
  #
@@ -15,8 +15,8 @@ begin
15
15
  require 'action_controller/session/mem_cache_store'
16
16
  require 'trick_serial/serializer/cgi_session'
17
17
  $have_mem_cache_store = true
18
- rescue Exception => err
19
- $stderr.puts "#{__FILE__}: #{err.inspect}\n #{err.backtrace * "\n "}"
18
+ rescue LoadError => err
19
+ # NOTHING
20
20
  end
21
21
 
22
22
 
@@ -16,11 +16,13 @@ describe "TrickSerial::Serializer::Simple" do
16
16
  t::B => { :instance_vars => [ "@x" ] },
17
17
  }
18
18
  TrickSerial::Serializer::Test::PhonyActiveRecord.find_map.clear
19
-
19
+ # Note: Structs are anonymous Classes and cannot be Marshal'ed.
20
+ @struct = Struct.new :sm, :sa, :sb
20
21
  @m = TrickSerial::Serializer::Test::Model.new(123)
21
22
  @m2 = TrickSerial::Serializer::Test::Model.new(456)
22
23
  @m_unsaved = TrickSerial::Serializer::Test::Model.new(:unsaved)
23
24
  @m_unsaved.id = nil
25
+ @os = OpenStruct.new
24
26
  @h = {
25
27
  :a => 1,
26
28
  'b' => 2,
@@ -28,7 +30,11 @@ describe "TrickSerial::Serializer::Simple" do
28
30
  :m => @m,
29
31
  :a => [ 0, 1, @m, 3, 4, @m ],
30
32
  :m_unsaved => @m_unsaved,
33
+ :os => @os,
31
34
  }
35
+ @os.osm = @m
36
+ @os.osa = @h
37
+ @os.osb = 'b'
32
38
  @h[:a2] = @h[:a]
33
39
  @h[:h2] = @h
34
40
  end
@@ -62,7 +68,38 @@ describe "TrickSerial::Serializer::Simple" do
62
68
  result.object_id.should == @h.object_id
63
69
  end
64
70
 
65
- it "should proxy unsaved models" do
71
+ it "should proxy saved models directly" do
72
+ @s.debug = 0
73
+
74
+ @o = @s.encode!(@m)
75
+ @o.object_id.should_not == @m.object_id
76
+ @o.class.should == TrickSerial::Serializer::ActiveRecordProxy
77
+ @o.cls.should == @m.class.name.to_sym
78
+ @o.id.should == @m.id
79
+
80
+ @o = @s.decode!(@o)
81
+
82
+ @o.object_id.should_not == @m.object_id
83
+ @o.class.should == @m.class
84
+ @o.id.should == @m.id
85
+ end
86
+
87
+ it "should not proxy saved models twice" do
88
+ @s.debug = 0
89
+
90
+ @o = @s.encode!(@m)
91
+ @o.object_id.should_not == @m.object_id
92
+ @o.class.should == TrickSerial::Serializer::ActiveRecordProxy
93
+ @o.cls.should == @m.class.name.to_sym
94
+ @o.id.should == @m.id
95
+
96
+ @o1 = @o
97
+ @o = @s.encode!(@o)
98
+ @o.object_id.should == @o1.object_id
99
+ @o.class.should == TrickSerial::Serializer::ActiveRecordProxy
100
+ end
101
+
102
+ it "should proxy saved models" do
66
103
  @o = @s.encode!(@h)
67
104
  @o = @s.decode!(@o)
68
105
  @o[:m].object_id.should_not == @m.object_id
@@ -154,6 +191,27 @@ describe "TrickSerial::Serializer::Simple" do
154
191
  a.should == p
155
192
  end
156
193
 
194
+ it "should handle encode/decode through OpenStruct" do
195
+ @o = @s.encode!(@os)
196
+ @o.osm.class.should == TrickSerial::Serializer::ActiveRecordProxy
197
+ @o = @s.decode!(@o)
198
+ @o.object_id.should == @os.object_id
199
+ @o.osm.class.should == TrickSerial::Serializer::Test::Model
200
+ end
201
+
202
+ it "should handle encode/decode through OpenStruct" do
203
+ s = @struct.new
204
+ s.sm = @m
205
+ s.sa = 'a'
206
+ s.sb = :b
207
+
208
+ @o = @s.encode!(s)
209
+ @o.sm.class.should == TrickSerial::Serializer::ActiveRecordProxy
210
+ @o = @s.decode!(@o)
211
+ @o.object_id.should == s.object_id
212
+ @o.sm.class.should == TrickSerial::Serializer::Test::Model
213
+ end
214
+
157
215
  it "should lazily traverse proxies" do
158
216
  fm = TrickSerial::Serializer::Test::PhonyActiveRecord.find_map
159
217
 
@@ -229,7 +287,7 @@ describe "TrickSerial::Serializer::Simple" do
229
287
  e.instance_variable_get("@x").class.should == TrickSerial::Serializer::ActiveRecordProxy
230
288
  e.instance_variable_get("@y").class.should == TrickSerial::Serializer::ActiveRecordProxy
231
289
 
232
- @s.verbose = @s.debug = true
290
+ @s.verbose = true; @s.debug = 0
233
291
  obj = @s.decode!(e)
234
292
  # $stderr.puts "marshal = #{str.inspect}"
235
293
 
@@ -241,7 +299,7 @@ describe "TrickSerial::Serializer::Simple" do
241
299
  obj = t::B.new
242
300
  obj.x = @m # should be encoded
243
301
  obj.y = @m # should not be encoded
244
- @s.verbose = @s.debug = false
302
+ @s.verbose = false; @s.debug = 0
245
303
  obj = @s.encode!(obj)
246
304
  e = Marshal.load(str = Marshal.dump(obj))
247
305
 
@@ -249,7 +307,7 @@ describe "TrickSerial::Serializer::Simple" do
249
307
  e.instance_variable_get("@x").class.should == TrickSerial::Serializer::ActiveRecordProxy
250
308
  e.instance_variable_get("@y").class.should == TrickSerial::Serializer::Test::Model
251
309
 
252
- @s.verbose = @s.debug = true
310
+ @s.verbose = true; @s.debug = 0
253
311
  obj = @s.decode!(e)
254
312
  # $stderr.puts "marshal = #{str.inspect}"
255
313
 
@@ -62,6 +62,7 @@ describe "TrickSerial::Serializer" do
62
62
 
63
63
  result.object_id.should == @h.object_id
64
64
  result[:s].class.should == @struct
65
+ result[:s].sm.object_id.should_not == @m2.object_id
65
66
  result[:s].sm.id.should == @m2.id
66
67
  result[:s].sm.class.should == TrickSerial::Serializer::ActiveRecordProxy
67
68
  result[:s].sa.object_id.should == @h.object_id
@@ -69,20 +70,82 @@ describe "TrickSerial::Serializer" do
69
70
  result[:s].sb.object_id.should == result[:s].object_id
70
71
  end
71
72
 
73
+ it "should handle #encode of Struct" do
74
+ @h[:s].sm.should == @m2
75
+ @h[:s].sa.should == @h
76
+ @h[:s].sb = @h[:s] # self-reference
77
+
78
+ result = @s.encode(@h)
79
+
80
+ result.object_id.should_not == @h.object_id
81
+ result[:s].class.should == @struct
82
+ result[:s].sm.object_id.should_not == @m2.object_id
83
+ result[:s].sm.id.should == @m2.id
84
+ result[:s].sm.class.should == TrickSerial::Serializer::ActiveRecordProxy
85
+ result[:s].sa.object_id.should_not == @h.object_id
86
+ result[:s].sb.object_id.should_not == @h[:s].sb.object_id
87
+ result[:s].sb.object_id.should == result[:s].object_id
88
+ end
89
+
72
90
  it "should handle #encode! of OpenStruct" do
73
91
  @h[:os].osm.should == @m
74
92
  @h[:os].osa.should == @h
75
93
  @h[:os].osos = @h[:os] # self-reference
94
+ os = @h[:os]
95
+
96
+ os.respond_to?(:osm).should == true
97
+ os.respond_to?(:osa).should == true
98
+ os.respond_to?(:osos).should == true
76
99
 
77
100
  result = @s.encode!(@h)
78
101
 
79
102
  result.object_id.should == @h.object_id
80
103
  result[:os].class.should == @h[:os].class
104
+
105
+ # Validate OpenStruct @table encoding.
106
+ osh = result[:os].instance_variable_get("@table")
107
+ osh._get_without_trick_serial(:osm).class.should == TrickSerial::Serializer::ActiveRecordProxy
108
+ # Force OpenStruct @table Hash Swizzling.
81
109
  result[:os].osm.id.should == @m.id
82
- result[:os].osm.class.should == TrickSerial::Serializer::ActiveRecordProxy
110
+ result[:os].osm.class.should == TrickSerial::Serializer::Test::Model
111
+ # Validate OpenStruct @table HashHash Swizzling.
112
+ osh._get_without_trick_serial(:osm).class.should == TrickSerial::Serializer::Test::Model
113
+
83
114
  result[:os].osa.object_id.should == @h.object_id
84
115
  result[:os].osb.object_id.should == @h[:os].osb.object_id
85
116
  result[:os].osos.object_id.should == result[:os].object_id
117
+
118
+ os = result[:os]
119
+ os.respond_to?(:osm).should == true
120
+ os.respond_to?(:osa).should == true
121
+ os.respond_to?(:osos).should == true
122
+ end
123
+
124
+ it "should handle #encode of OpenStruct" do
125
+ @h[:os].osm.should == @m
126
+ @h[:os].osa.should == @h
127
+ @h[:os].osos = @h[:os] # self-reference
128
+ os = @h[:os]
129
+
130
+ os.respond_to?(:osm).should == true
131
+ os.respond_to?(:osa).should == true
132
+ os.respond_to?(:osos).should == true
133
+
134
+ result = @s.encode(@h)
135
+
136
+ result.object_id.should_not == @h.object_id
137
+ result[:os].class.should == @h[:os].class
138
+ result[:os].object_id.should_not == @h[:os].object_id
139
+ result[:os].osm.id.should == @m.id
140
+ result[:os].osm.class.should == TrickSerial::Serializer::Test::Model
141
+ result[:os].osa.object_id.should_not == @h.object_id
142
+ result[:os].osb.object_id.should == @h[:os].osb.object_id
143
+ # result[:os].osos.object_id.should == result[:os].object_id
144
+
145
+ os = result[:os]
146
+ os.respond_to?(:osm).should == true
147
+ os.respond_to?(:osa).should == true
148
+ os.respond_to?(:osos).should == true
86
149
  end
87
150
 
88
151
  it "should honor #enabled?" do
@@ -167,6 +230,26 @@ describe "TrickSerial::Serializer" do
167
230
  a.should == p
168
231
  end
169
232
 
233
+ it "should handle proxy swizzling through OpenStruct" do
234
+ m = @h[:m]
235
+ os = OpenStruct.new
236
+ os.m = m
237
+ # pp os
238
+
239
+ @s.encode!(os)
240
+ osd = Marshal.dump(os) # save state
241
+
242
+ os.m.class.should == m.class
243
+ os.m.object_id.should_not == m.object_id
244
+
245
+ os = Marshal.load(osd)
246
+ # pp os
247
+
248
+ osh = os.instance_variable_get('@table')
249
+ os.m.class.should == m.class
250
+ os.m.object_id.should_not == m.object_id
251
+ end
252
+
170
253
  it "should lazily traverse proxies" do
171
254
  fm = TrickSerial::Serializer::Test::PhonyActiveRecord.find_map
172
255
 
@@ -192,6 +275,39 @@ describe "TrickSerial::Serializer" do
192
275
  fm.keys.size.should == 1
193
276
  end
194
277
 
278
+ it "should encode/decode proxies only once" do
279
+ fm = TrickSerial::Serializer::Test::PhonyActiveRecord.find_map
280
+
281
+ fm[@m.id].should == nil
282
+
283
+ # Encode once.
284
+ @s.encode!(@h)
285
+
286
+ # Note: Structs are anonymous Classes and cannot be Marshal'ed.
287
+ @h[:s] = nil
288
+ @h = Marshal.load(Marshal.dump(@h))
289
+
290
+ fm[@m.id].should == nil
291
+
292
+ # Encode again.
293
+ @s.encode!(@h)
294
+ @h = Marshal.load(Marshal.dump(@h))
295
+
296
+ fm[@m.id].should == nil
297
+
298
+ # ProxySwizzling occurs only once.
299
+ p = @h[:m]
300
+
301
+ fm[@m.id].should == 1
302
+
303
+ @h[:m].object_id.should == p.object_id
304
+ @h[:a][2].object_id.should == p.object_id
305
+ @h[:a][5].object_id.should == p.object_id
306
+
307
+ fm[@m.id].should == 1
308
+ fm.keys.size.should == 1
309
+ end
310
+
195
311
  it "should preserve object identity" do
196
312
  @s.encode!(@h)
197
313
 
@@ -0,0 +1,36 @@
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
+ lib = File.expand_path('../lib', __FILE__)
7
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
8
+ require 'trick_serial/version'
9
+
10
+ Gem::Specification.new do |s|
11
+ gem = s
12
+ s.name = %q{trick_serial}
13
+ s.version = TrickSerial::VERSION
14
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
15
+ s.authors = ["Kurt Stephens"]
16
+ s.description = %q{Trick Serializers using Proxies.}
17
+ s.summary = %q{Trick Serializers using Proxies.}
18
+ s.homepage = %q{http://github.com/kstephens/trick_serial}
19
+ s.email = %q{ks.github@kurtstephens.com}
20
+
21
+ gem.files = `git ls-files`.split($/)
22
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
23
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
24
+ gem.require_paths = ["lib"]
25
+
26
+ s.extra_rdoc_files = [
27
+ "LICENSE.txt",
28
+ "README.rdoc"
29
+ ]
30
+ s.licenses = ["MIT"]
31
+
32
+ gem.add_development_dependency 'rake', '>= 0.9.0'
33
+ gem.add_development_dependency 'rspec', '~> 2.12.0'
34
+ gem.add_development_dependency 'simplecov', '>= 0.1'
35
+ end
36
+
metadata CHANGED
@@ -1,158 +1,74 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: trick_serial
3
- version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 2
9
- - 0
10
- version: 0.2.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Kurt Stephens
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-07-20 00:00:00 -05:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- prerelease: false
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
12
+ date: 2012-12-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 2
31
- - 3
32
- - 0
33
- version: 2.3.0
34
- name: rspec
35
- requirement: *id001
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.0
36
22
  type: :development
37
- - !ruby/object:Gem::Dependency
38
23
  prerelease: false
39
- version_requirements: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
40
25
  none: false
41
- requirements:
42
- - - ~>
43
- - !ruby/object:Gem::Version
44
- hash: 7
45
- segments:
46
- - 0
47
- - 6
48
- - 0
49
- version: 0.6.0
50
- name: yard
51
- requirement: *id002
52
- type: :development
53
- - !ruby/object:Gem::Dependency
54
- prerelease: false
55
- version_requirements: &id003 !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.9.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
56
33
  none: false
57
- requirements:
34
+ requirements:
58
35
  - - ~>
59
- - !ruby/object:Gem::Version
60
- hash: 19
61
- segments:
62
- - 1
63
- - 1
64
- - 0
65
- version: 1.1.0
66
- name: bundler
67
- requirement: *id003
36
+ - !ruby/object:Gem::Version
37
+ version: 2.12.0
68
38
  type: :development
69
- - !ruby/object:Gem::Dependency
70
39
  prerelease: false
71
- version_requirements: &id004 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
72
41
  none: false
73
- requirements:
42
+ requirements:
74
43
  - - ~>
75
- - !ruby/object:Gem::Version
76
- hash: 55
77
- segments:
78
- - 1
79
- - 8
80
- - 0
81
- version: 1.8.0
82
- name: jeweler
83
- requirement: *id004
84
- type: :development
85
- - !ruby/object:Gem::Dependency
86
- prerelease: false
87
- version_requirements: &id005 !ruby/object:Gem::Requirement
44
+ - !ruby/object:Gem::Version
45
+ version: 2.12.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: simplecov
48
+ requirement: !ruby/object:Gem::Requirement
88
49
  none: false
89
- requirements:
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- hash: 3
93
- segments:
94
- - 0
95
- version: "0"
96
- name: rcov
97
- requirement: *id005
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0.1'
98
54
  type: :development
99
- - !ruby/object:Gem::Dependency
100
55
  prerelease: false
101
- version_requirements: &id006 !ruby/object:Gem::Requirement
56
+ version_requirements: !ruby/object:Gem::Requirement
102
57
  none: false
103
- requirements:
104
- - - ">="
105
- - !ruby/object:Gem::Version
106
- hash: 3
107
- segments:
108
- - 0
109
- version: "0"
110
- name: ruby-debug
111
- requirement: *id006
112
- type: :development
113
- - !ruby/object:Gem::Dependency
114
- prerelease: false
115
- version_requirements: &id007 !ruby/object:Gem::Requirement
116
- none: false
117
- requirements:
118
- - - ~>
119
- - !ruby/object:Gem::Version
120
- hash: 19
121
- segments:
122
- - 1
123
- - 2
124
- - 6
125
- version: 1.2.6
126
- name: rails
127
- requirement: *id007
128
- type: :development
129
- - !ruby/object:Gem::Dependency
130
- prerelease: false
131
- version_requirements: &id008 !ruby/object:Gem::Requirement
132
- none: false
133
- requirements:
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- hash: 11
137
- segments:
138
- - 1
139
- - 7
140
- - 0
141
- version: 1.7.0
142
- name: memcache-client
143
- requirement: *id008
144
- type: :development
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
145
62
  description: Trick Serializers using Proxies.
146
63
  email: ks.github@kurtstephens.com
147
64
  executables: []
148
-
149
65
  extensions: []
150
-
151
- extra_rdoc_files:
66
+ extra_rdoc_files:
152
67
  - LICENSE.txt
153
68
  - README.rdoc
154
- files:
69
+ files:
155
70
  - .document
71
+ - .gitignore
156
72
  - .rspec
157
73
  - Gemfile
158
74
  - LICENSE.txt
@@ -165,43 +81,42 @@ files:
165
81
  - lib/trick_serial/serializer/cgi_session.rb
166
82
  - lib/trick_serial/serializer/rails.rb
167
83
  - lib/trick_serial/serializer/simple.rb
84
+ - lib/trick_serial/version.rb
168
85
  - spec/spec_helper.rb
169
86
  - spec/trick_serial/cgi_session_spec.rb
170
87
  - spec/trick_serial/serializer_simple_spec.rb
171
88
  - spec/trick_serial/serializer_spec.rb
172
- has_rdoc: true
89
+ - trick_serial.gemspec
173
90
  homepage: http://github.com/kstephens/trick_serial
174
- licenses:
91
+ licenses:
175
92
  - MIT
176
93
  post_install_message:
177
94
  rdoc_options: []
178
-
179
- require_paths:
95
+ require_paths:
180
96
  - lib
181
- required_ruby_version: !ruby/object:Gem::Requirement
97
+ required_ruby_version: !ruby/object:Gem::Requirement
182
98
  none: false
183
- requirements:
184
- - - ">="
185
- - !ruby/object:Gem::Version
186
- hash: 3
187
- segments:
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ segments:
188
104
  - 0
189
- version: "0"
190
- required_rubygems_version: !ruby/object:Gem::Requirement
105
+ hash: -1879002801800302150
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
191
107
  none: false
192
- requirements:
193
- - - ">="
194
- - !ruby/object:Gem::Version
195
- hash: 3
196
- segments:
197
- - 0
198
- version: "0"
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
199
112
  requirements: []
200
-
201
113
  rubyforge_project:
202
- rubygems_version: 1.3.7
114
+ rubygems_version: 1.8.24
203
115
  signing_key:
204
116
  specification_version: 3
205
- summary: A Serialization Framework.
206
- test_files: []
207
-
117
+ summary: Trick Serializers using Proxies.
118
+ test_files:
119
+ - spec/spec_helper.rb
120
+ - spec/trick_serial/cgi_session_spec.rb
121
+ - spec/trick_serial/serializer_simple_spec.rb
122
+ - spec/trick_serial/serializer_spec.rb