mapping.rb 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. module Devise
  2. # Responsible for handling devise mappings and routes configuration. Each
  3. # resource configured by devise_for in routes is actually creating a mapping
  4. # object. You can refer to devise_for in routes for usage options.
  5. #
  6. # The required value in devise_for is actually not used internally, but it's
  7. # inflected to find all other values.
  8. #
  9. # map.devise_for :users
  10. # mapping = Devise.mappings[:user]
  11. #
  12. # mapping.name #=> :user
  13. # # is the scope used in controllers and warden, given in the route as :singular.
  14. #
  15. # mapping.as #=> "users"
  16. # # how the mapping should be search in the path, given in the route as :as.
  17. #
  18. # mapping.to #=> User
  19. # # is the class to be loaded from routes, given in the route as :class_name.
  20. #
  21. # mapping.modules #=> [:authenticatable]
  22. # # is the modules included in the class
  23. #
  24. class Mapping #:nodoc:
  25. attr_reader :singular, :scoped_path, :path, :controllers, :path_names,
  26. :class_name, :sign_out_via, :format, :used_routes, :used_helpers, :failure_app
  27. alias :name :singular
  28. # Receives an object and find a scope for it. If a scope cannot be found,
  29. # raises an error. If a symbol is given, it's considered to be the scope.
  30. def self.find_scope!(duck)
  31. case duck
  32. when String, Symbol
  33. return duck
  34. when Class
  35. Devise.mappings.each_value { |m| return m.name if duck <= m.to }
  36. else
  37. Devise.mappings.each_value { |m| return m.name if duck.is_a?(m.to) }
  38. end
  39. raise "Could not find a valid mapping for #{duck.inspect}"
  40. end
  41. def self.find_by_path!(path, path_type=:fullpath)
  42. Devise.mappings.each_value { |m| return m if path.include?(m.send(path_type)) }
  43. raise "Could not find a valid mapping for path #{path.inspect}"
  44. end
  45. def initialize(name, options) #:nodoc:
  46. @scoped_path = options[:as] ? "#{options[:as]}/#{name}" : name.to_s
  47. @singular = (options[:singular] || @scoped_path.tr('/', '_').singularize).to_sym
  48. @class_name = (options[:class_name] || name.to_s.classify).to_s
  49. @klass = Devise.ref(@class_name)
  50. @path = (options[:path] || name).to_s
  51. @path_prefix = options[:path_prefix]
  52. @sign_out_via = options[:sign_out_via] || Devise.sign_out_via
  53. @format = options[:format]
  54. default_failure_app(options)
  55. default_controllers(options)
  56. default_path_names(options)
  57. default_used_route(options)
  58. default_used_helpers(options)
  59. end
  60. # Return modules for the mapping.
  61. def modules
  62. @modules ||= to.respond_to?(:devise_modules) ? to.devise_modules : []
  63. end
  64. # Gives the class the mapping points to.
  65. def to
  66. @klass.get
  67. end
  68. def strategies
  69. @strategies ||= STRATEGIES.values_at(*self.modules).compact.uniq.reverse
  70. end
  71. def no_input_strategies
  72. self.strategies & Devise::NO_INPUT
  73. end
  74. def routes
  75. @routes ||= ROUTES.values_at(*self.modules).compact.uniq
  76. end
  77. def authenticatable?
  78. @authenticatable ||= self.modules.any? { |m| m.to_s =~ /authenticatable/ }
  79. end
  80. def fullpath
  81. "/#{@path_prefix}/#{@path}".squeeze("/")
  82. end
  83. # Create magic predicates for verifying what module is activated by this map.
  84. # Example:
  85. #
  86. # def confirmable?
  87. # self.modules.include?(:confirmable)
  88. # end
  89. #
  90. def self.add_module(m)
  91. class_eval <<-METHOD, __FILE__, __LINE__ + 1
  92. def #{m}?
  93. self.modules.include?(:#{m})
  94. end
  95. METHOD
  96. end
  97. private
  98. def default_failure_app(options)
  99. @failure_app = options[:failure_app] || Devise::FailureApp
  100. if @failure_app.is_a?(String)
  101. ref = Devise.ref(@failure_app)
  102. @failure_app = lambda { |env| ref.get.call(env) }
  103. end
  104. end
  105. def default_controllers(options)
  106. mod = options[:module] || "devise"
  107. @controllers = Hash.new { |h,k| h[k] = "#{mod}/#{k}" }
  108. @controllers.merge!(options[:controllers]) if options[:controllers]
  109. @controllers.each { |k,v| @controllers[k] = v.to_s }
  110. end
  111. def default_path_names(options)
  112. @path_names = Hash.new { |h,k| h[k] = k.to_s }
  113. @path_names[:registration] = ""
  114. @path_names.merge!(options[:path_names]) if options[:path_names]
  115. end
  116. def default_constraints(options)
  117. @constraints = Hash.new
  118. @constraints.merge!(options[:constraints]) if options[:constraints]
  119. end
  120. def default_defaults(options)
  121. @defaults = Hash.new
  122. @defaults.merge!(options[:defaults]) if options[:defaults]
  123. end
  124. def default_used_route(options)
  125. singularizer = lambda { |s| s.to_s.singularize.to_sym }
  126. if options.has_key?(:only)
  127. @used_routes = self.routes & Array(options[:only]).map(&singularizer)
  128. elsif options[:skip] == :all
  129. @used_routes = []
  130. else
  131. @used_routes = self.routes - Array(options[:skip]).map(&singularizer)
  132. end
  133. end
  134. def default_used_helpers(options)
  135. singularizer = lambda { |s| s.to_s.singularize.to_sym }
  136. if options[:skip_helpers] == true
  137. @used_helpers = @used_routes
  138. elsif skip = options[:skip_helpers]
  139. @used_helpers = self.routes - Array(skip).map(&singularizer)
  140. else
  141. @used_helpers = self.routes
  142. end
  143. end
  144. end
  145. end