rails 5 redirect_back not working - ruby-on-rails

i have a admin edit page and form in here. when i submit the form, it is going to the update action and updates the admin, there is no problem. After the update, i want redirect to the index page in the same controller. But it gets redirected to the edit form again. I tried a couple of things but in vain and gets redirected to edit page. i tried too much things but it is always going to edit page.
Controller (admins_controller.rb)
class Admin::AdminsController < ApplicationController
def index
#admins = Admin.all
end
def edit
#admin = Admin.find(params[:id])
end
def update
#admin = Admin.find(params[:id])
if #admin.update(admin_params)
redirect_back fallback_location: admin_admins_path
else
render 'edit'
end
end
private
def admin_params
params.require(:admin).permit(:id, :username, :password)
end
end
I'm trying admin_admins_path it does not work.

redirect_back like its name, it redirects to the route which it submitted the request, in this case is the edit page.
you should use redirect_to
redirect_to admin_index_path

Related

redirect_to the previous page but changing the language

What am I trying to do? To redirect the user in the previous page with the website translated in new language selected
My previous script was (language_controller):
class LanguagesController < ApplicationController
def edit
#language = Language.find_by(locale: I18n.locale)
render layout: false
end
def update
#language = Language.find(update_params[:id])
if user_signed_in?
setting = current_user.setting || current_user.build_setting
setting.language = #language.id
setting.save
end
redirect_to root_path(locale: #language.locale)
end
private
def update_params
params.require(:language).permit(:id)
end
end
As you can see, there is redirect_to root_path that redirect the user in the home page. Even if he is changing the language in an article-page
So I edit it and I added in edit session[:return_to] ||= request.referer
and in my update action I replaced redirect_to root_path(locale: #language.locale)
with redirect_to session.delete(:return_to)
What is happening? If the user is logged, it works very good and it redirects the user in the previous page.
If the user is not logged he is redirected in previous page BUT now the language is the same. Probably because I removed (locale: #language.locale), right?
I also try to edit redirect_to in this way: redirect_to session.delete(:return_to, locale: #language.locale)
but it said that I can not add two elements there.
How to solve?

Setting up logging out...is there a way to check if a controller action contains a before_action

I have a before_action :logged_in_user in my controller which redirects to the login_path if there is no current_user.
I am struggling with the logic of how to setup logout (destroy a session) in my app.
If a user is on a page where they are not required to be logged_in?, I want the logout just to redirect_to :back (stay on that page) since it does not effect the current page viewing.
If they are on a page that requires that they are logged_in?, I want them to be redirect_to :root_url, because otherwise they will be redirect_to the login_path which is awkward since they just logged_out.
So basically in pseudo code I want to do the following:
redirect_to :back
unless :back controller:action >> before_action :logged_in_user
then redirect_to root_url
SessionsController
def destroy
destroy_location
log_out if logged_in?
redirect_logout
end
def destroy_location
path = ["/feed", "/friends", "/saved_articles", "/favorites"]
if path.any?{|word| URI(request.referrer).path == word }
session[:exit] = root_url
end
end
def redirect_logout
redirect_to(session[:exit] || :back)
session.delete(:exit)
end
This works rather nicely!

redirecting from another page taking info

So after the user signs up, i redirect them to my additional info page where i collect some more information. However, something is wrong with my design/implementation as rails is saying im missing users/create template
this is my users controller
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def additional_info
#user = User.new(user_addinfo)
if #user.save
redirect_to show_path
end
end
def create
#user = User.new(user_params)
if #user.save
# UserMailer.welcome_email(#user).deliver
sign_in #user
redirect_to additional_info_path
flash[:success] = "Welcome to InYourShoes!"
#return #user
else
render'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def user_addinfo
params.permit(:year)
end
end
def show is the user profile page i want to show after redirecting to the additional_info page
def additional_info is just take additional info from the private method def user_addinfo
def create is the sign up process.
After entering the basic user info, it gets redirected to additional which is fine. but after the additional, it says im missing the users/create template, but my code i attempted to redirect to show_path and #usersshow, still doesnt work
any suggestions? sorry if this seems intuitive but Im new to rails.
I think your problem is in the additional_info method, as i said in the comment. What you're doing is:
creating a user
creating a session for the user (sign_in #user) - storing somewhere the user_id in the session
redirecting to your additional_info page
And here comes the problem. As the user is already signed in you don't have any need to create a new user with additional params. You should have some helper to retrieve the current signed in user (like current_user) and in additional_info method, just update it.
So your additional_info method would become something like:
def additional_info
user = User.find session[:user_id]
user.update params[:user]
redirect_to user_path #show action
end

Rails update_attributes always redirects

I'm writing a edit page for a record in my database, I want to redirect if the update was successful and render the edit page again for any errors. Here is the code:
def edit
#list = List.find(params[:id])
if #list.update_attributes(params[:list])
redirect_to(root_path)
else
render('edit')
end
end
The redirect fires as soon as I launch the edit page, before any changes are made or the submit button is clicked.
Any ideas greatly appreciated.
Your edit action should look like this:
def edit
#list = List.find(params[:id])
end
It renders the edit view. The form should point (and probably is) to the update action that should look like so:
def update
#list = List.find(params[:id])
if #list.update_attributes(params[:list])
redirect_to(root_path)
else
render :edit
end
end

return redirect_to in private controller method

Preface: I'm using devise for authentication.
I'm trying to catch unauthorized users from being able to see, edit, or update another user's information. My biggest concern is a user modifying the form in the DOM to another user's ID, filling out the form, and clicking update. I've read specifically on SO that something like below should work, but it doesn't. A post on SO recommended moving the validate_current_user method into the public realm, but that didn't work either.
Is there something obvious I'm doing wrong? Or is there a better approach to what I'm trying to do, either using devise or something else?
My UsersController looks like this:
class UsersController < ApplicationController
before_filter :authenticate_admin!, :only => [:new, :create, :destroy]
before_filter :redirect_guests
def index
redirect_to current_user unless current_user.try(:admin?)
if params[:approved] == "false"
#users = User.find_all_by_approved(false)
else
#users = User.all
end
end
def show
#user = User.find(params[:id])
validate_current_user
#user
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
validate_current_user
#user
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, :notice => 'User was successfully created.' }
else
format.html { render :action => "new" }
end
end
end
def update
#user = User.find(params[:id])
validate_current_user
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, :notice => 'User was successfully updated.' }
else
format.html { render :action => "edit" }
end
end
end
private
def redirect_guests
redirect_to new_user_session_path if current_user.nil?
end
def validate_current_user
if current_user && current_user != #user && !current_user.try(:admin?)
return redirect_to(current_user)
end
end
end
The authenticate_admin! method looks like this:
def authenticate_admin!
return redirect_to new_user_session_path if current_user.nil?
unless current_user.try(:admin?)
flash[:error] = "Unauthorized access!"
redirect_to root_path
end
end
EDIT -- What do you mean "it doesn't work?"
To help clarify, I get this error when I try to "hack" another user's account:
Render and/or redirect were called multiple times in this action.
Please note that you may only call render OR redirect, and at most
once per action. Also note that neither redirect nor render terminate
execution of the action, so if you want to exit an action after
redirecting, you need to do something like "redirect_to(...) and
return".
If I put the method code inline in the individual controller actions, they do work. But, I don't want to do that because it isn't DRY.
I should also specify I've tried:
def validate_current_user
if current_user && current_user != #user && !current_user.try(:admin?)
redirect_to(current_user) and return
end
end
If you think about it, return in the private method just exits the method and passes control back to the controller - it doesn't quit the action. If you want to quit the action you have to return again
For example, you could have something like this:
class PostsController < ApplicationController
def show
return if redirect_guest_posts(params[:guest], params[:id])
...
end
private
def redirect_guest_post(author_is_guest, post_id)
redirect_to special_guest_post_path(post_id) if author_is_guest
end
end
If params[:guest] is present and not false, the private method returns something truthy and the #show action quits. If the condition fails then it returns nil, and the action continues.
You are trying and you want to authorize users before every action. I would suggest you to use standard gems like CanCan or declarative_authorization.
Going ahead with this approach you might end up reinventing the wheel.
In case you decide on using cancan, all you have to do is add permissions in the ability.rb file(generated by rails cancan:install)
can [:read,:write,:destroy], :role => "admin"
And in the controller just add load_and_authorize_resource (cancan filter). It will check if the user has permissions for the current action. If the user doesnt have persmissions, then it will throw a 403 forbidden expection, which can be caught in the ApplicationController and handled appropriately.
Try,
before_filter :redirect_guests, :except => [:new, :create, :destroy]
should work.
This is because you are using redirect twice, in authenticate_admin! and redirect_guests for new, create and destroy actions.
"Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action."
That's the reason of the error. In show method, if you are neither the owner of this account nor the admin, you are facing two actions: redirect_to and render
My suggestion is to put all of the redirect logic into before_filter

Resources