I tried to use another function/method to redirect & output a notice, but it didn't work. It work fine within its own function.
def delete_sb
# #sb = SasaranBaru.find(params[:id])
# #sb.destroy
flash[:notice] = "fffff"
render_group("flash msg")
end
def render_group(notice)
logger.debug notice
flash[:notice] = notice
if params[:filter]
filter = prepare_filter_query(params[:filter])
redirect_to "/groups?#{filter.to_query}", notice: 'okokoko okokokok '
else
redirect_to "/groups", notice: 'hehehehe eheheheh'
end
end
there is no value for flash in my view.
Is there a redirect going on after this code? A flash is only valid for one request and then disappears.
One way to test this is use:
flash.keep[:notice]='ffffff'
and see if that shows up, but I suspect you are going through another controller in /group and redirecting again, losing the flash.
Related
A model in a Rails app has a url column, where users can enter the address of external sites.
The urls are displayed on a page. When clicked, in addition to routing to that url, I need to perform some actions in the app. So I defined a controller action as follows
#objects_controller.rb
def click
#object = Object.find params[:id]
# do some stuff
respond_to do |format|
format.html { redirect_to #object.url }
end
end
and in the view
<%= 'click me', click_object_path #object %>
Brakeman is (as expected) throwing a warning
High - Redirect - Possible unprotected redirect
Normally the solution to this would be to add only_path: true to the redirect and only allow redirects within the current app. But in this case the desired behaviour is to navigate to an external site.
My questions
Are there any steps I should be taking to ensure malicious code cannot be entered and activated from the Object.url column (or in other words, is my click controller action the best way to archive the desired in-app actions plus navigation)?
If this is the correct approach, is there a way to quieten Brakeman so that this particular issue is no longer reported?
For anyone else having a similar issue, I added some checks to my controller to verify that #object.url is indeed a properly formatted url.
def click
#object = Object.find params[:id]
if #object.url =~ URI::regexp
obj_url = URI.parse(#object.url)
else
obj_url = nil
end
# do some stuff
respond_to do |format|
format.html { redirect_to obj_url }
end
end
And Brakeman reports 1 fixed warning. Result!
In the app I am working on, the user can get to a new form from several different places. I need to redirect them back to where they came from. I solved it by passing a parameter in the link on the view, for example
= link_to "create a new post ยป", new_user_post_path(#current_user, :return_to => 'dashboard')
then in the new action in the controller like so
if params[:return_to] == 'dashboard'
session[:return_to]= 'dashboard'
end
now I am looking at the controller. what I need to do I can achieve by being really verbose, but I'm looking for a more elegant solution. Here is what I have now
if #user_post.save
flash[:notice] = "New Post Created"
if session[:return_to] == 'dashboard'
session.delete(:return_to)
redirect_to dashboard_path and return
else
redirect_to user_hub_path(#user)
end
else
flash[:error] = "Could not save post"
redirect_to new_user_post_path(#user)
end
This does what I need but I was hoping to tidy it up a little. I started looking at 1 line enumerators to see if I could do something like this...
if #user_post.save
flash[:notice] = "New post Created"
session[:return_to] == 'dashboard' ? redirect_to "#{session.delete(:return_to)}_path" : redirect_to user_hub_path(#user)
else
flash[:error] = "Could not save post"
redirect_to new_user_post_path(#user)
end
but it really doesn't like this part....redirect_to "#{session.delete(:return_to)}_path"
any advice? Guess I'm trying to get it to redirect and delete the session in one line and this is beyond my knowledge...
This looks like a good case for using Rails' built-in :back parameter, which, according to the Rails docs here, sends the user "Back to the page that issued the request. Useful for forms that are triggered from multiple places. Short-hand for redirect_to(request.env["HTTP_REFERER"])"
You can avoid passing a return_to param, and change your controller code to:
if #user_post.save
redirect_to :back, notice: "New Post Created" and return
else
redirect_to new_user_post_path(#user), flash: { error: "Could not save post" }
end
What about using send?
send takes a message name and optional arguments and forwards that to send's receiver (http://ruby-doc.org/core-2.2.0/Object.html#method-i-send)
path = send("#{session.delete(:return_to)}_path")
redirect_to path
In this case it sends the message to the current controller instance (same as just calling the ..._path method but gives the flexibility of the dynamic call)
Please instead of using a redirect_to variable of your controller, use the Referer Header.
HTTP referer (originally a misspelling of referrer) is an HTTP header field that identifies the address of the webpage (i.e. the URI or IRI) that linked to the resource being requested
In Rails is quite simple inside a controller
redirect_to request.referer
That is more elegant and efficient, because the session cookie storage can be expensive (cache storage) and could affect your HTTP cache proxies performance.
I have standard bug with notices, but I can't make it work correctly.
I'm calling some after_filter to verify if updated data is correct.
Here is code from before filter with notices:
after_filter :verify, :on => :update
def verify.
...
if account_status == "VERIFIED"
flash[:success] = "Your account is verified"
else
flash[:error] = "Sorry, your account is not verified or you entered wrong credentials"
end
so when I use this notices stays on my page after redirection to other page.
When I'm using flash.now[:notice] I lost my messages and they didn't show.
I know, that is standard problem, but I can't find solution that was working for me.
at this moment (before click) my account isn't verified(not correct data).So I'm change them into correct
After I click save it shows me this:
( http://i.imgur.com/j3uw8.png )
but after refreshing page:
( http://i.imgur.com/4EtrL.png )
If you want to set a flash notice that doesn't persist you need to do
flash.now[:notice] = "..."
not flash[:now]
If you want a flash value to be carried over to another request, use the keep method:
def index
# Will persist all flash values.
flash.keep
redirect_to users_url
end
I have this code :
def create
login(params[:email], params[:password])
if current_user
flash[:notice] = "Welcome back #{current_user.email}"
return redirect_to_first_page
else
flash[:notice] = "Email or password is wrong. Try again !"
redirect_to root_url
end
end
when the login is successful the flash is set and the redirect to the first page is made.
This part is working. The second part is not setting the flash notice message. Then when the page is displayed no message from flash is show. What is different i've try to have
return redirect_to root_url
but nothing still not showing anything.
In my controller i have a helper like flash_notice all it does is return flash[:notice].
This is because the flash is always empty in a view but accessible in controller.
In the view i have just one line :
<%= flash_notice %>
I'm using rails 3.1
Chris Drappier is correct, the flash hash is current for one request only. You can invoke a "keep" method with
flash.keep[:notice]="This message will persist"
Personally, I like to keep the flash in question in params when needed. The gory details are here:
http://guides.rubyonrails.org/action_controller_overview.html#the-flash
So I have a method in a reservation model called add_equip. This method does some checking to make sure the added piece of equipment is valid (not conflicting with another reservation).
The checks work. If a added piece of equipment shouldn't be added it isn't, and if it should it is.
The problem is I can't figure out how to send the messages back up to the controller to be put in the flash message? I know I must be missing something here, but I've googled for a few hours now and can't really find any clear explanations how how to pass errors back up the the controller, unless they are validation errors.
add_equip in reservations_controller
def add_equip
#reservation = Reservation.find(params[:id])
#addedEquip = Equip.find(params[:equip_id])
respond_to do |format|
if #reservation.add_equip(#addedEquip)
flash[:notice] = "Equipment was added"
format.html { redirect_to(edit_reservation_path(#reservation)) }
else
flash[:notice] = #reservation.errors
format.html { redirect_to(edit_reservation_path(#reservation)) }
end
end
end
add_equip in reservation model
def add_equip equip
if self.reserved.find_by_equip_id(equip.id)
self.errors.add_to_base("Equipment Already Added")
return false
elsif !equip.is_available?(self.start, self.end)
self.errors.add_to_base("Equipment Already Reserved")
return false
else
r = Reserved.new
r.reservation = self
r.equip = equip
r.save
end
end
Any help would be greatly appreciated. I know I'm missing something basic here.
Using add_to_base to store the error message seems fine to me, you just need to figure out how to get it into the view.
How about:
flash[:notice] = #reservation.errors.full_messages.to_sentence
Assuming you're going to re-display a form, you could also probably use:
<%= f.error_messages %>
Or possibly:
<%= error_messages_for :reservation %>
Also, you might want to use flash[:error], then you can color it differently with a CSS class in your view.
I think I can see why errors are not being passed back to the user.
The problem is that you are sending a redirect to the user when the action fails instead of just doing a render, that means you lose any variables you set up to use within the request. Instead of adding errors to the flash, just render the edit page and set the flash to a normal message and everything should be fine.
For example:
def add_equip
#reservation = Reservation.find(params[:id])
#addedEquip = Equip.find(params[:equip_id])
respond_to do |format|
if #reservation.add_equip(#addedEquip)
flash[:notice] = "Equipment was added"
format.html { redirect_to(edit_reservation_path(#reservation)) }
else
flash[:error] = 'Error adding equipment'
format.html { render :action => :edit }
end
end
end
Now you can continue to use the normal form helpers for displaying error messages.
Also, just a little suggestion for the model code, try to use i18n when possible (including for flash messages in the controller). Although this is mostly a personal preference, it gives a logical home to all your messages and specific text, and alos allows you to create general or default messages which can be changed in one place instead of duplicating the change in multiple models and controllers.
eg.
def add_equip equip
if self.reserved.find_by_equip_id(equip.id)
self.errors.add_to_base(:already_added)
return false
elsif !equip.is_available?(self.start, self.end)
self.errors.add_to_base(:already_reserved)
return false
else
r = Reserved.new
r.reservation = self
r.equip = equip
r.save
end
end