Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

initial conversion from dm-devise

  • Loading branch information...
commit 872f7a80e44c783b159a76bb79d53c18e94acf90 0 parents
Kristian Mandrup authored August 05, 2010

Showing 28 changed files with 920 additions and 0 deletions. Show diff stats Hide diff stats

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

0 notes on commit 872f7a8

Please sign in to comment.
Something went wrong with that request. Please try again.