diff --git a/lib/curator.rb b/lib/curator.rb index b78019a..aaf5a3e 100644 --- a/lib/curator.rb +++ b/lib/curator.rb @@ -1,5 +1,6 @@ require 'rubygems' +require 'curator/mapper' require 'curator/migration' require 'curator/migrator' require 'curator/model' diff --git a/lib/curator/mapper.rb b/lib/curator/mapper.rb new file mode 100644 index 0000000..87ccd41 --- /dev/null +++ b/lib/curator/mapper.rb @@ -0,0 +1,27 @@ +module Curator + class Mapper + def initialize(field_name, options) + @field_name = field_name + @serialize_function = options[:serialize] + @deserialize_function = options[:deserialize] + end + + def deserialize(attributes) + _map(attributes, @deserialize_function) + end + + def serialize(attributes) + _map(attributes, @serialize_function) + end + + def _map(attributes, mapping_function) + current_value = attributes[@field_name] + if current_value && mapping_function + mapped_value = mapping_function.call(current_value) + attributes.merge(@field_name => mapped_value) + else + attributes + end + end + end +end diff --git a/lib/curator/repository.rb b/lib/curator/repository.rb index a78aaf7..d440f86 100644 --- a/lib/curator/repository.rb +++ b/lib/curator/repository.rb @@ -55,6 +55,14 @@ def klass name.to_s.gsub("Repository", "").constantize end + def map(field_name, options) + _mappers << Mapper.new(field_name, options) + end + + def _mappers + @mappers ||= [] + end + def migrator @migrator ||= Curator::Migrator.new(collection_name) end @@ -82,7 +90,8 @@ def save_without_timestamps(object) end def serialize(object) - object.instance_values + attributes = object.instance_values.with_indifferent_access + _mappers.inject(attributes) { |attrs, mapper| mapper.serialize(attrs) } end def _build_finder_methods(field_name) @@ -106,7 +115,8 @@ def _find_by_index(collection_name, field_name, value) end def deserialize(attributes) - klass.new(attributes) + mapped_attributes = _mappers.inject(attributes) { |attrs, mapper| mapper.deserialize(attrs) } + klass.new(mapped_attributes) end def _deserialize(id, data) diff --git a/spec/curator/mapper_spec.rb b/spec/curator/mapper_spec.rb new file mode 100644 index 0000000..7c7c4f7 --- /dev/null +++ b/spec/curator/mapper_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe Curator::Mapper do + describe "serialize" do + it "serializes a field" do + mapper = Curator::Mapper.new(:foo, :serialize => lambda { |v| v + 1 }) + mapper.serialize(:foo => 1).should == {:foo => 2} + end + + it "ignores other fields" do + mapper = Curator::Mapper.new(:foo, :serialize => lambda { |v| v + 1 }) + mapper.serialize(:bar => 1).should == {:bar => 1} + end + + it "leaves fields alone if there is no option" do + mapper = Curator::Mapper.new(:foo, {}) + mapper.serialize(:foo => 1).should == {:foo => 1} + end + end + + describe "deserialize" do + it "deserializes a field" do + mapper = Curator::Mapper.new(:foo, :deserialize => lambda { |v| v + 1 }) + mapper.deserialize(:foo => 1).should == {:foo => 2} + end + + it "ignores other fields" do + mapper = Curator::Mapper.new(:foo, :deserialize => lambda { |v| v + 1 }) + mapper.deserialize(:bar => 1).should == {:bar => 1} + end + + it "leaves fields alone if there is no option" do + mapper = Curator::Mapper.new(:foo, {}) + mapper.deserialize(:foo => 1).should == {:foo => 1} + end + end +end diff --git a/spec/curator/repository_spec.rb b/spec/curator/repository_spec.rb index ace4922..8c4701e 100644 --- a/spec/curator/repository_spec.rb +++ b/spec/curator/repository_spec.rb @@ -306,4 +306,42 @@ def migrate(hash) repository.save_without_timestamps(model).should == model end end + + describe "mapping" do + it "runs serialize and deserialize" do + repository = test_repository do + map :some_field, :serialize => lambda { |i| (i + 1).to_s }, :deserialize => lambda { |str| "5#{str}".to_i } + end + + model = TestModel.new(:some_field => 3) + repository.save(model) + + found_model = repository.find_by_id(model.id) + found_model.some_field.should == 54 + end + + it "does not change value when no serialize is specified" do + repository = test_repository do + map :some_field, :deserialize => lambda { |str| Date.parse(str) } + end + + model = TestModel.new(:some_field => Date.today) + repository.save(model) + + found_model = repository.find_by_id(model.id) + found_model.some_field.should == Date.today + end + + it "leaves value as is when no deserialize is specified" do + repository = test_repository do + map :some_field, :serialize => lambda { |date| date.year } + end + + model = TestModel.new(:some_field => Date.today) + repository.save(model) + + found_model = repository.find_by_id(model.id) + found_model.some_field.should == Date.today.year + end + end end