Before_filters on re-rendered methods - what is the correct RAILS way?

Hello,

My Question:

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?

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 :slight_smile:

  • Chris

But if you look at the sample code, I did try to call the "Create" method as well as rendering its template

No 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.