Route depending on a session value? - ruby-on-rails-3

Is it possible to route a request depending on a session value?
I would like to route /test to test#withoutsession or /test to test#withsession depending on a session value.

Your best bet is probably applying dynamic constraints to your routes, like this:
get '/test', :to => 'test#withoutsession', :constraints => lambda{ |req| req.session[:user_id].blank? }
get '/test', :to => 'test#withsession', :constraints => lambda{ |req| req.session[:user_id].present? }
Reference: http://edgeguides.rubyonrails.org/routing.html#advanced-constraints

Related

How to Force SSL to Specific Named Route in Rails

I have a Rails Application in which I have used force_ssl method as
def force_ssl # to use https for payment page
if !Rails.env.development? && !request.ssl?
redirect_to :protocol => 'https'
end
end
for a Particular action name 'abc' with named route
match '/find-a-abc' => "home#abc"
when I go to URL
http://local.demo.com/find-a-abc
it will redirect_to https://local.demo.com/abc
Any Solution? so it will redirect_to Particular route, rather than redirecting to an Action when using a https Protocol.
It doesn't look like you've provided a named route here (i.e. match '/find-a-abc' => "home#abc", :as => :named_route). You will need to do this and call named_route_url rather than just the controller and action to get the right URL.
If you want a specific route to always be handled with SSL, you could define the route like so:
scope :protocol => 'https://', :constraints => { :protocol => 'https://' } do
match '/find-a-abc' => "home#abc", :as => :abc
end
Then abc_url should always be "https://local.demo.com/find-a-abc"

omniauth + devise "user/auth/facebook" magic route question

On a rails 3 app, I've got these routes defined:
devise_for :users, :controllers => {:omniauth_callbacks => "users/omniauth_callbacks", :registrations => 'registrations'}, :path_names => { :sign_in => 'login', :sign_out => 'logout' } do
get 'login' =>'devise/sessions#new', :as => :new_user_session
post 'login' => 'devise/sessions#create', :as => :user_session
get 'signup' => 'registrations#new', :as => :new_user_registration
get 'signout' => 'devise/sessions#destroy', :as => :destroy_user_session
end
# catchall route to deal with routing errors
match "*path" => "error#index"
However, now when I go to log /user/auth/facebook, it routes me to the errors page...
My solution to this was to add constraints to the final match:
match "*path" => "error#index", :constraints => lambda {|req| !req.path.starts_with?("/users/auth/") }
This works, but I am wondering if there is a better way... ?
I think you are better off letting a 404 page handle routing errors. You only get a 500 error in development. It's a 404 in production. For example on my site: http://agmprojects.com/test. So i suggest using the 404.html in the public folder instead, rather than loading that controller. Out of curiosity, are you responding with a 404 http status code?

Rails do something and redirect?

is there a way to execute code and then redirect inside the routes-file like this:
get 'cache/clear' => Proc.new { Rails.cache.clear && redirect('/') }
I just really don't want to create a controller for this particular action.
Yup. See here: http://www.railsdispatch.com/posts/rails-routing
match "/foo", :to => proc {|env| [200, {}, ["Hello world"]] }
or, more specifically for your case
match "cache/clear", :to => redirect {Rails.cache.clear && '/'}

Rails 3 Routing question

I have an issue where I have an admin subdomain setup in the routes like so:
constraints :subdomain => 'admin' do
scope :module => "admin" do
match 'articles/:id/', :to => 'articles#show'
resources :articles, :events do
collection do
post :update_attribute_on_the_spot
end
end
root :to => "dashboard#index"
end
end
Then after that on articles for the main site I have:
resources :articles, :events, :george
match '/:year/:month/:day/:slug', :to => 'articles#show', :as => "article", :constraints => {:year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/ }
match '/event/:year/:month/:day/:slug', :to => 'events#show', :as => "event", :constraints => {:year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/ }
I am wondering how I make sure the main site routes are not used when the admin subdomain routes are in effect, as of now when going to the admin section articles show is mapped to the main site route and therefore the admin routes will not function unless that route is removed.
If anyone can show me the best way around this issue it would be great.
Thanks!
I did not realize declaring something with :as would overwrite any other route so simply:
match '/:year/:month/:day/:slug', :to => 'articles#show', :constraints => {:year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/ }
Fixed everything!

Rails3 RSpec testing custom redirect route in routes.rb

I have a custom redirection in my routes.rb which works fine at the ui:
match ':hash' => redirect { |params| begin url = Sharing.find_by_short_url(params[:hash]); "/#{url.shareable_type}/#{url.shareable_id}/" rescue '/' end }, :constraints => { :hash => /[a-zA-Z0-9]{7}/ }
What is does is takes a shortened url and looks up the actual url path.
However my test is failing:
it "routes GET 'STU1VWX' to stations/1" do
{ :get => "STU1VWX" }.should redirect_to(
:controller => "stations",
:action => "show",
:params => {:id => 1}
)
end
With:
1) Shorter URL redirect routes GET 'STU1VWX' to stations/1
Failure/Error: { :get => "STU1VWX" }.should route_to(
ActionController::RoutingError:
No route matches "/STU1VWX"
# ./spec/routing_spec.rb:12:in `block (2 levels) in <top (required)>'
So the problem is isolated at the test level. I know I could test this in a controller test but given that the code is in routes.rb I should not have to. Is there inherently a reason that using should route_to not to work in the case of redirection?
Looks like you're saying here that if you can't find the page belonging to the hash, then redirect to "/"
There's something really stinky about performing an ActiveRecord find in your routes.
If you have to redirect to a specific controller depending on the sharable type, then I'd put this as a separate controller with a redirect:
match "/:hash" => 'SharableController#redirect':constraints => { :hash => /[a-zA-Z0-9]{7}/ }
and then deal with finding the record and redirecting to the correct controller action from there:
class SharableController < ApplicationController
def redirect
#sharable = Sharable.find_by_sharable_type(params[:hash])
redirect_to controller: #sharable.sharable_type, action: 'show', id: #sharable.id
end
end
OR... depending on how similar the show actions are:
class SharableController < ApplicationController
def redirect
#sharable = Sharable.find_by_sharable_type(params[:hash])
render template: "#{#sharable.sharable_type.pluralize}/show"
end
end
If you're only dealing with GET requests, better to swap out match for get by the way:
get "/:hash" => 'SharableController#redirect', :constraints => { :hash => /[a-zA-Z0-9]{7}/ }