Is it possible for me to find out what the last route/page a user was on in one of my controllers? For example, if the user was on /home, then moved to /contact, is there was way for me to find out he was at /home within my controller?
Thanks
request.referer will give you the url which issued the request. If you need more informations like the path, you can use URI and write in your controller something like:
last_page_path = URI(request.referer).path
Related
I have been programming in Ruby on Rails for a while now, but never really dug deep into routing until recently. After reading a fair amount of documentation and googling, I haven't been able to answer this question.
How do you change a URL after a route is matched? To better explain this, let me set a scenario I'm trying to solve. The root of my website while testing is localhost:3000. My login page is localhost:3000/login. Once logged in though, I want the URL to read localhost:3000 again with no extension. The actual page name is dashboard and my route is as follows currently.
get 'dashboard' => 'user#dashboard'
This only matches when the URL is localhost:3000/dashboard, but I wan't to have cleaner URL like a lot of sites have. How is this achieved with Ruby On Rails? I want to avoid a javascript solutions or anything that is a workaround.
Any help or tips is greatly appreciated. Many thanks in advance.
I've provided the solution below, but I agree with max that your wanting to make a RESTful URL less meaningful is backwards. You should strive to alias a URL to make it more meaningful (e.g. from site.com/posts/34239482069472/ to site.com/posts/my-post-title).
The URL that appears in the address bar is an instruction to an app. When a user puts "site.com/dashboard" into the address bar, they're instructing the app to make an HTTP request get 'dashboard'. The Controller#action is a set of instructions the app executes when it receives that request. If you're following Rails naming convention then Users#dashboard will retrieve data and then by default render the view template at views/users/dashboard.html.erb. Understand this: you're not changing the URL for a given view, you're changing which view template is rendered by the Controller#action that is set for that url.
This means the Controller#action for your root_url (i.e. your root to: 'controller#action' in config/routes.rb) should render one view template if user is logged in and a different view template if a user is not logged in. Assuming root to: welcome#index, your controller action would look something like this:
app/controllers/welcome_controller.rb
def index
# db queries, logic, set #variables
if session[:user_id]
render "users/dashboard" # app/views/users/dashboard.html.erb
else
render "index" # app/views/welcome/index.html.erb
end
end
Note that if the view template you want to render corresponds to the controller, e.g. users_controller.rb action is rendering a view in views/users, then you only need to give the view name, otherwise you need to give a path (relative to app/views).
Why? /dashboard is a proper RESTful definition of a resource. In REST a route should have the same response independent of state. So having a radically different root page for a logged in user violates REST.
Also your users may want to access the index page as well the dashboard and you would be denying them that possibility.
These kind of URL micro-optimizations do not warrant hacking a bunch of state into your routes definitions.
I use require_admin! frequently in my controllers. It works great.
Now, I want to add named route like so:
# config/routes.rb
match "poniesandrainbows" => redirect("https://poniesandrainbows.com")
# ^sadly, not really a website, btw.^
How do I restrict access to that route? Is this possible? Obviously it redirects to a public URL, but I still want to keep the route private.
You cannot restrict access from routes.
The safest way to match "poniesandrainbows" with a controller where you can use require_admin! and then redirect them to the public url.
You can try to solve the problem on the front end. Maybe only show the link to admin users.
It won't stop other users to paste the link directly to their browser url though
That kind of functionality should be encapsulated in the controller. The router handles the plumbing of passing a request to the correct controller. It is the controller's job to correctly figure out how to process the request. In this cause, the controller would use the auth service (such as require_admin!) to determine if the user is allowed to be redirected or if they are doom to another fate.
It is actually possible although as the other posters mentioned very rarely a good idea. You can read about how in this blog post: (scroll down to the routes section)
http://collectiveidea.com/blog/archives/2011/05/31/user-centric-routing-in-rails-3/
I have an url
domain.com/a
which redirects to
domain.com/controller/action/a .
How do I get the referrer (i.e domain.com/a) in my action for domain.com/controller/action/a ?
One option was to add the referring domain as a parameter .
domain.com/controller/action/a?referral=domain.com/a .
Is there a way to get the referrer without passing old referrer as a parameter. Like we would get from **request.referrer**. request.referrer doesn't seem to work with redirected urls.
I am using Ruby on Rails for my development.
I store the referrer path in the session right before redirection
session[:referrer]=url_for(params)
and then use it where I need it via session[:referrer].
I believe you are looking for the request.referrer property: http://rack.rubyforge.org/doc/classes/Rack/Request.html#M000280
We use this line in our application_controller.rb to save the http_referer when a visitor visits our site:
session[:http_referer] = request.env["HTTP_REFERER"]
Later on, we will save the value into our model for tracking.
May be late, but just to add on. I think it is important to remove the session after using it.
redirect_to session.delete(:referrer)
i'm having a situation (pretty standard for everybody i guess), where i have to do two things :
If a user asks for /user path, i have to present his/her personal information.
If a user asks for /user/:id path, i have to present information about that particular user, or the current user information if :id matches the current_user id.
There are definitely many ways to do that, but what is the best approach ? Should i have 2 different routes like /show/:id and /show_current, handled by different actions, or just have a /show/:id and do the handling in that action ?
Bear in mind that if this is the current view, i need to render a different more detailed view than the one about another view. I think the latter is probably the better way,but what do you think ?
If the current user is, say, 42 then /user/42 and /user would display the same information but /user/23 would display a stripped down public version of 23's data. So, the handler for /user/:id will have to know about the special case of :id being the current user; the handler for /user will also have to know about this special case as that's all it does.
If you use two routes then you'll either be duplicating code, wrapping the real code in an extra layer, or some other bit of busy work. I'd just send them both to the same controller method and that could start with something like this:
user = params['id'] ? User.find(params['id']) : current_user
And then later on you handle the special case of the requested user being the current user in just one place with something simple:
if(user == current_user)
# show the full blob of information
else
# show just the limited public information
end
You could, of course, slice it up into a bunch of little methods, such as show_current_user_info and show_other_user_info, inside the controller. The handler for /user could just be a call to show_current_user_info; the /user/:id handler could call show_current_user_info or show_other_user_info depending on what :id is. This approach smells like pointless layering to me.
In RESTful routing, you've described users_path and user_path(some_id). These map to User#index and User#show. The index method is normally a list of users, but if you are wanting index to show the current_user personal information, you can certainly do that. If you also need a list method, just add it to your controller and create a route to it.
Depending on the subdomain I want to call a specific controller.
What I currently do:
My page uses the subdomain to identify users like username.site.com. I get the username, look it up in the database and render the appropriate data in the UsernamesController.
the only exception to this is www.site.com or site.com . In that case another controller should be called. I currently do this by detecting the www or '' subdomain in `ApplicationController and then redirecting. Although I feel that a redirect is not in it's place here.
Someone has another approach?
Thanks
subdomains_routes allows you to define custom routes based on current subdomain.