views:

89

answers:

2

I'm trying to get my head around this one:

Say you have two models where:

:bar has_many :foos

And you have a url like this: http://myapp.com/24-name-of-the-bar-to-param/foos/new

On my site this page shows a lot of information about the bar which users are going to create a foo for. So, even if a user isn't logged in the user will still be able to see the info.

Currently, when the user is logged in, a form to create a new foo is on the left hand side of the web page. When the user isn't logged in it says "Please login or register"

The form explains a lot about how my app works, so I'd like to change it so that even if a user isn't logged in the form will display, and if they click submit it will take them to the login_path and then when they login, back to the path where the submitted the form.

I'm running into this problem: Currently I have a login_required method in my application controller like this:

    def store_location
            session[:return_to] = request.request_uri
    end
 def login_required
  unless current_user || admin?
      store_location
      flash[:notice] = "Please log in"
      redirect_to login_path and return false
  end
 end

This login required action is called on the create action of the foo. When I click submit on the form it takes me to http://myapp.com/foos instead of http://myapp.com/24-name-of-the-bar-to-param/foos/new

I assume this is because the login required function is called on the create action and not the new action.

Any ideas?

UPDATE as per request here is the controller code and callbacks:

  before_filter :find_bar, :except => [:index, :edit, :update]
  before_filter :login_required, :only => [:create]
  ssl_required :edit, :update


  def new
   @foo = Foo.new :amount =>  "0.00"
   @foos = Foo.find(:all, :conditions => ["bar_id = ?", @bar.id], :order => "created_at DESC").paginate :page => params[:page], :per_page => 10
   @foos_all = Foo.find(:all, :conditions => ["hatlink_id = ?", @hatlink.id], :order => "created_at DESC")
   @current_user = current_user
   @topfooers = User.bar_amount(@bar, nil)
   @average_foo = @bar.foos.average('amount')
  end

  def create
   @foo = @current_user.foos.build params[:foo]
   if (@bar.foos << @foo)
    flash[:notice] = "Thank you for fooing!"
    redirect_to new_bar_foo_path(@bar)
   else
    render :action => :new
   end
  end
private
  def find_bar
 @bar_id = params[:bar_id]
 return(redirect_to(categories_path)) unless @bar_id
 @bar = Bar.find(@bar_id)
  end
+2  A: 

You could store the referring url (if it's present) & redirect to that page if the request was a POST or PUT. Something like:

def store_location
  if request.post? || request.put?
    session[:return_to] = request.env['HTTP_REFERER']
  else
    session[:return_to] = request.request_uri
  end
end
jdeseno
Thanks jdesno! That would probably work. I think I just came up with a solution of my own. I'll post it below for other people's scrutiny.
Kenji Crosland
+1  A: 

Silly of me to come up with a solution just five minutes after posting the question. Oh well, here's what I did (and it works).

In the "new" action of foo I added these lines

if !current_user
    store_location
end

In the login required method I have added this:

if params[:controller] == "foos" && params[:action] == "create"
                #Took out the line for storing the location in this method.
                    flash[:notice] = "Please log in"
                redirect_to login_path and return false
Kenji Crosland