diff --git a/lib/couchrest/mixins/validation.rb b/lib/couchrest/mixins/validation.rb index 02c2df5..cae991e 100644 --- a/lib/couchrest/mixins/validation.rb +++ b/lib/couchrest/mixins/validation.rb @@ -48,6 +48,19 @@ module CouchRest module Validation def self.included(base) + base.cattr_accessor(:auto_validation) + base.class_eval <<-EOS, __FILE__, __LINE__ + # Turn off auto validation by default + @@auto_validation = false + + # Force the auto validation for the class properties + # This feature is still not fully ported over, + # test are lacking, so please use with caution + def self.auto_validate! + self.auto_validation = true + end + EOS + base.extend(ClassMethods) base.class_eval <<-EOS, __FILE__, __LINE__ if method_defined?(:_run_save_callbacks) @@ -164,7 +177,7 @@ module CouchRest context = opts.delete(:when) if opts.has_key?(:when) context = opts.delete(:group) if opts.has_key?(:group) opts[:context] = context - opts.mergs!(defaults) unless defaults.nil? + opts.merge!(defaults) unless defaults.nil? opts end @@ -197,7 +210,7 @@ module CouchRest # def add_validator_to_context(opts, fields, klazz) fields.each do |field| - validator = klazz.new(field, opts) + validator = klazz.new(field.to_sym, opts) if opts[:context].is_a?(Symbol) unless validators.context(opts[:context]).include?(validator) validators.context(opts[:context]) << validator diff --git a/lib/couchrest/more/extended_document.rb b/lib/couchrest/more/extended_document.rb index d800ad2..c4ca6d5 100644 --- a/lib/couchrest/more/extended_document.rb +++ b/lib/couchrest/more/extended_document.rb @@ -14,11 +14,14 @@ module CouchRest # Same as CouchRest::Document but with properties and validations class ExtendedDocument < Document include CouchRest::Callbacks - include CouchRest::Mixins::DocumentQueries - include CouchRest::Mixins::Properties + include CouchRest::Mixins::DocumentQueries include CouchRest::Mixins::Views include CouchRest::Mixins::DesignDoc + def self.inherited(subklass) + subklass.send(:include, CouchRest::Mixins::Properties) + end + # Callbacks define_callbacks :save define_callbacks :destroy @@ -38,8 +41,8 @@ module CouchRest # decent time format by default. See Time#to_json def self.timestamps! class_eval <<-EOS, __FILE__, __LINE__ - property(:updated_at, :read_only => true, :cast_as => 'Time') - property(:created_at, :read_only => true, :cast_as => 'Time') + property(:updated_at, :read_only => true, :cast_as => 'Time', :auto_validation => false) + property(:created_at, :read_only => true, :cast_as => 'Time', :auto_validation => false) save_callback :before do |object| object['updated_at'] = Time.now @@ -115,7 +118,7 @@ module CouchRest # Overridden to set the unique ID. # Returns a boolean value def save_without_callbacks(bulk = false) - raise ArgumentError, "a document requires database to be saved to" unless database + raise ArgumentError, "a document requires a database to be saved to" unless database set_unique_id if new_document? && self.respond_to?(:set_unique_id) result = database.save_doc(self, bulk) result["ok"] == true diff --git a/lib/couchrest/validation/auto_validate.rb b/lib/couchrest/validation/auto_validate.rb index 87d18c0..f3eac1d 100644 --- a/lib/couchrest/validation/auto_validate.rb +++ b/lib/couchrest/validation/auto_validate.rb @@ -6,22 +6,20 @@ module CouchRest class Property # flag letting us know if we already checked the autovalidation settings attr_accessor :autovalidation_check + @@autovalidation_check = false end module Validation - module AutoValidate + module AutoValidate - # Turn off auto validation by default - def auto_validation - @@auto_validation ||= false - end - - # Force the auto validation for the class properties - # This feature is still not fully ported over, - # test are lacking, so please use with caution - def auto_validate! - @@auto_validation = true - end + # # Force the auto validation for the class properties + # # This feature is still not fully ported over, + # # test are lacking, so please use with caution + # def auto_validate! + # require 'ruby-debug' + # debugger + # auto_validation = true + # end # adds message for validator def options_with_message(base_options, property, validator_name) @@ -93,9 +91,7 @@ module CouchRest # It is just shortcut if only one validation option is set # def auto_generate_validations(property) - return unless property.options - return unless property.autovalidation_check || auto_validation || (property.options && property.options.has_key?(:auto_validation) && property.options[:auto_validation]) - + return unless (property.autovalidation_check && self.auto_validation && (property.options && property.options.has_key?(:auto_validation) && property.options[:auto_validation])) # value is set by the storage system opts = {} opts[:context] = property.options[:validates] if property.options.has_key?(:validates) diff --git a/lib/couchrest/validation/validators/numeric_validator.rb b/lib/couchrest/validation/validators/numeric_validator.rb index 47ce05b..57a711f 100644 --- a/lib/couchrest/validation/validators/numeric_validator.rb +++ b/lib/couchrest/validation/validators/numeric_validator.rb @@ -40,7 +40,7 @@ module CouchRest value = target.send(field_name) return true if @options[:allow_nil] && value.nil? - value = value.kind_of?(BigDecimal) ? value.to_s('F') : value.to_s + value = value.kind_of?(Float) ? value.to_s('F') : value.to_s error_message = @options[:message] precision = @options[:precision] diff --git a/spec/couchrest/more/casted_model_spec.rb b/spec/couchrest/more/casted_model_spec.rb index f9ddeb3..941267b 100644 --- a/spec/couchrest/more/casted_model_spec.rb +++ b/spec/couchrest/more/casted_model_spec.rb @@ -1,19 +1,21 @@ require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') require File.join(FIXTURE_PATH, 'more', 'card') +class WithCastedModelMixin < Hash + include CouchRest::CastedModel + property :name +end + +class DummyModel < CouchRest::ExtendedDocument + use_database TEST_SERVER.default_database + raise "Default DB not set" if TEST_SERVER.default_database.nil? + property :casted_attribute, :cast_as => 'WithCastedModelMixin' +end + + describe CouchRest::CastedModel do - class WithCastedModelMixin < Hash - include CouchRest::CastedModel - property :name - end - - class DummyModel < CouchRest::ExtendedDocument - property :casted_attribute, :cast_as => 'WithCastedModelMixin' - end - describe "A non hash class including CastedModel" do - it "should fail raising and include error" do lambda do class NotAHashButWithCastedModelMixin @@ -23,7 +25,6 @@ describe CouchRest::CastedModel do end.should raise_error end - end describe "isolated" do @@ -37,7 +38,6 @@ describe CouchRest::CastedModel do end describe "casted as attribute" do - before(:each) do @obj = DummyModel.new(:casted_attribute => {:name => 'whatever'}) @casted_obj = @obj.casted_attribute @@ -54,6 +54,30 @@ describe CouchRest::CastedModel do it "should know who casted it" do @casted_obj.casted_by.should == @obj end + end + + describe "saved document with casted models" do + before(:each) do + @obj = DummyModel.new(:casted_attribute => {:name => 'whatever'}) + @obj.save + end + + it "should be able to load with the casted models" do + casted_obj = @obj.casted_attribute + casted_obj.should_not be_nil + casted_obj.should be_an_instance_of(WithCastedModelMixin) + end + + it "should have defined getters for the casted model" do + casted_obj = @obj.casted_attribute + casted_obj.name.should == "whatever" + end + + it "should have defined setters for the casted model" do + casted_obj = @obj.casted_attribute + casted_obj.name = "test" + casted_obj.name.should == "test" + end end diff --git a/spec/couchrest/more/extended_doc_spec.rb b/spec/couchrest/more/extended_doc_spec.rb index c1c10ef..e406182 100644 --- a/spec/couchrest/more/extended_doc_spec.rb +++ b/spec/couchrest/more/extended_doc_spec.rb @@ -1,15 +1,15 @@ require File.dirname(__FILE__) + '/../../spec_helper' -class WithDefaultValues < CouchRest::ExtendedDocument - use_database TEST_SERVER.default_database - property :preset, :default => {:right => 10, :top_align => false} - property :set_by_proc, :default => Proc.new{Time.now}, :cast_as => 'Time' - property :name - timestamps! -end - describe "ExtendedDocument" do + class WithDefaultValues < CouchRest::ExtendedDocument + use_database TEST_SERVER.default_database + property :preset, :default => {:right => 10, :top_align => false} + property :set_by_proc, :default => Proc.new{Time.now}, :cast_as => 'Time' + property :name + timestamps! + end + before(:each) do @obj = WithDefaultValues.new end @@ -32,6 +32,7 @@ describe "ExtendedDocument" do it "should define the updated_at and created_at getters and set the values" do @obj.save obj = WithDefaultValues.get(@obj.id) + obj.should be_an_instance_of(WithDefaultValues) obj.created_at.should be_an_instance_of(Time) obj.updated_at.should be_an_instance_of(Time) obj.created_at.to_s.should == @obj.updated_at.to_s diff --git a/spec/couchrest/more/property_spec.rb b/spec/couchrest/more/property_spec.rb index ef44141..05b7d91 100644 --- a/spec/couchrest/more/property_spec.rb +++ b/spec/couchrest/more/property_spec.rb @@ -39,7 +39,8 @@ describe "ExtendedDocument properties" do @card.updated_at.should be_nil # :emo: hack for autospec Card.use_database(TEST_SERVER.default_database) if @card.database.nil? - @card.save + @card.save #.should be_true + p @card.errors @card.created_at.should_not be_nil @card.updated_at.should_not be_nil end @@ -65,14 +66,17 @@ describe "ExtendedDocument properties" do @invoice.clear @invoice.should_not be_valid @invoice.errors.should_not be_empty - @invoice.errors.on(:client_name).should == ["Client name must not be blank"] + @invoice.errors.on(:client_name).first.should == "Client name must not be blank" @invoice.errors.on(:employee_name).should_not be_empty end it "should let you set an error message" do @invoice.location = nil @invoice.valid? - @invoice.errors.on(:location).first.should == "Hey stupid!, you forgot the location" + # require 'ruby-debug' + # debugger + # p @invoice.class.validators.map{|v| v.message}.inspect + @invoice.errors.on(:location).should == ["Hey stupid!, you forgot the location"] end it "should validate before saving" do diff --git a/spec/fixtures/more/card.rb b/spec/fixtures/more/card.rb index b57bb82..46307ad 100644 --- a/spec/fixtures/more/card.rb +++ b/spec/fixtures/more/card.rb @@ -1,6 +1,8 @@ class Card < CouchRest::ExtendedDocument # Include the validation module to get access to the validation methods include CouchRest::Validation + # set the auto_validation before defining the properties + auto_validate! # Set the default database to use use_database TEST_SERVER.default_database @@ -15,6 +17,4 @@ class Card < CouchRest::ExtendedDocument # Validation validates_present :first_name - auto_validate! - end \ No newline at end of file