Chris Mayan
2010-Mar-15 23:41 UTC
Before_filters on re-rendered methods - what is the correct RAILS way?
Hello, My Question: ------------ How can one have the equivalent of "before_filter" checking (e.g. to require a user to be logged in before carrying out an action) on a method when the method is called implicitly inside another action (the before_filter doesn''t seem to get run)? Background: ------------ So in this instance I have a restful controller that allows users to enter a new "entry", but after they click the next button instead of automatically creating the new entry, I would like to provide an additional "confirmation" stage where they can confirm their entry details, and their entries can be validated as well. _After_ they have confirmed and the entries validated, then I would like to call the create action where it is then created. My understanding is that you can''t redirect a post request to another handler (without writing a separate ruby method to create a HTTP request that resends the POST parameters etc..) and so what I have read somewhere else is to do if/then/else checking with params of the submit button''s name instead. Unfortunately doing it this way (refer to code below), the before_filter which requires a user to be logged in, doesn''t get run. What I would like to do is place no restrictions up to the confirmation stage, and only require a logged in user for the create action. Is there a right way to do this or is this just a really un-rails way of doing this - in which case how should it be done normally? Thanks for your help! Sample Code (Rails v2.3.4): --------------------------- class EntryController < ApplicationController before_filter :require_user, :only => [:create] # ==new # new_entry_url (GET /entries/new) def new # Display user a form page where they can fill # in details of a new entry, which will then # submit a post request to "confirm" end # ==confirm # confirm_new_entry_url (POST /entries/new/confirm) def confirm # Check params for button type so we can still handle it # as a "post" request without redirection if params["next"] # Validate entry and present user with a confirmation page # so they can check their entries are correct _before_ # entry is created. elsif params["create"] # Called from the confirmation page where there will # be a button with name "create" create render :action => :create return elsif params["back"] # Called from the confirmation page where there will # be a button with name "back" to correct user''s entries new render :action => :new return end # ==create # entries_url (POST /entries) def create # This action should only be run if the user is logged in! # But because of the re-rendering from confirm action, # the before_filter that checks whether user is logged in or # not does not seem to get run. # # @entry.save etc... end end Thanks, Chris -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Sharagoz --
2010-Mar-16 20:12 UTC
Re: Before_filters on re-rendered methods - what is the correct RAILS way?
render :action => :create only renders the template for the create action, it doesnt run the actual action, thats why the before filter doesnt get called. Rendering actions and rendering templates are very similar. So simliar that Im not sure why they arent merged into one. Why are you going with one controller action and the if/elsif/else solution instead of just separating steps into different controller actions? -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Chris Mayan
2010-Mar-16 23:31 UTC
Re: Re: Before_filters on re-rendered methods - what is the correct RAILS way?
Hello, render :action => :create only renders the template for the create> action, it doesnt run the actual action, thats why the before filter > doesnt get called. >But if you look at the sample code, I did try to call the "Create" method as well as rendering its template: elsif params["create"] # Called from the confirmation page where there will # be a button with name "create" create render :action => :create return> Why are you going with one controller action and the if/elsif/else > solution instead of just separating steps into different controller > actions? > -- >The two controller actions are required because of 2 different security requirements. The before_filter :require_user only applies to the "Create" controller action, and shouldn''t be a requirement for "Confirm" or for filling out a "New" entry. From the Confirm action there is also a need to allow a "Back" step (via posting back the params again) and this also shouldn''t require a user constraint. A poor-man''s solution is to manually call the "require_user" method at the top of the create function - but this doesn''t seem elegant and bypasses the whole point of the before_filter. What I don''t understand is why doesn''t the *_filters run on _every_ invocation of all Controller methods (including being called from within another method) and not just when it is called via the normal means of handling a routing request? Another possible solution is of course to place 2 buttons on a page that would point to 2 different action action handlers - but I don''t know how one would go about doing this without JavaScript and still be DRY. If you have other suggestions keep it rolling :) - Chris -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Sharagoz --
2010-Mar-17 08:35 UTC
Re: Re: Before_filters on re-rendered methods - what is the correct RAILS way?
> But if you look at the sample code, I did try to call the "Create" > method as well as rendering its templateNo you didnt. render :action => :create is identical to render :template => ''mycontroller/create''. You might as well comment out the create action, its not getting called at all in your current code. Im gonna suggest that you create one controller action for each step instead of trying to combine several steos into one action. To keep track of the object inbetween the requests you can store it in session. def new @stuff = session[:stuff] || Stuff.new # session[:stuff] is used when the user clicks ''back'' on the confirm page end def confirm session[:stuff] = @stuff = Stuff.new(params[:stuff]) end def create session[:stuff].save session[:stuff] = nil end The way Im using sessions here isnt 100% by the book. Generally you dont want to store entire objects in session. One of the main reasons is that session objects can become incompatible with the code when you change something. The best way would be to actually store the temporary object in the database and then only store its ID in session. You can mark the temporary object as temporary with a boolean flag or have an entire table dedicated to temporary objects. The code above should be enough to get you started though. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.