From 8ac6b78170398a3029913afc7c18cf811c6801b9 Mon Sep 17 00:00:00 2001 From: Chris Anderson Date: Thu, 2 Oct 2008 14:11:04 -0700 Subject: [PATCH] default values and lambda unique_ids --- lib/couchrest/core/model.rb | 28 ++++++++++++-- spec/couchrest/core/model_spec.rb | 61 +++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/lib/couchrest/core/model.rb b/lib/couchrest/core/model.rb index f9151e4..811d0fd 100644 --- a/lib/couchrest/core/model.rb +++ b/lib/couchrest/core/model.rb @@ -50,6 +50,11 @@ module CouchRest # instantiates the hash by converting all the keys to strings. def initialize keys = {} super() + if self.class.default + self.class.default.each do |k,v| + self[k.to_s] = v + end + end keys.each do |k,v| self[k.to_s] = v end @@ -62,6 +67,7 @@ module CouchRest # this is the CouchRest::Database that model classes will use unless # they override it with use_database attr_accessor :default_database + attr_accessor :template # override the CouchRest::Model-wide default_database def use_database db @@ -107,6 +113,14 @@ module CouchRest end end end + + def default + @default + end + + def set_default hash + @default = hash + end # Automatically set updated_at and created_at fields # on the document whenever saving occurs. CouchRest uses a pretty @@ -127,9 +141,17 @@ module CouchRest # must be globally unique across all document types which share a # database, so if you'd like to scope uniqueness to this class, you # should use the class name as part of the unique id. - def unique_id method - define_method :set_unique_id do - self['_id'] ||= self.send(method) + def unique_id method = nil, &block + if method + define_method :set_unique_id do + self['_id'] ||= self.send(method) + end + elsif block + define_method :set_unique_id do + uniqid = block.call(self) + raise ArgumentError, "unique_id block must not return nil" if uniqid.nil? + self['_id'] ||= uniqid + end end end diff --git a/spec/couchrest/core/model_spec.rb b/spec/couchrest/core/model_spec.rb index 91ac358..42b8f3c 100644 --- a/spec/couchrest/core/model_spec.rb +++ b/spec/couchrest/core/model_spec.rb @@ -1,7 +1,17 @@ require File.dirname(__FILE__) + '/../../spec_helper' class Basic < CouchRest::Model +end +class WithTemplate < CouchRest::Model + unique_id do |model| + model['important-field'] + end + set_default({ + :preset => 'value', + 'more-template' => [1,2,3] + }) + key_accessor :preset end class Article < CouchRest::Model @@ -105,6 +115,15 @@ describe CouchRest::Model do end end + describe "a model with template values" do + before(:all) do + @tmpl = WithTemplate.new + end + it "should have fields set when new" do + @tmpl.preset.should == 'value' + end + end + describe "getting a model" do before(:all) do @art = Article.new(:title => 'All About Getting') @@ -184,6 +203,48 @@ describe CouchRest::Model do end end + describe "saving a model with a unique_id lambda" do + before(:each) do + @templated = WithTemplate.new + @old = WithTemplate.get('very-important') rescue nil + @old.destroy if @old + end + + it "should require the field" do + lambda{@templated.save}.should raise_error + @templated['important-field'] = 'very-important' + @templated.save.should == true + end + + it "should save with the id" do + @templated['important-field'] = 'very-important' + @templated.save.should == true + t = WithTemplate.get('very-important') + t.should == @templated + end + + it "should not change the id on update" do + @templated['important-field'] = 'very-important' + @templated.save.should == true + @templated['important-field'] = 'not-important' + @templated.save.should == true + t = WithTemplate.get('very-important') + t.should == @templated + end + + it "should raise an error when the id is taken" do + @templated['important-field'] = 'very-important' + @templated.save.should == true + lambda{WithTemplate.new('important-field' => 'very-important').save}.should raise_error + end + + it "should set the id" do + @templated['important-field'] = 'very-important' + @templated.save.should == true + @templated.id.should == 'very-important' + end + end + describe "a model with timestamps" do before(:all) do @art = Article.new(:title => "Saving this")