From 90f0c4577833c83d09cd0b22553084e41576278f Mon Sep 17 00:00:00 2001 From: Adam Meehan Date: Wed, 22 Sep 2010 07:07:36 +1000 Subject: [PATCH] preliminary Mongoid support --- Gemfile | 2 + Gemfile.lock | 13 ++++ lib/validates_timeliness/orm/mongoid.rb | 33 ++++++++++ spec/validates_timeliness/orm/mongoid_spec.rb | 66 +++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 lib/validates_timeliness/orm/mongoid.rb create mode 100644 spec/validates_timeliness/orm/mongoid_spec.rb diff --git a/Gemfile b/Gemfile index 5b8b80b..2ee43bb 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,8 @@ group :test do gem 'ZenTest' gem 'rails', '3.0.0' gem 'sqlite3-ruby', :require => 'sqlite3' + gem 'mongoid', '2.0.0.beta.17' + gem 'bson_ext', '1.0.4' gem 'ruby-debug' gem 'rspec', '>= 2.0.0.beta.17' gem 'rspec-rails', '>= 2.0.0.beta.17' diff --git a/Gemfile.lock b/Gemfile.lock index f5f8c73..9552245 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -31,6 +31,8 @@ GEM activesupport (3.0.0) arel (1.0.1) activesupport (~> 3.0.0) + bson (1.0.4) + bson_ext (1.0.4) builder (2.1.2) columnize (0.3.1) diff-lcs (1.1.2) @@ -43,6 +45,14 @@ GEM mime-types treetop (>= 1.4.5) mime-types (1.16) + mongo (1.0.7) + bson (>= 1.0.4) + mongoid (2.0.0.beta.17) + activemodel (~> 3.0.0) + bson (= 1.0.4) + mongo (= 1.0.7) + tzinfo (~> 0.3.22) + will_paginate (~> 3.0.pre) nokogiri (1.4.3.1) polyglot (0.3.1) rack (1.2.1) @@ -90,12 +100,15 @@ GEM treetop (1.4.8) polyglot (>= 0.3.1) tzinfo (0.3.23) + will_paginate (3.0.pre2) PLATFORMS ruby DEPENDENCIES ZenTest + bson_ext (= 1.0.4) + mongoid (= 2.0.0.beta.17) rails (= 3.0.0) rspec (>= 2.0.0.beta.17) rspec-rails (>= 2.0.0.beta.17) diff --git a/lib/validates_timeliness/orm/mongoid.rb b/lib/validates_timeliness/orm/mongoid.rb new file mode 100644 index 0000000..5bc0248 --- /dev/null +++ b/lib/validates_timeliness/orm/mongoid.rb @@ -0,0 +1,33 @@ +module ValidatesTimeliness + module ORM + module Mongoid + extend ActiveSupport::Concern + # You need define the fields before you define the validations. + + module ClassMethods + def timeliness_validation_for(attr_names, type) + super + attr_names.each { |attr_name| define_timeliness_write_method(attr_name, type, false) } + end + + def define_timeliness_write_method(attr_name, type, timezone_aware) + method_body, line = <<-EOV, __LINE__ + 1 + def #{attr_name}=(value) + @attributes_cache ||= {} + @attributes_cache["_#{attr_name}_before_type_cast"] = value + #{ "value = ValidatesTimeliness::Parser.parse(value, :#{type}) if value.is_a?(String)" if ValidatesTimeliness.use_plugin_parser } + write_attribute(:#{attr_name}, value) + end + EOV + class_eval(method_body, __FILE__, line) + end + end + end + end +end + +module Mongoid::Document + include ValidatesTimeliness::HelperMethods + include ValidatesTimeliness::AttributeMethods + include ValidatesTimeliness::ORM::Mongoid +end diff --git a/spec/validates_timeliness/orm/mongoid_spec.rb b/spec/validates_timeliness/orm/mongoid_spec.rb new file mode 100644 index 0000000..9ad96f3 --- /dev/null +++ b/spec/validates_timeliness/orm/mongoid_spec.rb @@ -0,0 +1,66 @@ +require 'spec_helper' + +require 'mongoid' +require 'validates_timeliness/orm/mongoid' + +Mongoid.configure do |config| + name = "validates_timeliness_test" + host = "localhost" + config.master = Mongo::Connection.new.db(name) + config.persist_in_safe_mode = false +end + +describe ValidatesTimeliness, 'Mongoid' do + + class Article + ::ValidatesTimeliness.use_plugin_parser = true + include Mongoid::Document + field :publish_date, :type => Date + field :publish_time, :type => Time + field :publish_datetime, :type => DateTime + validates_date :publish_date + validates_time :publish_time + validates_datetime :publish_datetime + ::ValidatesTimeliness.use_plugin_parser = false + end + + it 'should define _timeliness_raw_value_for instance method' do + Article.instance_methods.should include('_timeliness_raw_value_for') + end + + context "attribute write method" do + it 'should cache attribute raw value' do + r = Article.new + r.publish_datetime = date_string = '2010-01-01' + r._timeliness_raw_value_for(:publish_datetime).should == date_string + end + + context "with plugin parser" do + before :all do + ValidatesTimeliness.use_plugin_parser = true + end + + it 'should parse a string value' do + ValidatesTimeliness::Parser.should_receive(:parse) + r = Article.new + r.publish_date = '2010-01-01' + end + + it 'should parse string into Time value' do + r = Article.new + r.publish_datetime = '2010-01-01 12:00' + r.publish_datetime.should == Time.utc(2010,1,1,12,0) + end + + after :all do + ValidatesTimeliness.use_plugin_parser = false + end + end + end + + context "before_type_cast method" do + it 'should not be defined if ORM does not support it' do + Article.instance_methods(false).should_not include("birth_datetime_before_type_cast") + end + end +end