├── .gitignore ├── .document ├── lib ├── dm-devise │ └── version.rb ├── devise │ └── orm │ │ ├── data_mapper │ │ ├── date_time.rb │ │ ├── schema.rb │ │ ├── dm-validations.rb │ │ ├── serializable.rb │ │ └── compatibility.rb │ │ ├── data_mapper.rb │ │ └── data_mapper_active_model.rb ├── generators │ └── data_mapper │ │ └── devise_generator.rb └── dm-devise.rb ├── test ├── rails_app │ ├── config │ │ ├── environment.rb │ │ └── application.rb │ └── app │ │ ├── data_mapper │ │ ├── admin.rb │ │ ├── shim.rb │ │ └── user.rb │ │ └── data_mapper_active_model │ │ ├── admin.rb │ │ └── user.rb ├── orm │ ├── data_mapper_active_model.rb │ └── data_mapper.rb ├── data_mapper │ ├── schema_test.rb │ └── compatibility_test.rb ├── generators │ └── data_mapper_generator_test.rb ├── test_helper.rb └── overrides │ ├── dm_validations_test.rb │ └── data_mapper_test.rb ├── Gemfile ├── LICENSE ├── dm-devise.gemspec ├── Rakefile ├── README.rdoc └── Gemfile.lock /.gitignore: -------------------------------------------------------------------------------- 1 | coverage/* 2 | .bundle 3 | rdoc/* 4 | pkg 5 | log 6 | -------------------------------------------------------------------------------- /.document: -------------------------------------------------------------------------------- 1 | README.rdoc 2 | lib/**/*.rb 3 | bin/* 4 | features/**/*.feature 5 | LICENSE 6 | -------------------------------------------------------------------------------- /lib/dm-devise/version.rb: -------------------------------------------------------------------------------- 1 | module DataMapper 2 | module Devise 3 | VERSION = '1.4.0'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/rails_app/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the rails application 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the rails application 5 | RailsApp::Application.initialize! 6 | -------------------------------------------------------------------------------- /lib/devise/orm/data_mapper/date_time.rb: -------------------------------------------------------------------------------- 1 | # Add DateTime#gmtime method if needed. 2 | class DateTime 3 | unless method_defined?(:gmtime) 4 | def gmtime 5 | self.new_offset(0) 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /test/orm/data_mapper_active_model.rb: -------------------------------------------------------------------------------- 1 | require 'rails/test_help' 2 | 3 | DataMapper.auto_migrate! 4 | 5 | class ActiveSupport::TestCase 6 | setup do 7 | User.all.destroy! 8 | Admin.all.destroy! 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/rails_app/app/data_mapper/admin.rb: -------------------------------------------------------------------------------- 1 | require 'shared_admin' 2 | 3 | class Admin 4 | include DataMapper::Resource 5 | 6 | property :id, Serial 7 | property :username, String 8 | 9 | include SharedAdmin 10 | include Shim 11 | 12 | property :remember_token, String 13 | end 14 | -------------------------------------------------------------------------------- /test/rails_app/app/data_mapper_active_model/admin.rb: -------------------------------------------------------------------------------- 1 | require 'shared_admin' 2 | require File.join(File.dirname(__FILE__), '../data_mapper/shim.rb') 3 | 4 | class Admin 5 | include DataMapper::Resource 6 | 7 | property :id, Serial 8 | property :username, String 9 | 10 | include SharedAdmin 11 | include Shim 12 | 13 | property :remember_token, String 14 | end 15 | -------------------------------------------------------------------------------- /test/rails_app/app/data_mapper_active_model/user.rb: -------------------------------------------------------------------------------- 1 | require 'shared_user' 2 | require File.join(File.dirname(__FILE__), '../data_mapper/shim.rb') 3 | 4 | class User 5 | include DataMapper::Resource 6 | 7 | property :id, Serial 8 | property :username, String 9 | property :facebook_token, String 10 | property :confirmation_token, String, :writer => :private 11 | timestamps :at 12 | 13 | include SharedUser 14 | include Shim 15 | end 16 | -------------------------------------------------------------------------------- /test/data_mapper/schema_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class DataMapperSchemaTest < ActiveSupport::TestCase 4 | test 'required explicitly set to false' do 5 | begin 6 | DataMapper::Property.required(true) 7 | model = Class.new(User) 8 | model.apply_devise_schema :required_string, String, :required => true 9 | model.apply_devise_schema :not_required_string, String 10 | assert model.properties['required_string'].required? 11 | assert !model.properties['not_required_string'].required? 12 | ensure 13 | DataMapper::Property.required(false) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /test/data_mapper/compatibility_test.rb: -------------------------------------------------------------------------------- 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 25 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | 3 | gemspec 4 | 5 | gem 'oa-oauth', '~> 0.2.0', :require => 'omniauth/oauth' 6 | gem 'oa-openid', '~> 0.2.0', :require => 'omniauth/openid' 7 | 8 | group :test do 9 | gem 'webrat', '0.7.2', :require => false 10 | gem 'mocha', :require => false 11 | end 12 | 13 | DM_VERSION = '~> 1.1.0' 14 | 15 | group :development do 16 | gem 'rails', '~> 3.0.4' 17 | gem 'dm-sqlite-adapter', DM_VERSION 18 | 19 | gem 'dm-core', DM_VERSION 20 | gem 'dm-migrations', DM_VERSION 21 | gem 'dm-serializer', DM_VERSION 22 | gem 'dm-timestamps', DM_VERSION 23 | gem 'dm-rails', DM_VERSION 24 | end 25 | 26 | group :data_mapper do 27 | gem 'dm-validations', DM_VERSION 28 | end 29 | -------------------------------------------------------------------------------- /test/rails_app/app/data_mapper/shim.rb: -------------------------------------------------------------------------------- 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 | # For benefit of Users::OmniauthCallbacksController 9 | def find_by_email(email) 10 | first(:email => email) 11 | end 12 | 13 | def create!(*args) 14 | create(*args) 15 | end 16 | 17 | def destroy_all 18 | all.destroy 19 | end 20 | end 21 | 22 | def to_xml(*args) 23 | "\n" + super + "\n" 24 | end 25 | 26 | def to_json(*args) 27 | {self.model.name.downcase => JSON.parse(super)}.to_json 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/generators/data_mapper_generator_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | if [:data_mapper, :data_mapper_active_model].include?(DEVISE_ORM) 4 | require "generators/data_mapper/devise_generator" 5 | 6 | class DataMapperGeneratorTest < Rails::Generators::TestCase 7 | tests DataMapper::Generators::DeviseGenerator 8 | destination File.expand_path("../../tmp", __FILE__) 9 | setup :prepare_destination 10 | 11 | test "all files are properly created" do 12 | run_generator %w(monster) 13 | assert_file "app/models/monster.rb", /devise/ 14 | end 15 | 16 | test "all files are properly deleted" do 17 | run_generator %w(monster) 18 | run_generator %w(monster), :behavior => :revoke 19 | assert_no_file "app/models/monster.rb" 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/devise/orm/data_mapper.rb: -------------------------------------------------------------------------------- 1 | require 'dm-devise' 2 | require 'devise/orm/data_mapper/compatibility' 3 | require 'devise/orm/data_mapper/schema' 4 | require 'devise/orm/data_mapper/date_time' 5 | require 'devise/orm/data_mapper/serializable' 6 | require 'devise/orm/data_mapper/dm-validations' 7 | require 'orm_adapter/adapters/data_mapper' 8 | 9 | module Devise 10 | module Orm 11 | module DataMapper 12 | module Hook 13 | def devise_modules_hook! 14 | extend Schema 15 | include Compatibility 16 | yield 17 | return unless Devise.apply_schema 18 | devise_modules.each { |m| send(m) if respond_to?(m, true) } 19 | end 20 | end 21 | end 22 | end 23 | end 24 | 25 | DataMapper::Model.append_extensions(Devise::Models) 26 | DataMapper::Model.append_extensions(Devise::Orm::DataMapper::Hook) 27 | -------------------------------------------------------------------------------- /test/rails_app/app/data_mapper/user.rb: -------------------------------------------------------------------------------- 1 | require 'shared_user' 2 | 3 | class User 4 | include DataMapper::Resource 5 | 6 | property :id, Serial 7 | property :username, String 8 | property :facebook_token, String 9 | property :confirmation_token, String, :writer => :private 10 | timestamps :at 11 | 12 | include SharedUser 13 | include Shim 14 | 15 | before :valid?, :update_password_confirmation 16 | 17 | # DM's validates_confirmation_of requires the confirmation field to be present, 18 | # while ActiveModel by default skips the confirmation test if the confirmation 19 | # value is nil. This test takes advantage of AM's behavior, so just add the 20 | # :password_confirmation value. 21 | def update_password_confirmation 22 | if self.password && self.password_confirmation.nil? 23 | self.password_confirmation = self.password 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 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 'dm-migrations' 8 | require "rails_app/config/environment" 9 | require "rails/test_help" 10 | require "orm/#{DEVISE_ORM}" 11 | 12 | I18n.load_path << "#{DEVISE_PATH}/test/support/locale/en.yml" 13 | require 'mocha' 14 | 15 | require 'webrat' 16 | Webrat.configure do |config| 17 | config.mode = :rails 18 | config.open_error_files = false 19 | end 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 } 24 | 25 | # For generators 26 | require "rails/generators/test_case" 27 | require "generators/devise/install_generator" 28 | require "generators/devise/views_generator" 29 | -------------------------------------------------------------------------------- /test/orm/data_mapper.rb: -------------------------------------------------------------------------------- 1 | require 'rails/test_help' 2 | 3 | DataMapper.auto_migrate! 4 | 5 | class ActiveSupport::TestCase 6 | setup do 7 | User.all.destroy! 8 | Admin.all.destroy! 9 | end 10 | end 11 | 12 | module DataMapper 13 | module Validations 14 | class ValidationErrors 15 | 16 | # ActiveModel prepends field names in +#full_messages+, and so the 17 | # expected result of calling errors[field_name] will not include the 18 | # field name in the message. However, DM expects the field name to be 19 | # included in the original message. Assuming that the field name will 20 | # begin the message, just strip it out (plus the following space) for 21 | # testing purposes. This has no effect on #full_messages. 22 | def [](property_name) 23 | if property_errors = errors[property_name.to_sym] 24 | property_errors.collect do |message| 25 | message[(property_name.to_s.length + 1)..-1] 26 | end 27 | end 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Jared Morgan 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. 21 | -------------------------------------------------------------------------------- /lib/generators/data_mapper/devise_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/devise/orm_helpers' 2 | require 'sugar-high/file' 3 | 4 | # Reload Active Support's String#blank?, overridden by sugar-high. Active Support's 5 | # version considers any all-space String blank, behavior that devise expects. 6 | class String #:nodoc: 7 | def blank? 8 | self !~ /\S/ 9 | end 10 | end 11 | 12 | module DataMapper 13 | module Generators 14 | class DeviseGenerator < Rails::Generators::NamedBase 15 | include ::Devise::Generators::OrmHelpers 16 | 17 | def generate_model 18 | invoke "data_mapper:model", [name] unless model_exists? && behavior == :invoke 19 | end 20 | 21 | def inject_devise_content 22 | inject_into_file model_path, model_contents, :after => "include DataMapper::Resource\n" if model_exists? 23 | end 24 | 25 | def replace_default_devise_orm 26 | devise_init_file = File.join(Rails.root, 'config', 'initializers', 'devise.rb') 27 | File.replace_content_from devise_init_file, :where => 'orm/active_record', :with => 'orm/data_mapper' 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /dm-devise.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "dm-devise/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "dm-devise" 7 | s.version = DataMapper::Devise::VERSION.dup 8 | s.summary = "DataMapper support for devise" 9 | s.description = "dm-devise adds DataMapper support to devise (http://github.com/plataformatec/devise) for authentication support for Rails" 10 | s.email = "jmorgan@morgancreative.net" 11 | s.homepage = "https://github.com/jm81/dm-devise" 12 | s.authors = ["Jared Morgan"] 13 | 14 | s.files = `git ls-files`.split("\n") 15 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 16 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 17 | s.require_paths = ["lib"] 18 | 19 | s.add_dependency('dm-core', '>= 1.0.2', '< 1.2') 20 | s.add_dependency('dm-migrations', '>= 1.0.2', '< 1.2') 21 | s.add_dependency('dm-serializer', '>= 1.0.2', '< 1.2') 22 | s.add_dependency('dm-timestamps', '>= 1.0.2', '< 1.2') 23 | s.add_dependency('dm-rails', '>= 1.0.3', '< 1.2') 24 | s.add_dependency('devise', '~> 1.3') 25 | s.add_dependency('sugar-high', '~> 0.2.10') 26 | end 27 | -------------------------------------------------------------------------------- /lib/devise/orm/data_mapper/schema.rb: -------------------------------------------------------------------------------- 1 | require 'dm-devise' 2 | require 'devise/schema' 3 | 4 | module Devise 5 | module Orm 6 | module DataMapper 7 | module Schema 8 | include Devise::Schema 9 | 10 | SCHEMA_OPTIONS = { 11 | :null => :required, 12 | :limit => :length 13 | } 14 | 15 | # Tell how to apply schema methods. This automatically maps :limit to 16 | # :length and :null to :required. 17 | def apply_devise_schema(name, type, options={}) 18 | return false if properties[name] 19 | SCHEMA_OPTIONS.each do |old_key, new_key| 20 | next unless options.key?(old_key) 21 | if :null == old_key 22 | # :required is opposite of :null 23 | options[new_key] = !options.delete(old_key) 24 | else 25 | options[new_key] = options.delete(old_key) 26 | end 27 | end 28 | 29 | if String == type && !options[:length] 30 | options[:length] = 255 31 | end 32 | 33 | options[:required] ||= false 34 | 35 | options.delete(:default) if options[:default].nil? 36 | property name, type, options 37 | end 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/rails_app/config/application.rb: -------------------------------------------------------------------------------- 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 38 | -------------------------------------------------------------------------------- /lib/devise/orm/data_mapper/dm-validations.rb: -------------------------------------------------------------------------------- 1 | if defined?(DataMapper::Validations) 2 | module DataMapper 3 | module Validations 4 | 5 | # Monkey-patch ValidationErrors to support generation of error message from 6 | # a Symbol. This does not translate, consistent with normal DataMapper 7 | # operation. Set DataMapper::Validate::ValidationErrors.default_error_messages 8 | # if alternate messages are needed (after devise has been initialized). 9 | class ValidationErrors 10 | alias_method :original_add, :add 11 | 12 | # If the message is a Symbol, allow +default_error_message+ to generate 13 | # the message, including translation. 14 | def add(field_name, message) 15 | if message.kind_of?(Symbol) 16 | message = self.class.default_error_message(message, field_name) 17 | end 18 | original_add(field_name, message) unless errors[field_name].include?(message) 19 | end 20 | 21 | # Some devise controller actions expect resource#errors to respond to 22 | # #to_xml. Otherwise, we get a Missing template error 23 | def to_xml(options = {}) 24 | @errors.to_hash.to_xml(options.merge(:root => 'errors')) 25 | end 26 | end 27 | end 28 | end 29 | 30 | if Devise.data_mapper_validation_messages 31 | DataMapper::Validations::ValidationErrors.default_error_messages = Devise.data_mapper_validation_messages 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/devise/orm/data_mapper/serializable.rb: -------------------------------------------------------------------------------- 1 | module Devise 2 | module Models 3 | # This module redefines properties_to_serialize in models for more 4 | # secure defaults. By default, it removes from the serializable model 5 | # all attributes whose writer or reader is *not* public. You can remove this default 6 | # by using :force_except and passing a new list of attributes you want 7 | # to exempt. All attributes given to :exclude will simply add names to 8 | # exempt to Devise internal list. 9 | module Serializable 10 | extend ActiveSupport::Concern 11 | 12 | def properties_to_serialize(options=nil) 13 | options ||= {} 14 | if options.key?(:force_except) || options.key?(:force_exclude) 15 | options[:exclude] = options.delete(:force_except) || options.delete(:force_exclude) 16 | super(options) 17 | else 18 | except = Array(options[:exclude]) + Array(options[:except]) 19 | super(options.merge(:exclude => except + self.class.blacklist_keys)) 20 | end 21 | end 22 | 23 | # Get back to DataMapper's #to_xml. 24 | def to_xml(*args) 25 | super 26 | end 27 | 28 | module ClassMethods 29 | # Returns keys that should be removed when serializing the record. 30 | def blacklist_keys 31 | @blacklist_keys ||= properties.select { |property| property.reader_visibility != :public || property.writer_visibility != :public }.map(&:name) 32 | end 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /test/overrides/dm_validations_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | # See data_mapper_test.rb in this folder for what this file is doing. 4 | if DEVISE_ORM == :data_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 128 characters long', user.errors[:password].join 16 | end 17 | 18 | undef test_should_require_a_password_with_maximum_of_128_characters_long 19 | 20 | # Same issue as previous test 21 | test 'should require a password with maximum of 128 characters long' do 22 | user = new_user(:password => 'x'*129, :password_confirmation => 'x'*129) 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 128 characters long', user.errors[:password].join 26 | end 27 | 28 | undef test_should_complain_about_length_even_if_possword_is_not_required 29 | 30 | test 'should complain about length even if possword is not required' do 31 | user = new_user(:password => 'x'*129, :password_confirmation => 'x'*129) 32 | user.stubs(:password_required?).returns(false) 33 | assert user.invalid? 34 | assert_equal 'must be between 6 and 128 characters long', user.errors[:password].join 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | require 'rubygems' 4 | require 'bundler' 5 | begin 6 | Bundler.setup(:default, :development) 7 | rescue Bundler::BundlerError => e 8 | $stderr.puts e.message 9 | $stderr.puts "Run `bundle install` to install missing gems" 10 | exit e.status_code 11 | end 12 | require 'rake' 13 | require 'rake/testtask' 14 | require 'rdoc/task' 15 | require 'dm-devise/version' 16 | 17 | desc 'Default: run tests for all DataMapper ORM setups.' 18 | task :default => :pre_commit 19 | 20 | desc 'Run Devise tests for all DataMapper ORM setups.' 21 | task :pre_commit do 22 | Dir[File.join(File.dirname(__FILE__), 'test', 'orm', '*.rb')].each do |file| 23 | orm = File.basename(file).split(".").first 24 | ENV['DEVISE_PATH'] ||= File.expand_path('../devise') 25 | system "rake test DEVISE_ORM=#{orm} DEVISE_PATH=#{ENV['DEVISE_PATH']}" 26 | end 27 | end 28 | 29 | desc 'Run Devise tests using DataMapper. Specify path to devise with DEVISE_PATH' 30 | Rake::TestTask.new(:test) do |test| 31 | ENV['DEVISE_ORM'] ||= 'data_mapper' 32 | ENV['DEVISE_PATH'] ||= File.expand_path('../devise') 33 | unless File.exist?(ENV['DEVISE_PATH']) 34 | puts "Specify the path to devise (e.g. rake DEVISE_PATH=/path/to/devise). Not found at #{ENV['DEVISE_PATH']}" 35 | exit 36 | end 37 | test.libs << 'lib' << 'test' 38 | test.libs << "#{ENV['DEVISE_PATH']}/lib" 39 | test.libs << "#{ENV['DEVISE_PATH']}/test" 40 | test.test_files = FileList["#{ENV['DEVISE_PATH']}/test/**/*_test.rb"] + FileList['test/**/*_test.rb'] 41 | test.verbose = true 42 | end 43 | 44 | desc 'Generate documentation for dm-devise.' 45 | Rake::RDocTask.new(:rdoc) do |rdoc| 46 | rdoc.rdoc_dir = 'rdoc' 47 | rdoc.title = 'dm-devise #{version}' 48 | rdoc.options << '--line-numbers' << '--inline-source' 49 | rdoc.rdoc_files.include('README.rdoc') 50 | rdoc.rdoc_files.include('lib/**/*.rb') 51 | end 52 | -------------------------------------------------------------------------------- /lib/devise/orm/data_mapper/compatibility.rb: -------------------------------------------------------------------------------- 1 | module Devise 2 | module Orm 3 | module DataMapper 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 before_validation(*args) 22 | wrap_hook(:before, :valid?, *args) 23 | end 24 | 25 | def wrap_hook(action, method, *args) 26 | options = args.extract_options! 27 | 28 | args.each do |callback| 29 | callback_method = :"#{callback}_callback_wrap" 30 | send action, method, callback_method 31 | class_eval <<-METHOD, __FILE__, __LINE__ + 1 32 | def #{callback_method} 33 | #{callback} if #{options[:if] || true} 34 | end 35 | METHOD 36 | end 37 | end 38 | end 39 | 40 | def changed? 41 | dirty? 42 | end 43 | 44 | def save(options=nil) 45 | if options.is_a?(Hash) && options[:validate] == false 46 | save! 47 | else 48 | super() 49 | end 50 | end 51 | 52 | def update_attribute(name, value) 53 | update(name => value) 54 | end 55 | 56 | def update_attributes(*args) 57 | update(*args) 58 | end 59 | 60 | def invalid? 61 | !valid? 62 | end 63 | 64 | def email_changed? 65 | attribute_dirty?(:email) 66 | end 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/devise/orm/data_mapper_active_model.rb: -------------------------------------------------------------------------------- 1 | require 'dm-devise' 2 | require 'devise/orm/data_mapper/compatibility' 3 | require 'devise/orm/data_mapper/schema' 4 | require 'devise/orm/data_mapper/date_time' 5 | require 'devise/orm/data_mapper/serializable' 6 | require 'orm_adapter/adapters/data_mapper' 7 | 8 | module Devise 9 | module Orm 10 | module DataMapper 11 | module Hook 12 | def devise_modules_hook! 13 | extend Schema 14 | include ActiveModel::Validations 15 | include ActiveModelCompatibility 16 | include Compatibility 17 | 18 | def self.validates_uniqueness_of(*fields) 19 | validates_with UniquenessValidator, _merge_attributes(fields) 20 | end 21 | 22 | yield 23 | return unless Devise.apply_schema 24 | devise_modules.each { |m| send(m) if respond_to?(m, true) } 25 | end 26 | end 27 | 28 | class UniquenessValidator < ActiveModel::EachValidator 29 | def validate_each(target, attribute, value) 30 | resource = ::DataMapper.repository(target.repository.name) { target.model.first(attribute => value) } 31 | if resource.nil? || (target.saved? && resource.key == target.key) 32 | return true 33 | else 34 | target.errors.add(attribute, :taken) 35 | return false 36 | end 37 | end 38 | end 39 | 40 | module ActiveModelCompatibility 41 | # include ActiveModel::Validations does not make save check valid?. 42 | # This may not be the best solution, but it seems to work. Note that 43 | # Compatibility is included after this module; its #save method handles 44 | # the :validate => false option. 45 | def save(*args) 46 | retval = valid? && super(*args) 47 | assert_save_successful(:save, retval) 48 | retval 49 | end 50 | end 51 | end 52 | end 53 | end 54 | 55 | DataMapper::Model.append_extensions(Devise::Models) 56 | DataMapper::Model.append_extensions(Devise::Orm::DataMapper::Hook) 57 | -------------------------------------------------------------------------------- /lib/dm-devise.rb: -------------------------------------------------------------------------------- 1 | require 'devise' 2 | require 'dm-core' 3 | require 'dm-serializer' 4 | require 'dm-timestamps' 5 | require 'dm-rails' 6 | 7 | require 'dm-devise/version' 8 | 9 | module Devise 10 | # Messages to use as the default DataMapper validation error messages. The 11 | # messages are updated from those included in dm-validations to be consistent 12 | # with ActiveModel (i.e. with the Devise test expectations) and include 13 | # additional messages that devise uses (:not_found, :already_confirmed, 14 | # :not_locked, and :expired). If set to false, the messages are left as 15 | # defined by the dm-validations gem. 16 | mattr_accessor :data_mapper_validation_messages 17 | @@data_mapper_validation_messages = { 18 | :absent => '%s must be absent', 19 | :inclusion => '%s is not included in the list', 20 | :exclusion => '%s is reserved', 21 | :invalid => '%s is invalid', 22 | :confirmation => "%s doesn't match confirmation", 23 | :accepted => '%s must be accepted', 24 | :nil => '%s must not be nil', 25 | :empty => "%s can't be empty", 26 | :blank => "%s can't be blank", 27 | :length_between => '%s must be between %s and %s characters long', 28 | :too_long => '%s is too long (maximum is %s characters)', 29 | :too_short => '%s is too short (minimum is %s characters)', 30 | :wrong_length => '%s "is the wrong length (should be %s characters)"', 31 | :taken => '%s has already been taken', 32 | :not_a_number => '%s is not a number', 33 | :not_an_integer => '%s must be an integer', 34 | :greater_than => '%s must be greater than %s', 35 | :greater_than_or_equal_to => '%s must be greater than or equal to %s', 36 | :equal_to => '%s must be equal to %s', 37 | :not_equal_to => '%s must not be equal to %s', 38 | :less_than => '%s must be less than %s', 39 | :less_than_or_equal_to => '%s must be less than or equal to %s', 40 | :value_between => '%s must be between %s and %s', 41 | :odd => 'must be odd', 42 | :even => 'must be even', 43 | :primitive => '%s must be of type %s', 44 | :not_found => '%s not found', 45 | :already_confirmed => '%s was already confirmed, please try signing in', 46 | :not_locked => '%s was not locked', 47 | :expired => '%s has expired, please request a new one' 48 | } 49 | end 50 | -------------------------------------------------------------------------------- /README.rdoc: -------------------------------------------------------------------------------- 1 | = dm-devise 2 | 3 | dm-devise lets you use devise (http://github.com/plataformatec/devise) with 4 | DataMapper. The gem gives you the options of 2 ORM setups depending on what 5 | library you wish to use for validations: 6 | 7 | :data_mapper:: 8 | Uses dm-validations. This involves a bit of monkey-patching, but you need to 9 | use this if you want auto-validations in *any* of your models. 10 | :data_mapper_active_model:: 11 | Uses ActiveModel::Validations. Do not use if you require 'dm-validations' 12 | anywhere in your app (or include it in your Gemfile). Things will break. 13 | The advantage to this is ActiveModel's I18n support for error messages, and 14 | it uses the same validations lib as devise does by default. 15 | 16 | dm-devise is intended for use with Rails 3 and devise >= 1.1. It may work with 17 | earlier versions, but it's not been tested (if you try, please let Jared Morgan 18 | (http://github.com/jm81) know how it goes.) 19 | 20 | This README only covers dm-devise specifics. Make sure to read the devise 21 | README http://github.com/plataformatec/devise/blob/master/README.rdoc 22 | 23 | Last tested against devise master: 2011-07-26, commit 33d7644b4fc13de68da8 24 | Last tested against devise release 1.4.2 25 | 26 | == Installation 27 | 28 | Add dm-devise and dm gems to your Gemfile. The following gems are required: 29 | 30 | gem 'dm-core', '~> 1.1.0' 31 | gem 'dm-sqlite-adapter', '~> 1.1.0' # or your preferred adapter 32 | gem 'dm-serializer', '~> 1.1.0' 33 | gem 'dm-timestamps', '~> 1.1.0' 34 | gem 'dm-rails', '~> 1.1.0' 35 | gem 'dm-validations', '~> 1.1.0' # Do not include if using data_mapper_active_model 36 | gem 'dm-devise', '~> 1.4.0' 37 | 38 | If you're using data_mapper_active_model do not include dm-validations in your 39 | Gemfile. 40 | 41 | dm-devise works with versions of DataMapper gems >= 1.0.2 on the 1.0 branch 42 | and >= 1.1.0.rc3 on the 1.1 branch. 43 | 44 | Run the generator: 45 | 46 | rails generate devise:install 47 | 48 | The generator will install an initializer which describes ALL Devise's 49 | configuration options and you MUST take a look at it. Make sure to specify 50 | either data_mapper (for using dm-validations) or data_mapper_active_model 51 | (ActiveModel::Validations) as the orm in the configuration file. 52 | 53 | To add Devise to any of your models using the generator: 54 | 55 | rails generate data_mapper:devise MODEL 56 | 57 | Read the README for devise at http://github.com/plataformatec/devise/blob/master/README.rdoc 58 | 59 | == TODO 60 | 61 | * Example app 62 | * Rails templates 63 | 64 | == Testing 65 | 66 | The dm-devise test rake task runs all of devise's tests using the data_mapper 67 | and data_mapper_active_model ORM setups. In order to run tests, you'll need a 68 | local copy of devise (a gem is fine as long as you specify the path). By default, 69 | dm-devise looks for devise in [path-to-dm-devise]/../devise. You can override 70 | this by setting a DEVISE_PATH env variable. For example: 71 | 72 | rake test DEVISE_PATH=/path/to/devise 73 | 74 | Tests of the master branch should be run against devise master. Tests of the 75 | 1.1 branch should be run against the devise 1.1 branch (or a 1.1.x gem). 76 | 77 | == Note on Patches/Pull Requests 78 | 79 | * Fork the project. 80 | * Make your feature addition or bug fix. 81 | * Add tests for it. This is important so I don't break it in a 82 | future version unintentionally. 83 | * Commit, do not mess with rakefile, version, or history. 84 | (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) 85 | * Send me a pull request. Bonus points for topic branches. 86 | 87 | == Maintainers 88 | 89 | * Jared Morgan (http://github.com/jm81) 90 | 91 | == Contributors 92 | 93 | http://github.com/jm81/dm-devise/contributors 94 | 95 | == Bugs and Feedback 96 | 97 | For dm-devise specific issues, please create an issue on GitHub at: 98 | 99 | http://github.com/jm81/dm-devise/issues 100 | 101 | == Copyright 102 | 103 | Copyright (c) 2010 Jared Morgan. See LICENSE for details. 104 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | dm-devise (1.4.0) 5 | devise (~> 1.3) 6 | dm-core (>= 1.0.2, < 1.2) 7 | dm-migrations (>= 1.0.2, < 1.2) 8 | dm-rails (>= 1.0.3, < 1.2) 9 | dm-serializer (>= 1.0.2, < 1.2) 10 | dm-timestamps (>= 1.0.2, < 1.2) 11 | sugar-high (~> 0.2.10) 12 | 13 | GEM 14 | remote: http://rubygems.org/ 15 | specs: 16 | abstract (1.0.0) 17 | actionmailer (3.0.9) 18 | actionpack (= 3.0.9) 19 | mail (~> 2.2.19) 20 | actionpack (3.0.9) 21 | activemodel (= 3.0.9) 22 | activesupport (= 3.0.9) 23 | builder (~> 2.1.2) 24 | erubis (~> 2.6.6) 25 | i18n (~> 0.5.0) 26 | rack (~> 1.2.1) 27 | rack-mount (~> 0.6.14) 28 | rack-test (~> 0.5.7) 29 | tzinfo (~> 0.3.23) 30 | activemodel (3.0.9) 31 | activesupport (= 3.0.9) 32 | builder (~> 2.1.2) 33 | i18n (~> 0.5.0) 34 | activerecord (3.0.9) 35 | activemodel (= 3.0.9) 36 | activesupport (= 3.0.9) 37 | arel (~> 2.0.10) 38 | tzinfo (~> 0.3.23) 39 | activeresource (3.0.9) 40 | activemodel (= 3.0.9) 41 | activesupport (= 3.0.9) 42 | activesupport (3.0.9) 43 | addressable (2.2.6) 44 | arel (2.0.10) 45 | bcrypt-ruby (2.1.4) 46 | builder (2.1.2) 47 | data_objects (0.10.6) 48 | addressable (~> 2.1) 49 | devise (1.4.2) 50 | bcrypt-ruby (~> 2.1.2) 51 | orm_adapter (~> 0.0.3) 52 | warden (~> 1.0.3) 53 | dm-active_model (1.1.0) 54 | activemodel (~> 3.0.4) 55 | dm-core (~> 1.1.0) 56 | dm-core (1.1.0) 57 | addressable (~> 2.2.4) 58 | dm-do-adapter (1.1.0) 59 | data_objects (~> 0.10.2) 60 | dm-core (~> 1.1.0) 61 | dm-migrations (1.1.0) 62 | dm-core (~> 1.1.0) 63 | dm-rails (1.1.0) 64 | actionpack (~> 3.0.4) 65 | dm-active_model (~> 1.1.0) 66 | dm-core (~> 1.1.0) 67 | railties (~> 3.0.4) 68 | dm-serializer (1.1.0) 69 | dm-core (~> 1.1.0) 70 | fastercsv (~> 1.5.4) 71 | json (~> 1.4.6) 72 | dm-sqlite-adapter (1.1.0) 73 | dm-do-adapter (~> 1.1.0) 74 | do_sqlite3 (~> 0.10.2) 75 | dm-timestamps (1.1.0) 76 | dm-core (~> 1.1.0) 77 | dm-validations (1.1.0) 78 | dm-core (~> 1.1.0) 79 | do_sqlite3 (0.10.6) 80 | data_objects (= 0.10.6) 81 | erubis (2.6.6) 82 | abstract (>= 1.0.0) 83 | faraday (0.6.1) 84 | addressable (~> 2.2.4) 85 | multipart-post (~> 1.1.0) 86 | rack (< 2, >= 1.1.0) 87 | fastercsv (1.5.4) 88 | i18n (0.5.0) 89 | json (1.4.6) 90 | mail (2.2.19) 91 | activesupport (>= 2.3.6) 92 | i18n (>= 0.4.0) 93 | mime-types (~> 1.16) 94 | treetop (~> 1.4.8) 95 | mime-types (1.16) 96 | mocha (0.9.12) 97 | multi_json (1.0.3) 98 | multi_xml (0.2.2) 99 | multipart-post (1.1.3) 100 | nokogiri (1.5.0) 101 | oa-core (0.2.6) 102 | oa-oauth (0.2.6) 103 | faraday (~> 0.6.1) 104 | multi_json (~> 1.0.0) 105 | multi_xml (~> 0.2.2) 106 | oa-core (= 0.2.6) 107 | oauth (~> 0.4.0) 108 | oauth2 (~> 0.4.1) 109 | oa-openid (0.2.6) 110 | oa-core (= 0.2.6) 111 | rack-openid (~> 1.3.1) 112 | ruby-openid-apps-discovery (~> 1.2.0) 113 | oauth (0.4.5) 114 | oauth2 (0.4.1) 115 | faraday (~> 0.6.1) 116 | multi_json (>= 0.0.5) 117 | orm_adapter (0.0.5) 118 | polyglot (0.3.2) 119 | rack (1.2.3) 120 | rack-mount (0.6.14) 121 | rack (>= 1.0.0) 122 | rack-openid (1.3.1) 123 | rack (>= 1.1.0) 124 | ruby-openid (>= 2.1.8) 125 | rack-test (0.5.7) 126 | rack (>= 1.0) 127 | rails (3.0.9) 128 | actionmailer (= 3.0.9) 129 | actionpack (= 3.0.9) 130 | activerecord (= 3.0.9) 131 | activeresource (= 3.0.9) 132 | activesupport (= 3.0.9) 133 | bundler (~> 1.0) 134 | railties (= 3.0.9) 135 | railties (3.0.9) 136 | actionpack (= 3.0.9) 137 | activesupport (= 3.0.9) 138 | rake (>= 0.8.7) 139 | rdoc (~> 3.4) 140 | thor (~> 0.14.4) 141 | rake (0.9.2) 142 | rdoc (3.8) 143 | require_all (1.2.0) 144 | ruby-openid (2.1.8) 145 | ruby-openid-apps-discovery (1.2.0) 146 | ruby-openid (>= 2.1.7) 147 | sugar-high (0.2.12) 148 | mocha (~> 0.9.8) 149 | require_all (~> 1.2.0) 150 | thor (0.14.6) 151 | treetop (1.4.10) 152 | polyglot 153 | polyglot (>= 0.3.1) 154 | tzinfo (0.3.29) 155 | warden (1.0.5) 156 | rack (>= 1.0) 157 | webrat (0.7.2) 158 | nokogiri (>= 1.2.0) 159 | rack (>= 1.0) 160 | rack-test (>= 0.5.3) 161 | 162 | PLATFORMS 163 | ruby 164 | 165 | DEPENDENCIES 166 | dm-core (~> 1.1.0) 167 | dm-devise! 168 | dm-migrations (~> 1.1.0) 169 | dm-rails (~> 1.1.0) 170 | dm-serializer (~> 1.1.0) 171 | dm-sqlite-adapter (~> 1.1.0) 172 | dm-timestamps (~> 1.1.0) 173 | dm-validations (~> 1.1.0) 174 | mocha 175 | oa-oauth (~> 0.2.0) 176 | oa-openid (~> 0.2.0) 177 | rails (~> 3.0.4) 178 | webrat (= 0.7.2) 179 | -------------------------------------------------------------------------------- /test/overrides/data_mapper_test.rb: -------------------------------------------------------------------------------- 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 | 51 | class DatabaseAuthenticatableTest < ActiveSupport::TestCase 52 | undef test_should_downcase_case_insensitive_keys_when_saving 53 | 54 | # save! is used in devise version of this test. In AR, save! runs callbacks 55 | # (and raises an error if any return false, which I assume is why its being 56 | # used). In DM, save! skips callbacks. Therefore, override and change #save! 57 | # to #save. 58 | test 'should downcase case insensitive keys when saving' do 59 | # case_insensitive_keys is set to :email by default. 60 | email = 'Foo@Bar.com' 61 | user = new_user(:email => email) 62 | 63 | assert_equal email, user.email 64 | user.save 65 | assert_equal email.downcase, user.email 66 | end 67 | 68 | undef test_should_remove_whitespace_from_strip_whitespace_keys_when_saving 69 | 70 | test 'should remove whitespace from strip whitespace keys when saving' do 71 | # strip_whitespace_keys is set to :email by default. 72 | email = ' foo@bar.com ' 73 | user = new_user(:email => email) 74 | 75 | assert_equal email, user.email 76 | user.save 77 | assert_equal email.strip, user.email 78 | end 79 | end 80 | 81 | class ValidatableTest < ActiveSupport::TestCase 82 | # user.save! is failing in these tests, since validation are running anyway. 83 | # See https://github.com/datamapper/dm-validations/pull/13. 84 | 85 | undef :"test_should_require_uniqueness_of_email_if_email_has_changed,_allowing_blank" 86 | 87 | test 'should require uniqueness of email if email has changed, allowing blank' do 88 | existing_user = create_user 89 | 90 | user = new_user(:email => '') 91 | assert user.invalid? 92 | assert_no_match(/taken/, user.errors[:email].join) 93 | 94 | user.email = existing_user.email 95 | assert user.invalid? 96 | assert_match(/taken/, user.errors[:email].join) 97 | 98 | pending do 99 | user.save(:validate => false) 100 | assert user.valid? 101 | end 102 | end 103 | 104 | undef :"test_should_require_correct_email_format_if_email_has_changed,_allowing_blank" 105 | 106 | test 'should require correct email format if email has changed, allowing blank' do 107 | user = new_user(:email => '') 108 | assert user.invalid? 109 | assert_not_equal 'is invalid', user.errors[:email].join 110 | 111 | %w(invalid_email_format 123 $$$ \(\) ).each do |email| 112 | user.email = email 113 | assert user.invalid?, 'should be invalid with email ' << email 114 | assert_equal 'is invalid', user.errors[:email].join 115 | end 116 | 117 | pending do 118 | user.save(:validate => false) 119 | assert user.valid? 120 | end 121 | end 122 | end 123 | 124 | class SerializableTest < ActiveSupport::TestCase 125 | # AR's #to_xml replaces underscore with dash. DM does not. 126 | undef test_should_not_include_unsafe_keys_on_XML 127 | undef test_should_not_include_unsafe_keys_on_XML_even_if_a_new_except_is_provided 128 | undef test_should_include_unsafe_keys_on_XML_if_a_force_except_is_provided 129 | 130 | test 'should not include unsafe keys on XML' do 131 | assert_match /email/, @user.to_xml 132 | assert_no_match /confirmation_token/, @user.to_xml 133 | end 134 | 135 | test 'should not include unsafe keys on XML even if a new except is provided' do 136 | assert_no_match /email/, @user.to_xml(:except => :email) 137 | assert_no_match /confirmation_token/, @user.to_xml(:except => :email) 138 | end 139 | 140 | test 'should include unsafe keys on XML if a force_except is provided' do 141 | assert_no_match /email/, @user.to_xml(:force_except => :email) 142 | assert_match /confirmation_token/, @user.to_xml(:force_except => :email) 143 | end 144 | end 145 | 146 | class DeviseHelperTest < ActionController::IntegrationTest 147 | # Ensure test finds the translation of the model name. 148 | setup do 149 | I18n.backend.store_translations :fr, 150 | { 151 | :data_mapper => { :models => { :user => "utilisateur" } } 152 | } 153 | end 154 | end 155 | --------------------------------------------------------------------------------