# Before\_filters on re-rendered methods - what is the correct RAILS way?

**URL:** <https://www.ruby-forum.com/t/before-filters-on-re-rendered-methods-what-is-the-correct-rails-way/185217>\
**Category:** Rails\
**Created:** [March 16, 2010, 9:10am UTC](https://www.ruby-forum.com/t/before-filters-on-re-rendered-methods-what-is-the-correct-rails-way/185217 "2010-03-16T09:10:17Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chris\_Mayan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Chris\_Mayan](https://www.ruby-forum.com/u/Chris_Mayan)\
**Post date:** [March 16, 2010, 9:10am UTC](https://www.ruby-forum.com/t/before-filters-on-re-rendered-methods-what-is-the-correct-rails-way/185217/1 "2010-03-16T09:10:17Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Chris\_Mayan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Chris\_Mayan](https://www.ruby-forum.com/u/Chris_Mayan)\
**Post date:** [March 16, 2010, 9:12pm UTC](https://www.ruby-forum.com/t/before-filters-on-re-rendered-methods-what-is-the-correct-rails-way/185217/2 "2010-03-16T21:12:26Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![Chris\_Mayan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Chris\_Mayan](https://www.ruby-forum.com/u/Chris_Mayan)\
**Post date:** [March 17, 2010, 12:33am UTC](https://www.ruby-forum.com/t/before-filters-on-re-rendered-methods-what-is-the-correct-rails-way/185217/3 "2010-03-17T00:33:20Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Chris\_Mayan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Chris\_Mayan](https://www.ruby-forum.com/u/Chris_Mayan)\
**Post date:** [March 17, 2010, 9:35am UTC](https://www.ruby-forum.com/t/before-filters-on-re-rendered-methods-what-is-the-correct-rails-way/185217/4 "2010-03-17T09:35:58Z")

</div>

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