I'm using Devise as authenticating solution in Rails and I have a cached fragment :recent_users.
I want this fragment to expire when a new user is registered, changed or removed, so I put in my(manually created) users_controller.rb
class UsersController < ApplicationController
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
...
But my fragment does not expire when new creates or changes.
My user_sweeper contains basic prescriptions
class UserSweeper < ActionController::Caching::Sweeper
observe User
def after_save(user)
expire_cache(user)
end
def after_destroy(user)
expire_cache(user)
end
private
def expire_cache(user)
expire_fragment :recent_users
end
end
What am I doing wrong?
Problem solved!
I followed this steps and everything works:
$ mkdir app/controllers/users
$ touch app/controllers/users/registrations_controller.rb
In registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
end
Problem was that Registrations in Devise is a separate controller.
Put this in applications_controller.rb
class ApplicationController < ActionController::Base
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
...
Related
I want users to access the home page whether they're authenticated or not. Though, whenever the root url is visited, the user is immediately redirected to /users/sign_in. How do I disable this?
routes.rb
Rails.application.routes.draw do
root 'home#index'
devise_for :users
end
home_controller.rb
class HomeController < ApplicationController
before_action :authenticate_user!, except: [:index]
def index
end
end
With Devise is usually better to require authentication by default and then add exceptions with skip_before_action:
class ApplicationController < ActionController::Base
before_action :authenticate_user!
end
class HomeController < ApplicationController
skip_before_action :authenticate_user!
def index
end
end
This avoids the risk of leaving security holes just by programmer omission.
I have next definitions:
ApplicationController:
before_action :set_resource, only: [:edit, :update, :destroy]
...
private
def set_resource
...
OtherController < ApplicationController
before_action :set_resource, only: [:new_action1, :new_action2]
...
def new_action1
....
def new_action2
I expect set_resource method will be called before actions edit, update, destroy, new_action1, new_action2, but it right only for methods: edit, update, destroy
I faced almost the same problem today while writing plugin for Redmine.
There is an issues_controller with callbacks in Redmine:
OtherController < ApplicationController
before_filter :find_issue, :only => [:show, :edit, :update]
before_filter :authorize, :except => [:index]
end
And I added another action in module that is being included in issues_controller:
module IssuesControllerPatch
def self.included(base)
before_filter :find_issue, :only => [:show, :edit, :update, :merge]
end
end
What happened here is newly added filter for merge action gets called after authorize method, thus failing authorization.
To solve the problem, I overrode authorize method like that:
module IssuesControllerPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
alias_method :default_authorize, :authorize
alias_method :authorize, :authorize_with_merge
end
end
module InstanceMethods
def authorize_with_merge
find_issue if params[:action] == "merge" && params[:controller] == "issues"
default_authorize
end
end
end
Not quite elegant, but works like a charm. This should help you, as well.
I'm using Devise in a ruby-on-rails project, and before_filter :authenticate_user!, :only => [:show] is not working when I use it in UsersController :
# ./controllers/users_controller.rb
class UsersController < Devise::SessionsController
before_filter :authenticate_user!, :only => [:show]
def show
end
end
# ./config/routes.rb
Notify::Application.routes.draw do
devise_for :users
...
end
I have a Admin::SessionsController who extends from Admin::ApplicationController.
I'm using a before_filter except to the login page, but the server is entering in a loop
I think there`s is something with the except thing, I think that I need to set the namespace or something...
This is the line of before_filte:
before_filter :authenticate_user , :except => { :sessions => :new }
This is my SessionController
class Admin::SessionsController < Admin::ApplicationController
def new
end
end
It might be easiest just to put a skip_before_filter in the Admin:SessionsController
class Admin::SessionsController < Admin::ApplicationController
skip_before_filter :authenticate_user, :only => [:new]
def new
end
end
When I have a specific action that I don't want to check the authenticity token on, how do I tell Rails to skip checking it?
Rails 5.2+
You can use the same skip_before_action method listed below or a new method skip_forgery_protection which is a thin wrapper for skip_before_action :verify_authenticity_token
skip_forgery_protection
Rails 4+:
# entire controller
skip_before_action :verify_authenticity_token
# all actions except for :create, :update, :destroy
skip_before_action :verify_authenticity_token, except: [:create, :destroy]
# only specified actions - :create, :update, :destroy
skip_before_action :verify_authenticity_token, only: [:create, :destroy]
See all options # api.rubyonrails.org
Rails 3 and below:
skip_before_filter :verify_authenticity_token
In Rails4 you use skip_before_action with except or only.
class UsersController < ApplicationController
skip_before_action :verify_authenticity_token, only: [:create]
skip_before_action :some_custom_action, except: [:new]
def new
# code
end
def create
# code
end
protected
def some_custom_action
# code
end
end