trick_serial 0.2.0 → 0.3.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.
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