From b2a50db1df91da7d0f0cac56f62a02b38d8b44c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 15 Apr 2010 08:34:49 +0200 Subject: [PATCH] Fix a bug with STI. Closes #195. --- CHANGELOG.rdoc | 3 +++ lib/devise/models.rb | 22 ++++++++++++++-------- test/models_test.rb | 9 ++++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 2b83d7fc..6544089a 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -19,6 +19,9 @@ * No need to append ?unauthenticated=true in URLs anymore since Flash was moved to a middleware in Rails 3. * :activatable is included by default in your models. +* bug fix + * fix a bug with STI + * deprecations * Rails 3 compatible only. * Scoped views are no longer "sessions/users/new". Now use "users/sessions/new". diff --git a/lib/devise/models.rb b/lib/devise/models.rb index 9079aef6..a8157c88 100644 --- a/lib/devise/models.rb +++ b/lib/devise/models.rb @@ -1,5 +1,17 @@ module Devise module Models + class << self + def hook(base) + base.class_eval do + class_attribute :devise_modules, :instance_writer => false + self.devise_modules ||= [] + end + end + + alias :included :hook + alias :extended :hook + end + # Creates configuration values for Devise and for the given module. # # Devise::Models.config(Devise::Authenticable, :stretches, 10) @@ -61,20 +73,14 @@ module Devise ActiveSupport::Deprecation.warn ":http_authenticatable as module is deprecated and is on by default. Revert by setting :http_authenticatable => false.", caller end - @devise_modules = Devise::ALL & modules.map(&:to_sym).uniq + self.devise_modules += Devise::ALL & modules.map(&:to_sym).uniq devise_modules_hook! do - @devise_modules.each { |m| include Devise::Models.const_get(m.to_s.classify) } + devise_modules.each { |m| include Devise::Models.const_get(m.to_s.classify) } options.each { |key, value| send(:"#{key}=", value) } end end - # Stores all modules included inside the model, so we are able to verify - # which routes are needed. - def devise_modules - @devise_modules ||= [] - end - # The hook which is called inside devise. So your ORM can include devise # compatibility stuff. def devise_modules_hook! diff --git a/test/models_test.rb b/test/models_test.rb index d92cdafe..00819da2 100644 --- a/test/models_test.rb +++ b/test/models_test.rb @@ -6,6 +6,9 @@ class Configurable < User :remember_for => 7.days, :timeout_in => 15.minutes, :unlock_in => 10.days end +class Inheritable < Admin +end + class ActiveRecordTest < ActiveSupport::TestCase def include_module?(klass, mod) klass.devise_modules.include?(mod) && @@ -22,10 +25,14 @@ class ActiveRecordTest < ActiveSupport::TestCase end end - test 'add modules cherry pick' do + test 'can cherry pick modules' do assert_include_modules Admin, :database_authenticatable, :registerable, :timeoutable, :recoverable end + test 'chosen modules are inheritable' do + assert_include_modules Inheritable, :database_authenticatable, :registerable, :timeoutable, :recoverable + end + test 'order of module inclusion' do correct_module_order = [:database_authenticatable, :recoverable, :registerable, :timeoutable] incorrect_module_order = [:database_authenticatable, :timeoutable, :registerable, :recoverable]