diff --git a/lib/gitmodel.rb b/lib/gitmodel.rb index 57fedeb..afcaf87 100644 --- a/lib/gitmodel.rb +++ b/lib/gitmodel.rb @@ -16,9 +16,12 @@ require 'gitmodel/index' require 'gitmodel/persistable' require 'gitmodel/transaction' +require 'gitmodel/serialization/yajl' +require 'gitmodel/serialization/yaml' module GitModel + DEFAULT_SERIALIZER = GitModel::Serialization::Yajl # db_root must be an existing git repo. (It can be created with create_db!) # Bare repositories aren't supported yet, it must be a normal git repo with a # working directory and a '.git' subdirectory. @@ -38,6 +41,9 @@ module GitModel mattr_accessor :memcache_servers mattr_accessor :memcache_namespace + mattr_accessor :serializer + self.serializer = DEFAULT_SERIALIZER + def self.repo @@repo = Grit::Repo.new(GitModel.db_root) end @@ -122,4 +128,13 @@ def self.head_sha(branch_name) ref = File.join(repo.git.git_dir, "refs/heads/#{branch_name}") File.exist?(ref) ? File.read(ref).chomp : nil end + + def self.attributes_filename + serializer.attributes_filename + end + + def self.filename_extension + serializer.filename_extension + end + end diff --git a/lib/gitmodel/index.rb b/lib/gitmodel/index.rb index 485608c..8e6e147 100644 --- a/lib/gitmodel/index.rb +++ b/lib/gitmodel/index.rb @@ -27,7 +27,7 @@ def attr_index(attr) end def filename - File.join(@model_class.db_subdir, '_indexes.json') + File.join(@model_class.db_subdir, "_indexes.#{GitModel.filename_extension}") end def generated?(branch = GitModel.default_branch) @@ -48,7 +48,7 @@ def save(options = {}) end data << [attr,values_and_ids] end - data = Yajl::Encoder.encode(data, nil, :pretty => true) + data = GitModel.serializer.encode(data) t.index.add(filename, data) end end diff --git a/lib/gitmodel/persistable.rb b/lib/gitmodel/persistable.rb index ed03436..c11e62a 100644 --- a/lib/gitmodel/persistable.rb +++ b/lib/gitmodel/persistable.rb @@ -124,7 +124,7 @@ def save(options = {}) transaction = options.delete(:transaction) || GitModel::Transaction.new(options) result = transaction.execute do |t| # Write the attributes to the attributes file - t.index.add(File.join(dir, 'attributes.json'), Yajl::Encoder.encode(attributes, nil, :pretty => true)) + t.index.add(File.join(dir, 'attributes.json'), GitModel.serializer.encode(attributes)) # Write the blob files blobs.each do |name, data| diff --git a/lib/gitmodel/serialization/yajl.rb b/lib/gitmodel/serialization/yajl.rb new file mode 100644 index 0000000..0d14a4b --- /dev/null +++ b/lib/gitmodel/serialization/yajl.rb @@ -0,0 +1,19 @@ +module GitModel + module Serialization + class Yajl + class << self + def filename_extension + "json" + end + + def attributes_filename + "attributes.#{filename_extension}" + end + + def encode(data) + ::Yajl::Encoder.encode(data, nil, :pretty => true) + end + end + end + end +end \ No newline at end of file diff --git a/lib/gitmodel/serialization/yaml.rb b/lib/gitmodel/serialization/yaml.rb new file mode 100644 index 0000000..551a367 --- /dev/null +++ b/lib/gitmodel/serialization/yaml.rb @@ -0,0 +1,19 @@ +module GitModel + module Serialization + class Yaml + class << self + def filename_extension + "yaml" + end + + def attributes_filename + "attributes.#{filename_extension}" + end + + def encode(data) + data.to_hash.to_yaml + end + end + end + end +end \ No newline at end of file diff --git a/spec/gitmodel/index_spec.rb b/spec/gitmodel/index_spec.rb index 5fea8cd..353bd62 100644 --- a/spec/gitmodel/index_spec.rb +++ b/spec/gitmodel/index_spec.rb @@ -27,10 +27,22 @@ @i.attr_index(:x).should == {1 => SortedSet.new(["foo", "bar"]), 2 => SortedSet.new(["baz"])} end - it "knows it's filename" do - @i.filename.should == "test_entities/_indexes.json" - end + context "with serializer" do + context "Yajl" do + it "knows it's filename" do + GitModel.serializer = GitModel::Serialization::Yajl + @i.filename.should == "test_entities/_indexes.json" + end + end + context "Yaml" do + it "knows it's filename" do + GitModel.serializer = GitModel::Serialization::Yaml + @i.filename.should == "test_entities/_indexes.yaml" + end + end + end + it "can save itself to a JSON file" do @i.save json = <<-END.strip diff --git a/spec/gitmodel/serialization/yajl_spec.rb b/spec/gitmodel/serialization/yajl_spec.rb new file mode 100644 index 0000000..2cb1219 --- /dev/null +++ b/spec/gitmodel/serialization/yajl_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +RSpec.configure do |c| + c.include RawData +end + +describe GitModel::Serialization::Yajl do + describe ".encode" do + it "should encode data as json" do + data = { + x: 1, + y: "bob", + z: [4,5,6] + } + GitModel::Serialization::Yajl.encode(data).should == + ::Yajl::Encoder.encode(data, nil, :pretty => true) + end + end + + context "set as GitModel serializer" do + before do + GitModel.serializer = GitModel::Serialization::Yajl + end + + + it "should use attributes.json as the attribute filename" do + GitModel.attributes_filename.should == "attributes.json" + end + + it "should save attributes as json" do + data = { + x: 1, + y: "bob", + z: [4,5,6] + } + + TestEntity.create!(:id => "foo", + :attributes => {:x => 1, :y => "bob", :z => [4,5,6]}) + + last_saved_entity_attributes('foo').should == Yajl::Encoder.encode(data, nil, :pretty => true) + end + end +end \ No newline at end of file diff --git a/spec/gitmodel/serialization/yaml_spec.rb b/spec/gitmodel/serialization/yaml_spec.rb new file mode 100644 index 0000000..dba238c --- /dev/null +++ b/spec/gitmodel/serialization/yaml_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +RSpec.configure do |c| + c.include RawData +end + +describe GitModel::Serialization::Yaml do + describe ".encode" do + it "should encode data as yaml" do + data = { + x: 1, + y: "bob", + z: [4,5,6] + } + GitModel::Serialization::Yaml.encode(data).should == + data.to_yaml + end + end + + context "set as GitModel serializer" do + before do + GitModel.serializer = GitModel::Serialization::Yaml + end + + + it "should use attributes.json as the attribute filename" do + GitModel.attributes_filename.should == "attributes.yaml" + end + + + it "should save attributes as yaml" do + data = { + 'x' => 1, + 'y' => "bob", + 'z' => [4,5,6] + } + + TestEntity.create!(:id => "foo", + :attributes => {:x => 1, :y => "bob", :z => [4,5,6]}) + + last_saved_entity_attributes('foo').should == data.to_yaml + end + end +end \ No newline at end of file diff --git a/spec/gitmodel_spec.rb b/spec/gitmodel_spec.rb index 69bfcc2..1183d3d 100644 --- a/spec/gitmodel_spec.rb +++ b/spec/gitmodel_spec.rb @@ -44,5 +44,10 @@ end end + describe ".serializer" do + it "should be Yajl by default" do + GitModel.serializer.should == GitModel::Serialization::Yajl + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 51a1f51..3001488 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,10 @@ RSpec.configure do |c| c.mock_with :rspec + + c.before(:each) do + GitModel.serializer = GitModel::DEFAULT_SERIALIZER + end end class TestEntity @@ -19,3 +23,10 @@ class TestEntity2 #GitModel.logger.level = ::Logger::DEBUG GitModel.memcache_servers = ['localhost'] + +module RawData + def last_saved_entity_attributes(id) + repo = Grit::Repo.new(GitModel.db_root) + (repo.commits.first.tree / File.join(TestEntity.db_subdir, id, 'attributes.json')).data + end +end \ No newline at end of file