Reputation: 3186
I am trying to override the Devise method set_flash_message
. Devise documentation covers how to override controllers for the various submodules.
However this particular method is located within DeviseController
, the parent class of all the modules.
The documentation (both wiki and inline) says nothing about how to achieve this, so I'm not sure how best to proceed. I believe the best approach would be to simply re-open the class and modify the method as needed, and I placed a file in /lib
to that effect. However it appears that is getting loaded prior to Devise, resulting in error spew.
NameError in Devise::RegistrationsController#new
undefined local variable or method `require_no_authentication' for #<Devise::RegistrationsController>
The complex parent definition for DeviseController
may also be having an net negative effect:
class DeviseController < Devise.parent_controller.constantize
Thoughts?
Upvotes: 7
Views: 2620
Reputation: 446
I only needed to override find_message
and set_flash_messages
in one particular controller (RegistrationsController
).
To override/append to the method, I just ended up writing the method in the RegistrationsController itself. This could be extracted to a module and used in multiple Devise Controllers, giving a single location to the modified method.
This way, I was able to use super
as well. I had some difficulties using super
with class_eval
...
My controller looks like this now:
class RegistrationsController < Devise::RegistrationsController
###
protected
def find_message(kind, options = {})
# my custom code here
super
end
end
Upvotes: 0
Reputation: 14630
I made the file:
config/initilializers/devise_controller.rb
and put:
DeviseController.class_eval do
protected
def set_flash_message
....
end
def resource_params
....
end
end
That seemed to do the trick. I was concerned about load order, and at least class_eval will give you an error if the class doesn't already exist, instead of silently overwriting it.
Upvotes: 1
Reputation: 11
Devise.parent_controller
is defined in the Devise module definition in devise/devise.rb
. Luckily, it has mattr_accessor
declared, so you can set the value yourself (the default value is "ApplicationController"). It probably makes the most sense to do this some time in your application initialization process, for example, along with the rest of the Devise configuration in initializers/devise.rb
.
Upvotes: 1
Reputation: 76784
I believe this is the syntax to override Devise controllers:
class RegistrationsController < Devise::RegistrationsController
If you're receiving method errors, you need to remember this won't totally overwrite the controller - your methods will be delegated to from the "main" devise controller, so you can use things like this:
def method
super
your_code_here
end
Update
class SessionsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
prepend_before_filter :allow_params_authentication!, :only => :create
prepend_before_filter { request.env["devise.skip_timeout"] = true }
prepend_view_path 'app/views/devise'
# GET /resource/sign_in
def new
self.resource = resource_class.new(sign_in_params)
clean_up_passwords(resource)
respond_with(resource, serialize_options(resource))
end
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
respond_to do |format|
format.json { render :json => {}, :status => :ok }
format.html { respond_with resource, :location => after_sign_in_path_for(resource) }
end
end
# DELETE /resource/sign_out
def destroy
redirect_path = after_sign_out_path_for(resource_name)
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
set_flash_message :notice, :signed_out if signed_out && is_navigational_format?
# We actually need to hardcode this as Rails default responder doesn't
# support returning empty response on GET request
respond_to do |format|
format.all { head :no_content }
format.any(*navigational_formats) { redirect_to redirect_path }
end
end
protected
def sign_in_params
devise_parameter_sanitizer.sanitize(:sign_in)
end
def serialize_options(resource)
methods = resource_class.authentication_keys.dup
methods = methods.keys if methods.is_a?(Hash)
methods << :password if resource.respond_to?(:password)
{ :methods => methods, :only => [:password] }
end
def auth_options
{ :scope => resource_name, :recall => "#{controller_path}#new" }
end
end
Upvotes: 0