Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial conversion from dm-devise

  • Loading branch information...
commit 872f7a80e44c783b159a76bb79d53c18e94acf90 0 parents
@kristianmandrup authored
Showing with 920 additions and 0 deletions.
  1. +5 −0 .document
  2. +5 −0 .gitignore
  3. +12 −0 Gemfile
  4. +146 −0 Gemfile.lock
  5. +20 −0 LICENSE
  6. +84 −0 README.rdoc
  7. +65 −0 Rakefile
  8. +17 −0 lib/generators/mongo_mapper/devise_generator.rb
  9. +5 −0 lib/mm-devise/version.rb
  10. +27 −0 lib/mongo_mapper/orm/mongo_mapper.rb
  11. +72 −0 lib/mongo_mapper/orm/mongo_mapper/compatibility.rb
  12. +6 −0 lib/mongo_mapper/orm/mongo_mapper/date_time.rb
  13. +55 −0 lib/mongo_mapper/orm/mongo_mapper/mm-validations.rb
  14. +31 −0 lib/mongo_mapper/orm/mongo_mapper/schema.rb
  15. +63 −0 lib/mongo_mapper/orm/mongo_mapper_active_model.rb
  16. +24 −0 test/mongo_mapper/compatibility_test.rb
  17. +29 −0 test/orm/mongo_mapper.rb
  18. +8 −0 test/orm/mongo_mapper_active_model.rb
  19. +46 −0 test/overrides/mm_validations_test.rb
  20. +50 −0 test/overrides/mongo_mapper_test.rb
  21. +10 −0 test/rails_app/app/mongo_mapper/admin.rb
  22. +25 −0 test/rails_app/app/mongo_mapper/shim.rb
  23. +26 −0 test/rails_app/app/mongo_mapper/user.rb
  24. +11 −0 test/rails_app/app/mongo_mapper_active_model/admin.rb
  25. +13 −0 test/rails_app/app/mongo_mapper_active_model/user.rb
  26. +37 −0 test/rails_app/config/application.rb
  27. +5 −0 test/rails_app/config/environment.rb
  28. +23 −0 test/test_helper.rb
5 .document
@@ -0,0 +1,5 @@
+README.rdoc
+lib/**/*.rb
+bin/*
+features/**/*.feature
+LICENSE
5 .gitignore
@@ -0,0 +1,5 @@
+coverage/*
+.bundle
+rdoc/*
+pkg
+log
12 Gemfile
@@ -0,0 +1,12 @@
+source :rubygems
+
+gem "rails", :git => "git://github.com/rails/rails.git"
+
+gem "warden", "0.10.7"
+gem "webrat", "0.7.0"
+gem "mocha", :require => false
+gem "bcrypt-ruby", :require => "bcrypt"
+gem "oauth2"
+
+gem 'mongo_mapper', '>= 0.8.2'
+
146 Gemfile.lock
@@ -0,0 +1,146 @@
+GIT
+ remote: git://github.com/datamapper/dm-rails
+ revision: e2ee760
+ specs:
+ dm-rails (1.0.0)
+ actionpack (~> 3.0.0.beta3)
+ activesupport (~> 3.0.0.beta3)
+ dm-active_model (~> 1.0.0)
+ dm-core (~> 1.0.0)
+ railties (~> 3.0.0.beta3)
+
+GIT
+ remote: git://github.com/rails/rails.git
+ revision: 4952a80
+ specs:
+ actionmailer (3.0.0.rc)
+ actionpack (= 3.0.0.rc)
+ mail (~> 2.2.5)
+ actionpack (3.0.0.rc)
+ activemodel (= 3.0.0.rc)
+ activesupport (= 3.0.0.rc)
+ builder (~> 2.1.2)
+ erubis (~> 2.6.6)
+ i18n (~> 0.4.1)
+ rack (~> 1.2.1)
+ rack-mount (~> 0.6.9)
+ rack-test (~> 0.5.4)
+ tzinfo (~> 0.3.22)
+ activemodel (3.0.0.rc)
+ activesupport (= 3.0.0.rc)
+ builder (~> 2.1.2)
+ i18n (~> 0.4.1)
+ activerecord (3.0.0.rc)
+ activemodel (= 3.0.0.rc)
+ activesupport (= 3.0.0.rc)
+ arel (~> 0.4.0)
+ tzinfo (~> 0.3.22)
+ activeresource (3.0.0.rc)
+ activemodel (= 3.0.0.rc)
+ activesupport (= 3.0.0.rc)
+ activesupport (3.0.0.rc)
+ rails (3.0.0.rc)
+ actionmailer (= 3.0.0.rc)
+ actionpack (= 3.0.0.rc)
+ activerecord (= 3.0.0.rc)
+ activeresource (= 3.0.0.rc)
+ activesupport (= 3.0.0.rc)
+ bundler (>= 1.0.0.rc.1)
+ railties (= 3.0.0.rc)
+ railties (3.0.0.rc)
+ actionpack (= 3.0.0.rc)
+ activesupport (= 3.0.0.rc)
+ rake (>= 0.8.3)
+ thor (~> 0.14.0)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ abstract (1.0.0)
+ addressable (2.1.2)
+ arel (0.4.0)
+ activesupport (>= 3.0.0.beta)
+ bcrypt-ruby (2.1.2)
+ builder (2.1.2)
+ data_objects (0.10.2)
+ addressable (~> 2.1)
+ dm-active_model (1.0.0)
+ activemodel (~> 3.0.0.beta3)
+ dm-core (~> 1.0.0)
+ dm-core (1.0.0)
+ addressable (~> 2.1)
+ extlib (~> 0.9.15)
+ dm-do-adapter (1.0.0)
+ data_objects (~> 0.10.1)
+ dm-core (~> 1.0.0)
+ dm-migrations (1.0.0)
+ dm-core (~> 1.0.0)
+ dm-serializer (1.0.0)
+ dm-core (~> 1.0.0)
+ fastercsv (~> 1.5.3)
+ json_pure (~> 1.4.3)
+ dm-sqlite-adapter (1.0.0)
+ dm-do-adapter (~> 1.0.0)
+ do_sqlite3 (~> 0.10.2)
+ dm-timestamps (1.0.0)
+ dm-core (~> 1.0.0)
+ dm-validations (1.0.0)
+ dm-core (~> 1.0.0)
+ do_sqlite3 (0.10.2)
+ data_objects (= 0.10.2)
+ erubis (2.6.6)
+ abstract (>= 1.0.0)
+ extlib (0.9.15)
+ faraday (0.4.6)
+ addressable (>= 2.1.1)
+ rack (>= 1.0.1)
+ fastercsv (1.5.3)
+ i18n (0.4.1)
+ json_pure (1.4.3)
+ mail (2.2.5)
+ activesupport (>= 2.3.6)
+ mime-types
+ treetop (>= 1.4.5)
+ mime-types (1.16)
+ mocha (0.9.8)
+ rake
+ multi_json (0.0.4)
+ nokogiri (1.4.2)
+ oauth2 (0.0.10)
+ faraday (~> 0.4.1)
+ multi_json (>= 0.0.4)
+ polyglot (0.3.1)
+ rack (1.2.1)
+ rack-mount (0.6.9)
+ rack (>= 1.0.0)
+ rack-test (0.5.4)
+ rack (>= 1.0)
+ rake (0.8.7)
+ thor (0.14.0)
+ treetop (1.4.8)
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.22)
+ warden (0.10.7)
+ rack (>= 1.0.0)
+ webrat (0.7.0)
+ nokogiri (>= 1.2.0)
+ rack (>= 1.0)
+ rack-test (>= 0.5.3)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ bcrypt-ruby
+ dm-core (~> 1.0.0)
+ dm-migrations (~> 1.0.0)
+ dm-rails (~> 1.0.0)!
+ dm-serializer (~> 1.0.0)
+ dm-sqlite-adapter (~> 1.0.0)
+ dm-timestamps (~> 1.0.0)
+ dm-validations (~> 1.0.0)
+ mocha
+ oauth2
+ rails!
+ warden (= 0.10.7)
+ webrat (= 0.7.0)
20 LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2010 Kristian Mandrup
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
84 README.rdoc
@@ -0,0 +1,84 @@
+= mm-devise
+
+== Note
+*Aug 5, 2010*
+
+This gem has not been tested but is currently just a quick "hack" to use *dm-devise* by Jared Morgan as a template
+for a Mongo Mapper integration with Devise. Please assist in this effort in you have knowledge of the internals of Devise and Mongo Mapper.
+
+== Intro
+
+mm-devise will (hopefully!) let you use devise (http://github.com/plataformatec/devise) with MongoMapper.
+
+The gem gives you the options of 2 ORM setups depending on what library you wish to use for validations:
+
++Note: Not sure if this is approach needed for MongoMapper!?+
+
+:mongo_mapper::
+ Default.
+:mongo_mapper_active_model::
+ Uses ActiveModel::Validations.
+
+ The advantage to this is ActiveModel's I18n support for error messages, and
+ it uses the same validations lib as devise does by default.
+
+mm-devise is intended for use with Rails 3 and devise 1.1.
+It may work with earlier versions, but it's not been tested
+
+This README only covers dm-devise specifics.
+Make sure to read the devise README http://github.com/plataformatec/devise/blob/master/README.rdoc
+
+== Installation
+
+Add devise, dm-devise and dm gems to your Gemfile. The following gems are
+required (although devise version may differ)
+
+ gem 'mongo_mapper', '>= 0.8.2'
+ gem 'devise', '~> 1.1.1'
+ gem 'mm-devise', '>= 1.1.0'
+
+Run the generator:
+
+ rails generate devise:install
+
+The generator will install an initializer which describes ALL Devise's
+configuration options and you MUST take a look at it. Make sure to specify
+either mongo_mapper or data_mapper_active_model
+(ActiveModel::Validations) as the orm in the configuration file.
+
+To add Devise to any of your models using the generator:
+
+ rails generate mongo_mapper:devise MODEL
+
+Read the README for devise at http://github.com/plataformatec/devise/blob/master/README.rdoc
+
+== TODO
+
+* Example app
+* Rails templates
+
+== Note on Patches/Pull Requests
+
+* Fork the project.
+* Make your feature addition or bug fix.
+* Add tests for it. This is important so I don't break it in a
+ future version unintentionally.
+* Commit, do not mess with rakefile, version, or history.
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
+* Send me a pull request. Bonus points for topic branches.
+
+== Maintainers
+
+== Contributors
+
+== Bugs and Feedback
+
+For mm-devise specific issues, please create an issue on GitHub at:
+
+http://github.com/kristianmandrup/mm-devise/issues
+
+== Copyright
+
+Copyright (c) 2010 Jared Morgan. See LICENSE for details.
+
+Note: I, Kristian Mandrup used dm-devise as a template for creating this gem.
65 Rakefile
@@ -0,0 +1,65 @@
+# encoding: UTF-8
+
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+require File.join(File.dirname(__FILE__), 'lib', 'mm-devise', 'version')
+
+desc 'Default: run tests for all MongoMapper ORM setups.'
+task :default => :pre_commit
+
+desc 'Run Devise tests for all MongoMapper ORM setups.'
+task :pre_commit do
+ Dir[File.join(File.dirname(__FILE__), 'test', 'orm', '*.rb')].each do |file|
+ orm = File.basename(file).split(".").first
+ ENV['DEVISE_PATH'] ||= File.expand_path('../devise')
+ system "rake test DEVISE_ORM=#{orm} DEVISE_PATH=#{ENV['DEVISE_PATH']}"
+ end
+end
+
+desc 'Run Devise tests using MongoMapper. Specify path to devise with DEVISE_PATH'
+Rake::TestTask.new(:test) do |test|
+ ENV['DEVISE_ORM'] ||= 'mongo_mapper'
+ ENV['DEVISE_PATH'] ||= File.expand_path('../devise')
+ unless File.exist?(ENV['DEVISE_PATH'])
+ puts "Specify the path to devise (e.g. rake DEVISE_PATH=/path/to/devise). Not found at #{ENV['DEVISE_PATH']}"
+ exit
+ end
+ test.libs << 'lib' << 'test'
+ test.libs << "#{ENV['DEVISE_PATH']}/lib"
+ test.libs << "#{ENV['DEVISE_PATH']}/test"
+ test.test_files = FileList["#{ENV['DEVISE_PATH']}/test/**/*_test.rb"] + FileList['test/**/*_test.rb']
+ test.verbose = true
+end
+
+task :test => :check_dependencies
+
+desc 'Generate documentation for dm-devise.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'mm-devise #{version}'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README.rdoc')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+begin
+ require 'jeweler'
+ Jeweler::Tasks.new do |gem|
+ gem.name = "mm-devise"
+ gem.version = MongoMapper::Devise::VERSION.dup
+ gem.summary = %Q{Support for using MongoMapper ORM with devise}
+ gem.description = %Q{dm-devise adds MongoMapper support to devise (http://github.com/plataformatec/devise) for authentication support for Rails}
+ gem.email = "jmorgan@morgancreative.net"
+ gem.homepage = "http://github.com/kristianmandrup/mm-devise"
+ gem.authors = ["Kristian Mandrup"]
+ gem.add_dependency 'mongo_mapper', '>= 0.8.2'
+ gem.add_dependency 'devise'
+ gem.add_dependency 'warden', '~> 0.10.7'
+ gem.add_dependency 'bcrypt-ruby', '~> 2.1.2'
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
+ end
+ Jeweler::GemcutterTasks.new
+rescue LoadError
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
+end
17 lib/generators/mongo_mapper/devise_generator.rb
@@ -0,0 +1,17 @@
+require 'generators/devise/orm_helpers'
+
+module MongoMapper
+ module Generators
+ class DeviseGenerator < Rails::Generators::NamedBase
+ include Devise::Generators::OrmHelpers
+
+ def generate_model
+ invoke "mongo_mapper:model", [name] unless model_exists?
+ end
+
+ def inject_devise_content
+ inject_into_file model_path, model_contents, :after => "include MongoMapper::Document\n"
+ end
+ end
+ end
+end
5 lib/mm-devise/version.rb
@@ -0,0 +1,5 @@
+module DataMapper
+ module Devise
+ VERSION = '1.1.1'.freeze
+ end
+end
27 lib/mongo_mapper/orm/mongo_mapper.rb
@@ -0,0 +1,27 @@
+require 'devise/orm/mongo_mapper/compatibility'
+require 'devise/orm/mongo_mapper/schema'
+require 'devise/orm/mongo_mapper/date_time'
+require 'devise/orm/mongo_mapper/mm-validations'
+
+module Devise
+ module Orm
+ module MongoMapper
+ module Hook
+ def devise_modules_hook!
+ extend Schema
+ include Compatibility
+ yield
+ return unless Devise.apply_schema
+ devise_modules.each { |m| send(m) if respond_to?(m, true) }
+ end
+ end
+ end
+ end
+end
+
+module MongoMapper
+ module Document
+ extend ::Devise::Models
+ extend ::Devise::Orm::MongoMapper::Hook
+ end
+end
72 lib/mongo_mapper/orm/mongo_mapper/compatibility.rb
@@ -0,0 +1,72 @@
+module Devise
+ module Orm
+ module MongoMapper
+ module Compatibility
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ # Hooks for confirmable
+ def before_create(*args)
+ wrap_hook(:before, :create, *args)
+ end
+
+ def after_create(*args)
+ wrap_hook(:after, :create, *args)
+ end
+
+ def before_save(*args)
+ wrap_hook(:before, :save, *args)
+ end
+
+ def wrap_hook(action, method, *args)
+ options = args.extract_options!
+
+ args.each do |callback|
+ callback_method = :"#{callback}_callback_wrap"
+ send action, method, callback_method
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
+ def #{callback_method}
+ #{callback} if #{options[:if] || true}
+ end
+ METHOD
+ end
+ end
+
+ # Add ActiveRecord like finder
+ def find(*args)
+ case args.first
+ when :first, :all
+ send(args.shift, *args)
+ else
+ get(*args)
+ end
+ end
+ end
+
+ def changed?
+ dirty?
+ end
+
+ def save(options=nil)
+ if options.is_a?(Hash) && options[:validate] == false
+ save!
+ else
+ super()
+ end
+ end
+
+ def update_attribute(name, value)
+ update(name => value)
+ end
+
+ def update_attributes(*args)
+ update(*args)
+ end
+
+ def invalid?
+ !valid?
+ end
+ end
+ end
+ end
+end
6 lib/mongo_mapper/orm/mongo_mapper/date_time.rb
@@ -0,0 +1,6 @@
+# Add DateTime#gmtime method if needed.
+class DateTime
+ unless method_defined?(:gmtime)
+ delegate :gmtime, :to => :to_time
+ end
+end
55 lib/mongo_mapper/orm/mongo_mapper/mm-validations.rb
@@ -0,0 +1,55 @@
+module MongoMapper
+ module Validate
+
+ # Monkey-patch ValidationErrors to support generation of error message from
+ # a Symbol. This does not translate, consistent with normal DataMapper
+ # operation. Set DataMapper::Validate::ValidationErrors.default_error_messages
+ # if alternate messages are needed (after devise has been initialized).
+ class ValidationErrors
+ alias_method :original_add, :add
+
+ # If the message is a Symbol, allow +default_error_message+ to generate
+ # the message, including translation.
+ def add(field_name, message)
+ if message.kind_of?(Symbol)
+ message = self.class.default_error_message(message, field_name)
+ end
+ original_add(field_name, message) unless errors[field_name].include?(message)
+ end
+ end
+ end
+end
+
+# Default error messages consistent with ActiveModel messages and devise
+# expectations.
+MongoMapper::Validate::ValidationErrors.default_error_messages = {
+ :absent => '%s must be absent',
+ :inclusion => '%s is not included in the list',
+ :exclusion => '%s is reserved',
+ :invalid => '%s is invalid',
+ :confirmation => "%s doesn't match confirmation",
+ :accepted => '%s must be accepted',
+ :nil => '%s must not be nil',
+ :empty => "%s can't be empty",
+ :blank => "%s can't be blank",
+ :length_between => '%s must be between %s and %s characters long',
+ :too_long => '%s is too long (maximum is %s characters)',
+ :too_short => '%s is too short (minimum is %s characters)',
+ :wrong_length => '%s "is the wrong length (should be %s characters)"',
+ :taken => '%s has already been taken',
+ :not_a_number => '%s is not a number',
+ :not_an_integer => '%s must be an integer',
+ :greater_than => '%s must be greater than %s',
+ :greater_than_or_equal_to => '%s must be greater than or equal to %s',
+ :equal_to => '%s must be equal to %s',
+ :not_equal_to => '%s must not be equal to %s',
+ :less_than => '%s must be less than %s',
+ :less_than_or_equal_to => '%s must be less than or equal to %s',
+ :value_between => '%s must be between %s and %s',
+ :odd => 'must be odd',
+ :even => 'must be even',
+ :primitive => '%s must be of type %s',
+ :not_found => '%s not found',
+ :already_confirmed => '%s was already confirmed',
+ :not_locked => '%s was not locked'
+}
31 lib/mongo_mapper/orm/mongo_mapper/schema.rb
@@ -0,0 +1,31 @@
+module Devise
+ module Orm
+ module MongoMapper
+ module Schema
+ include Devise::Schema
+
+ SCHEMA_OPTIONS = {
+ :null => :required,
+ :limit => :length
+ }
+
+ # Tell how to apply schema methods. This automatically maps :limit to
+ # :length and :null to :required.
+ def apply_devise_schema(name, type, options={})
+ SCHEMA_OPTIONS.each do |old_key, new_key|
+ next unless options.key?(old_key)
+ if :null == old_key
+ # :required is opposite of :null
+ options[new_key] = !options.delete(old_key)
+ else
+ options[new_key] = options.delete(old_key)
+ end
+ end
+
+ options.delete(:default) if options[:default].nil?
+ property name, type, options
+ end
+ end
+ end
+ end
+end
63 lib/mongo_mapper/orm/mongo_mapper_active_model.rb
@@ -0,0 +1,63 @@
+require 'devise/orm/mongo_mapper/compatibility'
+require 'devise/orm/mongo_mapper/schema'
+require 'devise/orm/mongo_mapper/date_time'
+
+module Devise
+ module Orm
+ module MongoMapper
+ module Hook
+ def devise_modules_hook!
+ extend Schema
+ include ActiveModel::Validations
+ include ActiveModelCompatibility
+ include Compatibility
+ class << self; attr_reader :descendants; end;
+
+ def self.validates_uniqueness_of(*fields)
+ validates_with UniquenessValidator, _merge_attributes(fields)
+ end
+
+ yield
+ return unless Devise.apply_schema
+ devise_modules.each { |m| send(m) if respond_to?(m, true) }
+ end
+ end
+
+ # http://github.com/jkaramon/mongomapper/blob/rails3/lib/mongo_mapper/plugins/validations.rb
+ # ==============================================================
+ # validates_each in mongo_mapper should work just fine!
+ # ==============================================================
+
+ # class UniquenessValidator < ActiveModel::EachValidator
+ # def validate_each(target, attribute, value)
+ # resource = ::DataMapper.repository(target.repository.name) { target.model.first(attribute => value) }
+ # if resource.nil? || (target.saved? && resource.key == target.key)
+ # return true
+ # else
+ # target.errors.add(attribute, :taken)
+ # return false
+ # end
+ # end
+ # end
+
+ module ActiveModelCompatibility
+ # include ActiveModel::Validations does not make save check valid?.
+ # This may not be the best solution, but it seems to work. Note that
+ # Compatibility is included after this module; its #save method handles
+ # the :validate => false option.
+ def save(*args)
+ retval = valid? && super(*args)
+ assert_save_successful(:save, retval)
+ retval
+ end
+ end
+ end
+ end
+end
+
+module MongoMapper
+ module Document
+ extend ::Devise::Models
+ extend ::Devise::Orm::MongoMapper::Hook
+ end
+end
24 test/mongo_mapper/compatibility_test.rb
@@ -0,0 +1,24 @@
+require 'test_helper'
+
+class DataMapperCompatibilityTest < ActiveSupport::TestCase
+ def teardown
+ User.raise_on_save_failure = false
+ end
+
+ test 'respects raise_on_save_failure' do
+ User.raise_on_save_failure = true
+ user = new_user(:email => nil)
+ assert user.invalid?
+ assert_raise DataMapper::SaveFailureError do
+ user.save
+ end
+
+ user = new_user
+ assert user.valid?
+ assert user.save
+
+ User.raise_on_save_failure = false
+ user = new_user(:email => nil)
+ assert !user.save
+ end
+end
29 test/orm/mongo_mapper.rb
@@ -0,0 +1,29 @@
+require 'rails/test_help'
+
+class ActiveSupport::TestCase
+ setup do
+ User.all.destroy!
+ Admin.all.destroy!
+ end
+end
+
+module MongoMapper
+ module Validate
+ class ValidationErrors
+
+ # ActiveModel prepends field names in +#full_messages+, and so the
+ # expected result of calling errors[field_name] will not include the
+ # field name in the message. However, DM expects the field name to be
+ # included in the original message. Assuming that the field name will
+ # begin the message, just strip it out (plus the following space) for
+ # testing purposes. This has no effect on #full_messages.
+ def [](property_name)
+ if property_errors = errors[property_name.to_sym]
+ property_errors.collect do |message|
+ message[(property_name.to_s.length + 1)..-1]
+ end
+ end
+ end
+ end
+ end
+end
8 test/orm/mongo_mapper_active_model.rb
@@ -0,0 +1,8 @@
+require 'rails/test_help'
+
+class ActiveSupport::TestCase
+ setup do
+ User.all.destroy!
+ Admin.all.destroy!
+ end
+end
46 test/overrides/mm_validations_test.rb
@@ -0,0 +1,46 @@
+require 'test_helper'
+
+# See data_mapper_test.rb in this folder for what this file is doing.
+if DEVISE_ORM == :mongo_mapper
+
+ class ValidatableTest < ActiveSupport::TestCase
+ undef test_should_require_a_password_with_minimum_of_6_characters
+
+ # DataMapper uses a :value_between error message when given a minimum and
+ # maximum; ActiveModel shows either the :too_long or :too_short message.
+ test 'should require a password with minimum of 6 characters' do
+ user = new_user(:password => '12345', :password_confirmation => '12345')
+ assert user.invalid?
+ # assert_equal 'is too short (minimum is 6 characters)', user.errors[:password].join
+ assert_equal 'must be between 6 and 20 characters long', user.errors[:password].join
+ end
+
+ undef test_should_require_a_password_with_maximum_of_20_characters_long
+
+ # Same issue as previous test
+ test 'should require a password with maximum of 20 characters long' do
+ user = new_user(:password => 'x'*21, :password_confirmation => 'x'*21)
+ assert user.invalid?
+ # assert_equal 'is too long (maximum is 20 characters)', user.errors[:password].join
+ assert_equal 'must be between 6 and 20 characters long', user.errors[:password].join
+ end
+
+ end
+
+ class AuthenticationOthersTest < ActionController::IntegrationTest
+
+ undef test_registration_in_xml_format_works_when_recognizing_path
+
+ # DM's validates_confirmation_of requires the confirmation field to be present,
+ # while ActiveModel by default skips the confirmation test if the confirmation
+ # value is nil. This test takes advantage of AM's behavior, so just add the
+ # :password_confirmation value.
+ test 'registration in xml format works when recognizing path' do
+ assert_nothing_raised do
+ # post user_registration_path(:format => 'xml', :user => {:email => "test@example.com", :password => "invalid"} )
+ post user_registration_path(:format => 'xml', :user => {:email => "test@example.com", :password => "invalid", :password_confirmation => "invalid"} )
+ end
+ end
+ end
+
+end
50 test/overrides/mongo_mapper_test.rb
@@ -0,0 +1,50 @@
+require 'test_helper'
+
+# This file contains test cases that override devise tests, in the cases that
+# the difference is values from DM versus those expected by devise is not
+# particularly important and getting DM to pass the original devise tests would
+# be difficult.
+#
+# This file contains tests shared by both data_mapper and
+# data_mapper_active_model ORM setups.
+# Tests specific to the data_mapper orm which uses dm-validations are in dm_validations_test.rb
+# Tests specific to the data_mapper_active_model orm which uses ActiveModel
+# validations would be in active_model_test.rb, but there aren't any (I would
+# be rather surprised if there ever were any).
+#
+# For each test, an explanation is given as to why I chose to override the test,
+# and the original assertion is commented above the DM-specific assertion.
+
+class TrackableHooksTest < ActionController::IntegrationTest
+
+ undef test_current_and_last_sign_in_timestamps_are_updated_on_each_sign_in
+
+ # DataMapper uses a DateTime type where ActiveRecord uses Time. The test is
+ # that the tested properties are being set, so just check for kind_of?(DateTime)
+ # instead of kind_of?(Time)
+ test "current and last sign in timestamps are updated on each sign in" do
+ user = create_user
+ assert_nil user.current_sign_in_at
+ assert_nil user.last_sign_in_at
+
+ sign_in_as_user
+ user.reload
+
+ # assert_kind_of Time, user.current_sign_in_at
+ # assert_kind_of Time, user.last_sign_in_at
+ assert_kind_of DateTime, user.current_sign_in_at
+ assert_kind_of DateTime, user.last_sign_in_at
+
+ assert_equal user.current_sign_in_at, user.last_sign_in_at
+ assert user.current_sign_in_at >= user.created_at
+
+ visit destroy_user_session_path
+ new_time = 2.seconds.from_now
+ Time.stubs(:now).returns(new_time)
+
+ sign_in_as_user
+ user.reload
+ assert user.current_sign_in_at > user.last_sign_in_at
+ end
+end
+
10 test/rails_app/app/mongo_mapper/admin.rb
@@ -0,0 +1,10 @@
+require 'shared_admin'
+
+class Admin
+ include MongoMapper::Document
+
+ key :username, String
+
+ include SharedAdmin
+ include Shim
+end
25 test/rails_app/app/mongo_mapper/shim.rb
@@ -0,0 +1,25 @@
+# Shim should be included after SharedUser / SharedAdmin
+module Shim
+ def self.included(klass)
+ klass.extend(ModelMethods)
+ end
+
+ module ModelMethods
+ # Override version in SharedUser which uses #find_by_email.
+ def find_for_facebook_oauth(access_token, signed_in_resource=nil)
+ data = ActiveSupport::JSON.decode(access_token.get('/me'))
+ user = signed_in_resource || User.first(:email => data["email"]) || User.new
+ user.update_with_facebook_oauth(access_token, data)
+ user.save
+ user
+ end
+
+ def create!(*args)
+ create(*args)
+ end
+
+ def destroy_all
+ all.destroy
+ end
+ end
+end
26 test/rails_app/app/mongo_mapper/user.rb
@@ -0,0 +1,26 @@
+require 'shared_user'
+
+class User
+ include MongoMapper::Document
+
+ key :username, String
+ key :facebook_token, String
+ timestamps!
+
+ include SharedUser
+ include Shim
+
+ unless DEVISE_ORM == :mongo_mapper_active_model
+ before :valid?, :update_password_confirmation
+
+ # DM's validates_confirmation_of requires the confirmation field to be present,
+ # while ActiveModel by default skips the confirmation test if the confirmation
+ # value is nil. This test takes advantage of AM's behavior, so just add the
+ # :password_confirmation value.
+ def update_password_confirmation
+ if self.password && self.password_confirmation.nil?
+ self.password_confirmation = self.password
+ end
+ end
+ end
+end
11 test/rails_app/app/mongo_mapper_active_model/admin.rb
@@ -0,0 +1,11 @@
+require 'shared_admin'
+require File.join(File.dirname(__FILE__), '../mongo_mapper/shim.rb')
+
+class Admin
+ include MongoMapper::Document
+
+ key :username, String
+
+ include SharedAdmin
+ include Shim
+end
13 test/rails_app/app/mongo_mapper_active_model/user.rb
@@ -0,0 +1,13 @@
+require 'shared_user'
+require File.join(File.dirname(__FILE__), '../mongo_mapper/shim.rb')
+
+class User
+ include MongoMapper::Document
+
+ key :username, String
+ key :facebook_token, String
+ timestamps!
+
+ include SharedUser
+ include Shim
+end
37 test/rails_app/config/application.rb
@@ -0,0 +1,37 @@
+APP_ROOT = File.expand_path("#{DEVISE_PATH}/test/rails_app")
+require "#{APP_ROOT}/config/boot"
+
+require "action_controller/railtie"
+require "action_mailer/railtie"
+require "active_resource/railtie"
+require "rails/test_unit/railtie"
+
+Bundler.require :default, DEVISE_ORM
+
+begin
+ require "#{DEVISE_ORM}/railtie"
+rescue LoadError
+end
+
+require "devise"
+
+module RailsApp
+ class Application < Rails::Application
+ # Add additional load paths for your own custom dirs
+ config.root = APP_ROOT
+ config.autoload_paths.reject!{ |p| p =~ /\/app\/(\w+)$/ && !%w(controllers helpers views).include?($1) }
+ config.autoload_paths += [ File.expand_path("#{File.dirname(__FILE__)}/../app/#{DEVISE_ORM}") ]
+
+ # Configure generators values. Many other options are available, be sure to check the documentation.
+ # config.generators do |g|
+ # g.orm :active_record
+ # g.template_engine :erb
+ # g.test_framework :test_unit, :fixture => true
+ # end
+
+ # Configure sensitive parameters which will be filtered from the log file.
+ config.filter_parameters << :password
+
+ config.action_mailer.default_url_options = { :host => "localhost:3000" }
+ end
+end
5 test/rails_app/config/environment.rb
@@ -0,0 +1,5 @@
+# Load the rails application
+require File.expand_path('../application', __FILE__)
+
+# Initialize the rails application
+RailsApp::Application.initialize!
23 test/test_helper.rb
@@ -0,0 +1,23 @@
+ENV["RAILS_ENV"] = "test"
+DEVISE_ORM = (ENV["DEVISE_ORM"] || :data_mapper).to_sym
+DEVISE_PATH = ENV['DEVISE_PATH']
+
+puts "\n==> Devise.orm = #{DEVISE_ORM.inspect}"
+
+require "rails_app/config/environment"
+require "rails/test_help"
+require "orm/#{DEVISE_ORM}"
+
+I18n.load_path << "#{DEVISE_PATH}/test/support/locale/en.yml"
+require 'mocha'
+
+Webrat.configure do |config|
+ config.mode = :rails
+ config.open_error_files = false
+end
+
+Devise::Oauth.test_mode!
+
+# Add support to load paths so we can overwrite broken webrat setup
+$:.unshift "#{DEVISE_PATH}/test/support"
+Dir["#{DEVISE_PATH}/test/support/**/*.rb"].each { |f| require f }
Please sign in to comment.
Something went wrong with that request. Please try again.