mccraigmccraig-better_serialization 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +102 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/init.rb +2 -0
- data/lib/better_serialization.rb +125 -0
- data/spec/better_serialization_spec.rb +122 -0
- data/spec/models/customer.rb +6 -0
- data/spec/models/directory.rb +3 -0
- data/spec/models/line_item.rb +4 -0
- data/spec/models/order_log.rb +5 -0
- data/spec/models/person.rb +12 -0
- data/spec/models/product.rb +3 -0
- data/spec/schema.rb +24 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +30 -0
- metadata +141 -0
data/.document
ADDED
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [name of plugin creator]
|
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.rdoc
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
=== Faster, Smaller, Gzip-able
|
2
|
+
|
3
|
+
This adds +marshal_serialize+ and +json_serialize+ to ActiveRecord::Base (class methods), which act similar to rails' own +serialize+ except they don't use yaml, which is slooooow and biiiiig (byte-wise). Also supports adding gzip to the serialization process for really large stuff (can save a ton of database memory with minimal added insert time). Note that gzip columns must be of type "binary", "blob", etc (not text).
|
4
|
+
|
5
|
+
Note that there's a limitation with the plugin: you can't call destructive actions on attributes using better_serialization (ex. << for an array), and update_attribute etc won't work. See TODO for an explanation.
|
6
|
+
|
7
|
+
=== Example
|
8
|
+
|
9
|
+
see tests, but here's the gist:
|
10
|
+
|
11
|
+
class OrderLog < ActiveRecord::Base
|
12
|
+
marshal_serialize :line_items_cache, :gzip => true
|
13
|
+
marshal_serialize :product_cache
|
14
|
+
json_serialize :customer_cache
|
15
|
+
end
|
16
|
+
|
17
|
+
order_log = OrderLog.new
|
18
|
+
product = Product.new(:name => "Woot")
|
19
|
+
order_log.product_cache = product
|
20
|
+
|
21
|
+
order_log.product_cache # => normal
|
22
|
+
order_log[:product_cache] # => raw Marshal.dump of product
|
23
|
+
|
24
|
+
=== Notes for json_serialize
|
25
|
+
|
26
|
+
JSON serialization is faster and smaller, but needs more configuration. This is because Marshal and the default YAML serialization dump the whole object, instance variables and all. JSON just stores an instances' attribute values. Thus, you need to tell it what class to instantiate, or tell it not to instantiate anything at all for storing a hash or array of data.
|
27
|
+
|
28
|
+
Also, when serializing ActiveRecord objects, if <code>ActiveRecord::Base.include_root_in_json == true</code> (the new rails defalut), it'll all 'just work'. Otherwise, you will need to use the :class_name option if it's not inferable by the association name, and will probably want modify that class's to_json to include the id.
|
29
|
+
|
30
|
+
=== The Problem With YAML Serialization: speed and size
|
31
|
+
|
32
|
+
[NOTE: this code does not represent the BetterSerialization api, but rather the underlying ideas]
|
33
|
+
|
34
|
+
The following examples came from the real-world objects that inspired the plugin.
|
35
|
+
|
36
|
+
+lis+ is an 18-member array of line items that have many associations loaded into memory,
|
37
|
+
the point being that they're relatively big objects.
|
38
|
+
|
39
|
+
marshal_data, yaml_data, json_data = nil
|
40
|
+
|
41
|
+
Benchmark.bm(7) do |x|
|
42
|
+
x.report("Marshal") { marshal_data = Marshal.dump(lis) }
|
43
|
+
x.report("to_yaml") { yaml_data = lis.to_yaml }
|
44
|
+
x.report('to_json') { json_data = lis.to_json }
|
45
|
+
end
|
46
|
+
|
47
|
+
user system total real
|
48
|
+
Marshal 0.590000 0.000000 0.590000 ( 0.605567)
|
49
|
+
to_yaml 11.730000 0.010000 11.740000 ( 12.179310)
|
50
|
+
to_json 0.010000 0.000000 0.010000 ( 0.006129)
|
51
|
+
|
52
|
+
The reason JSON is so fast is that rails' ActiveRecord::Base#to_json only jsonifies the attributes hash, not the actual ruby object. If you want the full object though, Marshal is waaaaay faster than to_yaml, and it *is* representing the full ruby object.
|
53
|
+
|
54
|
+
Marshal is also a lot smaller than yaml:
|
55
|
+
|
56
|
+
>> marshal_data.size
|
57
|
+
=> 1119279
|
58
|
+
>> yaml_data.size
|
59
|
+
=> 1958610
|
60
|
+
>> json_data.size
|
61
|
+
=> 7886
|
62
|
+
|
63
|
+
Whammy. What about deserialization?
|
64
|
+
|
65
|
+
Benchmark.bm(7) do |x|
|
66
|
+
x.report("Marshal") { Marshal.load(marshal_data) }
|
67
|
+
x.report("to_yaml") { YAML::load(yaml_data) }
|
68
|
+
x.report('to_json') { ActiveSupport::JSON.decode(json_data).collect {|hash| BuylistLineItem.new(hash)} }
|
69
|
+
end
|
70
|
+
|
71
|
+
user system total real
|
72
|
+
Marshal 0.040000 0.000000 0.040000 ( 0.046616)
|
73
|
+
to_yaml 0.380000 0.000000 0.380000 ( 0.380686)
|
74
|
+
to_json 0.020000 0.000000 0.020000 ( 0.019096)
|
75
|
+
|
76
|
+
With json you can't just unmarshal it 'cuz it's just representing an attribute array, but even compensating with object creation it's still the fastest.
|
77
|
+
|
78
|
+
Finally, if you need to save some space, you can use gzip with the serialization:
|
79
|
+
|
80
|
+
>> Benchmark.measure {gz_marshal_data = Zlib::Deflate.deflate(marshal_data)}
|
81
|
+
=> #<Benchmark::Tms:0x10a7ee54 @utime=0.0300000000000011, @cstime=0.0, @cutime=0.0, @total=0.0300000000000011, @label="", @stime=0.0, @real=0.0292189121246338>
|
82
|
+
>> marshal_data.size - gz_marshal_data.size
|
83
|
+
=> 1036979
|
84
|
+
>> Benchmark.measure {Zlib::Inflate.inflate(marshal_data)}
|
85
|
+
=> #<Benchmark::Tms:0x10a8db98 @utime=0.0, @cstime=0.0, @cutime=0.0, @total=0.0, @label="", @stime=0.0, @real=0.00509905815124512>
|
86
|
+
|
87
|
+
So on this machine it would add 30ms on insert and 5ms on load, but save ~1mb of database space. Seems worth it if you're saving this much stuff.
|
88
|
+
|
89
|
+
[EDIT: Also note that from personal experience, gzipping json will still use 1/10th the overall space with ~.5ms performance hit - WIN]
|
90
|
+
|
91
|
+
=== Summary
|
92
|
+
|
93
|
+
If you want speed/small data and don't need to flash-freeze the whole object, use json. Otherwise, use Marshal. If you want to use minimal database space, add gzip to those (adds a relatively small performance hit). Use the default yaml if you really, really *need* to save the whole object and also have a more human-readable datastore... eh, actually, don't use yaml.
|
94
|
+
|
95
|
+
=== TODO
|
96
|
+
|
97
|
+
* deserialization should be cached, and it would be nice if the deserialized value was stored in the attributes hash.
|
98
|
+
* Allow destructive actions
|
99
|
+
* The problem is that serializing and de-serializing creates new objects, so if you do object.array_attribute << "blah", you will have deserialized a new object, destructively added a value to it, and thrown the new object away. ActiveRecord avoids this issue by calling to_yaml as a catch-all on the result of read_attribute in activerecord/lib/active_record/connection_adapters/abstract/quoting.rb#quote (as of 2.3.4). What we need is something like being able to specify what AR's catch-all case is (although that wouldn't work for some option/value combos, ex. gzip option on a string or date). Gratefully accepting ideas :)
|
100
|
+
* Also, just thought of another way. have the raw data be in the raw_#{attribute} column, and object.attribute be a method that loads raw_#{attribute}. That + save hooks = win.
|
101
|
+
|
102
|
+
Copyright (c) 2009 Woody Peterson, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "mccraigmccraig-better_serialization"
|
8
|
+
gem.summary = %Q{json and zlib serialization for activerecord attributes}
|
9
|
+
gem.description = %Q{serialize and deserialize activerecord attributes using json or zlib}
|
10
|
+
gem.email = "mccraigmccraig@googlemail.com"
|
11
|
+
gem.homepage = "http://github.com/trampoline/better_serialization"
|
12
|
+
gem.authors = ["http://github.com/crystalcommerce", "http://github.com/rhburrows", "http://github.com/mccraigmccraig"]
|
13
|
+
gem.add_dependency "activerecord", ">= 2.3.8"
|
14
|
+
gem.add_development_dependency "rspec", ">= 1.2.8"
|
15
|
+
gem.add_development_dependency "sqlite3-ruby", ">= 1.3.1"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
25
|
+
spec.libs << 'lib' << 'spec'
|
26
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
+
end
|
28
|
+
|
29
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
+
spec.rcov = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :spec => :check_dependencies
|
36
|
+
|
37
|
+
task :default => :spec
|
38
|
+
|
39
|
+
require 'rake/rdoctask'
|
40
|
+
Rake::RDocTask.new do |rdoc|
|
41
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
42
|
+
|
43
|
+
rdoc.rdoc_dir = 'rdoc'
|
44
|
+
rdoc.title = "better_serialization #{version}"
|
45
|
+
rdoc.rdoc_files.include('README*')
|
46
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
47
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/init.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
|
3
|
+
module BetterSerialization
|
4
|
+
class JsonSerializer
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_json(object)
|
12
|
+
json = object.to_json
|
13
|
+
json = Zlib::Deflate.deflate(json) if options[:gzip]
|
14
|
+
json
|
15
|
+
end
|
16
|
+
|
17
|
+
def from_json(attribute)
|
18
|
+
return options[:default].try(:call) if attribute.nil?
|
19
|
+
|
20
|
+
json = options[:gzip] ? Zlib::Inflate.inflate(attribute) : attribute
|
21
|
+
decoded = ActiveSupport::JSON.decode(json)
|
22
|
+
|
23
|
+
if options[:with_indifferent_access]
|
24
|
+
return decoded.respond_to?(:with_indifferent_access) ? decoded.with_indifferent_access : decoded
|
25
|
+
end
|
26
|
+
return decoded if !options[:instantiate]
|
27
|
+
|
28
|
+
result = deserialize(attribute, [decoded].flatten)
|
29
|
+
return decoded.is_a?(Array) ? result : result.first
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def deserialize(attribute, attribute_hashes)
|
35
|
+
class_name = options[:class_name]
|
36
|
+
attribute_hashes.inject([]) do |result, attr_hash|
|
37
|
+
if class_name.blank? || class_included?(class_name)
|
38
|
+
class_name = attr_hash.keys.first.camelcase
|
39
|
+
attr_hash = attr_hash.values.first
|
40
|
+
end
|
41
|
+
class_name ||= attribute.to_s.singularize.camelize
|
42
|
+
|
43
|
+
result << create(class_name.constantize, attr_hash.with_indifferent_access)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def active_record?(klass)
|
48
|
+
k = klass.superclass
|
49
|
+
while k != Object
|
50
|
+
return true if k == ActiveRecord::Base
|
51
|
+
k = k.superclass
|
52
|
+
end
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def class_included?(class_name)
|
57
|
+
class_name.present? &&
|
58
|
+
active_record?(class_name.constantize) &&
|
59
|
+
ActiveRecord::Base.include_root_in_json
|
60
|
+
end
|
61
|
+
|
62
|
+
def create(klass, attr_hash)
|
63
|
+
if active_record?(klass)
|
64
|
+
klass.send(:instantiate, attr_hash)
|
65
|
+
else
|
66
|
+
klass.send(:new, attr_hash)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# === Options
|
72
|
+
# * +gzip+ - uses gzip before marshalling and unmarshalling. Slight speed hit,
|
73
|
+
# but can save a lot of hard drive space.
|
74
|
+
def marshal_serialize(*attrs)
|
75
|
+
options = attrs.last.is_a?(Hash) ? attrs.pop : {}
|
76
|
+
|
77
|
+
attrs.each do |attribute|
|
78
|
+
define_method "#{attribute}=" do |value|
|
79
|
+
marshalled_value = Marshal.dump(value)
|
80
|
+
marshalled_value = Zlib::Deflate.deflate(marshalled_value) if options[:gzip]
|
81
|
+
super(marshalled_value)
|
82
|
+
end
|
83
|
+
|
84
|
+
define_method attribute do
|
85
|
+
return nil if self[attribute].nil?
|
86
|
+
|
87
|
+
value = Zlib::Inflate.inflate(self[attribute]) if options[:gzip]
|
88
|
+
Marshal.load(value || self[attribute])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# === Options
|
94
|
+
# options is the last parameter (a hash):
|
95
|
+
# * +:gzip+ - uses gzip before and after serialization. Slight speed hit,
|
96
|
+
# but can save a lot of hard drive space.
|
97
|
+
# * +:instantiate+ - if false, it will return the raw decoded json and not attempt to
|
98
|
+
# instantiate ActiveRecord objects. Defaults to true.
|
99
|
+
# * +:with_indifferent_access+ - if true, it will return the raw decoded json as
|
100
|
+
# a hash with indifferent access. This can be handy because json doesn't have a concept
|
101
|
+
# of symbols, so it gets annoying when you're using a field as a key-value store
|
102
|
+
# * +:default+ - A proc that gets called when the field is null
|
103
|
+
# * +:class_name+ - If ActiveRecord::Base.include_root_in_json is false, you
|
104
|
+
# will need this option so that we can figure out which AR class to instantiate
|
105
|
+
# (not applicable if +raw+ is true)
|
106
|
+
def json_serialize(*attrs)
|
107
|
+
options = attrs.last.is_a?(Hash) ? attrs.pop : {}
|
108
|
+
options = {:instantiate => true}.merge(options)
|
109
|
+
|
110
|
+
attrs.each do |attribute|
|
111
|
+
define_method "#{attribute}=" do |value|
|
112
|
+
super(JsonSerializer.new(options).to_json(value))
|
113
|
+
end
|
114
|
+
|
115
|
+
define_method attribute do
|
116
|
+
JsonSerializer.new(options).from_json(self[attribute])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class ActiveRecord::Base
|
123
|
+
extend BetterSerialization
|
124
|
+
end
|
125
|
+
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe BetterSerialization do
|
4
|
+
before do
|
5
|
+
@order_log = OrderLog.new
|
6
|
+
@li = LineItem.new
|
7
|
+
@product = Product.new(:name => "Woot", :line_items => [@li])
|
8
|
+
@li.product = @product
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "json serialization" do
|
12
|
+
before do
|
13
|
+
@customer = Customer.new(:name => "John Spartan")
|
14
|
+
@order_log.customer_cache = @customer
|
15
|
+
@serialized_customer = @customer.to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
it "serializes the attribute" do
|
19
|
+
@order_log[:customer_cache].should == @serialized_customer
|
20
|
+
end
|
21
|
+
|
22
|
+
it "deserializes the attribute" do
|
23
|
+
@order_log.customer_cache.attributes.should == @customer.attributes
|
24
|
+
end
|
25
|
+
|
26
|
+
it "works with arrays (and gzip)" do
|
27
|
+
OrderLog.json_serialize :line_items_cache, :class_name => "LineItem", :gzip => true
|
28
|
+
@order_log.line_items_cache = [@li]
|
29
|
+
@serialized_gzip_li = Zlib::Deflate.deflate([@li].to_json)
|
30
|
+
|
31
|
+
@order_log.save
|
32
|
+
@order_log.reload
|
33
|
+
@order_log[:line_items_cache].should == @serialized_gzip_li
|
34
|
+
@order_log.line_items_cache.first.attributes.should == @li.attributes
|
35
|
+
|
36
|
+
OrderLog.marshal_serialize :line_items_cache, :gzip => true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "works with ActiveRecord::Base.include_root_in_json == true" do
|
40
|
+
ActiveRecord::Base.include_root_in_json = true
|
41
|
+
|
42
|
+
@order_log.customer_cache = @customer
|
43
|
+
@serialized_customer = @customer.to_json
|
44
|
+
|
45
|
+
@order_log[:customer_cache].should == @serialized_customer
|
46
|
+
@order_log.customer_cache.attributes.should == @customer.attributes
|
47
|
+
end
|
48
|
+
|
49
|
+
it "includes :id in serialization" do
|
50
|
+
@customer.save
|
51
|
+
|
52
|
+
@order_log.customer_cache = @customer
|
53
|
+
@serialized_customer = @customer.to_json
|
54
|
+
|
55
|
+
@order_log.customer_cache.attributes.should == @customer.attributes
|
56
|
+
@order_log.customer_cache.id.should == @customer.id
|
57
|
+
end
|
58
|
+
|
59
|
+
it "includes :id in a subclass of a subclass of ActiveRecord::Base" do
|
60
|
+
context "STI" do
|
61
|
+
before do
|
62
|
+
$DBG = true
|
63
|
+
@customer = PreferredCustomer.new(:name => "Lt. Lenina Huxley")
|
64
|
+
@order_log = OrderLog.new
|
65
|
+
end
|
66
|
+
|
67
|
+
it "includes :id when deserialized" do
|
68
|
+
@customer.save
|
69
|
+
|
70
|
+
@order_log.customer_cache = @customer
|
71
|
+
@order_log.customer_cache.id.should == @customer.id
|
72
|
+
$DBG = false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "on a non-ActiveRecord object" do
|
78
|
+
let(:directory){ Directory.new }
|
79
|
+
|
80
|
+
it "unserializes the same" do
|
81
|
+
person = Person.new(:name => "Simon Phoenix", :age => 75)
|
82
|
+
directory.people = [person]
|
83
|
+
directory.people.first.should == person
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "Marshal serialization" do
|
89
|
+
before do
|
90
|
+
@order_log.product_cache = @product
|
91
|
+
@serialized_product = Marshal.dump(@product)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "serializes the input of attribute=" do
|
95
|
+
@order_log[:product_cache].should == @serialized_product
|
96
|
+
end
|
97
|
+
|
98
|
+
it "deserializes the input of attribute=" do
|
99
|
+
# can't compare them directly 'cuz they have different object ids
|
100
|
+
@order_log.product_cache.attributes.should == @product.attributes
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "Marshal serialization with gzip" do
|
105
|
+
before do
|
106
|
+
@order_log.line_items_cache = [@li]
|
107
|
+
@serialized_gzip_li = Zlib::Deflate.deflate(Marshal.dump([@li]))
|
108
|
+
|
109
|
+
# testing putting binary data in the database
|
110
|
+
@order_log.save
|
111
|
+
@order_log.reload
|
112
|
+
end
|
113
|
+
|
114
|
+
it "serializes the input of attribute=" do
|
115
|
+
@order_log[:line_items_cache].should == @serialized_gzip_li
|
116
|
+
end
|
117
|
+
|
118
|
+
it "deserializes the input of attribute=" do
|
119
|
+
@order_log.line_items_cache.first.attributes.should == @li.attributes
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table :order_logs do |t|
|
3
|
+
t.text "customer_cache"
|
4
|
+
t.text "product_cache"
|
5
|
+
t.binary "line_items_cache"
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :customers do |t|
|
9
|
+
t.string "name"
|
10
|
+
end
|
11
|
+
|
12
|
+
create_table :products do |t|
|
13
|
+
t.string "name"
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :line_items do |t|
|
17
|
+
t.integer "product_id"
|
18
|
+
t.integer "customer_id"
|
19
|
+
end
|
20
|
+
|
21
|
+
create_table :directories do |t|
|
22
|
+
t.binary "people"
|
23
|
+
end
|
24
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
require 'activerecord'
|
7
|
+
require 'better_serialization'
|
8
|
+
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
RAILS_ENV="test"
|
14
|
+
ActiveRecord::Base.logger = Logger.new(StringIO.new) # make it think it has a logger
|
15
|
+
|
16
|
+
ActiveRecord::Base.configurations = {
|
17
|
+
"test" => {
|
18
|
+
:adapter => 'sqlite3',
|
19
|
+
:database => ":memory:"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
ActiveRecord::Base.establish_connection
|
23
|
+
silence_stream(STDOUT) {require 'schema'}
|
24
|
+
|
25
|
+
require "models/order_log"
|
26
|
+
require "models/customer"
|
27
|
+
require "models/line_item"
|
28
|
+
require "models/product"
|
29
|
+
require "models/person"
|
30
|
+
require "models/directory"
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mccraigmccraig-better_serialization
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- http://github.com/crystalcommerce
|
14
|
+
- http://github.com/rhburrows
|
15
|
+
- http://github.com/mccraigmccraig
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2010-07-15 00:00:00 +01:00
|
21
|
+
default_executable:
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
24
|
+
name: activerecord
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 19
|
32
|
+
segments:
|
33
|
+
- 2
|
34
|
+
- 3
|
35
|
+
- 8
|
36
|
+
version: 2.3.8
|
37
|
+
type: :runtime
|
38
|
+
version_requirements: *id001
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: rspec
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 15
|
48
|
+
segments:
|
49
|
+
- 1
|
50
|
+
- 2
|
51
|
+
- 8
|
52
|
+
version: 1.2.8
|
53
|
+
type: :development
|
54
|
+
version_requirements: *id002
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sqlite3-ruby
|
57
|
+
prerelease: false
|
58
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 25
|
64
|
+
segments:
|
65
|
+
- 1
|
66
|
+
- 3
|
67
|
+
- 1
|
68
|
+
version: 1.3.1
|
69
|
+
type: :development
|
70
|
+
version_requirements: *id003
|
71
|
+
description: serialize and deserialize activerecord attributes using json or zlib
|
72
|
+
email: mccraigmccraig@googlemail.com
|
73
|
+
executables: []
|
74
|
+
|
75
|
+
extensions: []
|
76
|
+
|
77
|
+
extra_rdoc_files:
|
78
|
+
- README.rdoc
|
79
|
+
files:
|
80
|
+
- .document
|
81
|
+
- .gitignore
|
82
|
+
- MIT-LICENSE
|
83
|
+
- README.rdoc
|
84
|
+
- Rakefile
|
85
|
+
- VERSION
|
86
|
+
- init.rb
|
87
|
+
- lib/better_serialization.rb
|
88
|
+
- spec/better_serialization_spec.rb
|
89
|
+
- spec/models/customer.rb
|
90
|
+
- spec/models/directory.rb
|
91
|
+
- spec/models/line_item.rb
|
92
|
+
- spec/models/order_log.rb
|
93
|
+
- spec/models/person.rb
|
94
|
+
- spec/models/product.rb
|
95
|
+
- spec/schema.rb
|
96
|
+
- spec/spec.opts
|
97
|
+
- spec/spec_helper.rb
|
98
|
+
has_rdoc: true
|
99
|
+
homepage: http://github.com/trampoline/better_serialization
|
100
|
+
licenses: []
|
101
|
+
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options:
|
104
|
+
- --charset=UTF-8
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
hash: 3
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
version: "0"
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
hash: 3
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
version: "0"
|
125
|
+
requirements: []
|
126
|
+
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 1.3.7
|
129
|
+
signing_key:
|
130
|
+
specification_version: 3
|
131
|
+
summary: json and zlib serialization for activerecord attributes
|
132
|
+
test_files:
|
133
|
+
- spec/better_serialization_spec.rb
|
134
|
+
- spec/models/customer.rb
|
135
|
+
- spec/models/directory.rb
|
136
|
+
- spec/models/line_item.rb
|
137
|
+
- spec/models/order_log.rb
|
138
|
+
- spec/models/person.rb
|
139
|
+
- spec/models/product.rb
|
140
|
+
- spec/schema.rb
|
141
|
+
- spec/spec_helper.rb
|