From ae729aedc3755b65dc525f5ff543bb4932fda47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 26 Mar 2010 10:19:31 +0100 Subject: [PATCH] Allow devise to work with association proxies. --- CHANGELOG.rdoc | 1 + app/models/devise/mailer.rb | 7 +++---- lib/devise/mapping.rb | 19 ++++++------------- test/mapping_test.rb | 15 +++++---------- 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index d75ad29d..f3e32199 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -15,6 +15,7 @@ * bug fix * Do not use lock! on lockable since it's part of ActiveRecord API. + * Fix a bug when giving an association proxy to devise. * deprecations * Rails 3 compatible only. diff --git a/app/models/devise/mailer.rb b/app/models/devise/mailer.rb index 8e471bbd..ad77bf2b 100644 --- a/app/models/devise/mailer.rb +++ b/app/models/devise/mailer.rb @@ -19,10 +19,9 @@ class Devise::Mailer < ::ActionMailer::Base # Configure default email options def setup_mail(record, action) - @devise_mapping = Devise::Mapping.find_by_class(record.class) - - raise "Invalid devise resource #{record}" unless @devise_mapping - @resource = instance_variable_set("@#{@devise_mapping.name}", record) + @scope_name = Devise::Mapping.find_scope!(record) + @devise_mapping = Devise.mappings[@scope_name] + @resource = instance_variable_set("@#{@devise_mapping.name}", record) template_path = ["devise/mailer"] template_path.unshift "#{@devise_mapping.as}/mailer" if self.class.scoped_views? diff --git a/lib/devise/mapping.rb b/lib/devise/mapping.rb index 0de44735..d4d149a2 100644 --- a/lib/devise/mapping.rb +++ b/lib/devise/mapping.rb @@ -34,26 +34,19 @@ module Devise nil end - # Find a mapping by a given class. It takes into account single table inheritance as well. - def self.find_by_class(klass) - Devise.mappings.each_value do |mapping| - return mapping if klass <= mapping.to - end - nil - end - # Receives an object and find a scope for it. If a scope cannot be found, # raises an error. If a symbol is given, it's considered to be the scope. def self.find_scope!(duck) case duck when String, Symbol - duck + return duck + when Class + Devise.mappings.each_value { |m| return m.name if duck <= m.to } else - klass = duck.is_a?(Class) ? duck : duck.class - mapping = Devise::Mapping.find_by_class(klass) - raise "Could not find a valid mapping for #{duck}" unless mapping - mapping.name + Devise.mappings.each_value { |m| return m.name if duck.is_a?(m.to) } end + + raise "Could not find a valid mapping for #{duck}" end def initialize(name, options) #:nodoc: diff --git a/test/mapping_test.rb b/test/mapping_test.rb index 8593cd23..6fe62e99 100644 --- a/test/mapping_test.rb +++ b/test/mapping_test.rb @@ -38,22 +38,17 @@ class MappingTest < ActiveSupport::TestCase assert_equal Devise.mappings[:admin], Devise::Mapping.find_by_path("/admin_area/session") end - test 'find mapping by class' do - assert_nil Devise::Mapping.find_by_class(String) - assert_equal Devise.mappings[:user], Devise::Mapping.find_by_class(User) - end - - test 'find mapping by class works with single table inheritance' do - klass = Class.new(User) - assert_equal Devise.mappings[:user], Devise::Mapping.find_by_class(klass) - end - test 'find scope for a given object' do assert_equal :user, Devise::Mapping.find_scope!(User) assert_equal :user, Devise::Mapping.find_scope!(:user) assert_equal :user, Devise::Mapping.find_scope!(User.new) end + test 'find scope works with single table inheritance' do + assert_equal :user, Devise::Mapping.find_scope!(Class.new(User)) + assert_equal :user, Devise::Mapping.find_scope!(Class.new(User).new) + end + test 'find scope raises an error if cannot be found' do assert_raise RuntimeError do Devise::Mapping.find_scope!(String)