There is a user registration controller:

class UsersController < ApplicationController def new unless current_user @user = User.new else redirect_to root_path, alert: "You are already signed up!" end end def create unless current_user @user = User.new(user_params) if @user.save sign_user_in(@user.auth_token) redirect_to root_path, notice: "Signed up&in!" else render 'new' end else redirect_to root_path, alert: "You are already signed up!" end end private def user_params params.require(:user).permit(:email, :password, :password_confirmation) end end 

There is also a user login controller for the site:

 class SessionsController < ApplicationController def new if current_user redirect_to root_path, alert: "You are already signed in!" end end def create unless current_user user = User.find_by_email(params[:email]) if user && user.authenticate(params[:password]) sign_user_in(user.auth_token) redirect_to root_path, notice: "You have been succussfully signed in!" else flash.now[:alert] = "Wrong E-mail or password" render 'new' end else redirect_to root_path, alert: "You are already signed in!" end end def destroy cookies.delete(:auth_token) redirect_to root_path, notice: "You have been successfully logged out!" end end 

It is necessary to make it so that an already logged in user cannot get to the registration and login pages (because why should an authorized user log in / register on the site again?).
Immediately I thought to use before_action, but the fact is that my current_user method returns an instance of the User class. I thought to create a method current_user ?, which would return whether the user entered the site or not (boolean value), but then you still have to use the if (unless) / else constructs. And this is not DRY at all. How to correctly solve the situation to remove duplication of code?

  • Do you use devise? In my opinion, this is what he does by default; he doesn’t allow access to the registration page and log in if you are already logged in. Do you look like rouses for him? - cheops
  • @cheops no, I do not use. - smellyshovel

1 answer 1

You can do the following for UsersController

 class UsersController < ApplicationController before_action :redirect_sign_in, only: [:new, :create] def new @user = User.new end def create @user = User.new(user_params) if @user.save sign_user_in(@user.auth_token) redirect_to root_path, notice: "Signed up&in!" else render 'new' end end private def redirect_sign_in if current_user redirect_to root_path, alert: "You are already signed in!" end end def user_params params.require(:user).permit(:email, :password, :password_confirmation) end end 

And for SessionsController

 class SessionsController < ApplicationController before_action :redirect_sign_in, only: [:new, :create] def new; end def create user = User.find_by_email(params[:email]) if user && user.authenticate(params[:password]) sign_user_in(user.auth_token) redirect_to root_path, notice: "You have been succussfully signed in!" else flash.now[:alert] = "Wrong E-mail or password" render 'new' end end def destroy cookies.delete(:auth_token) redirect_to root_path, notice: "You have been successfully logged out!" end private def redirect_sign_in if current_user redirect_to root_path, alert: "You are already signed in!" end end end 

So that the definition of the redirect_sign_in method does not repeat from the controller to the controller, it can be put into a jerk mixed into the controllers with the help of include . To do this, in the controllers folder, create a subfolder of concerns, create in it the file filters_concern.rb in the following content

 module FiltersConcern extend ActiveSupport::Concern def redirect_sign_in if current_user redirect_to root_path, alert: "You are already signed in!" end end end 

After this, the redirect_sign_in method can be removed from the controllers and the Contern FiltersConcern can be included in them FiltersConcern

 class UsersController < ApplicationController include FiltersConcern before_action :redirect_sign_in, only: [:new, :create] ... end class SessionsController < ApplicationController include FiltersConcern before_action :redirect_sign_in, only: [:new, :create] ... end 
  • Unfortunately, the cans are not familiar to me. Can I bring in ApplicationController? - smellyshovel
  • @Matvey Mamonov so read . It will be useful. - D-side
  • @ Matvey Mamonov, corrected the answer. - cheops
  • @ D-side Needless to say, if I find out that I don’t know something, I go and read about it :) But thanks for the link, you have accelerated the process. - smellyshovel
  • @cheops Well, thanks, now it became clear. But still: why did you not render this method to ApplicationController? Is this bad practice (putting filters into ApplicationController)? - smellyshovel