How to Force SSL to Specific Named Route in Rails - ruby-on-rails-3

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"

Related

My login route doesn't work after trying to force SSL via routes.rb

I want people to be able to both subscribe and login to my application via SSL. My original route, which was not SSL, was this:
resource :login, controller: "sessions" do
collection do
get 'new'
get 'create'
end
end
Worked great, but was unencrypted. Then I tried this:
scope :protocol => 'https://', :constraints => { :protocol => 'https://' } do
resource :login, controller: "sessions" do
collection do
get 'new'
get 'create'
end
end
end
Now Rails me:
No route matches [GET] "/login"
when I navigate to https://myapp.dev/login
Please note I am using Pow in development mode.
hmm, I was thinking it would just be
scope :constraints => { :protocol => "https" } do
resource :login, controller: "sessions" do
collection do
get 'new'
get 'create'
end
end
end
and you could put more resource entries under there as needed
Why don't you leave the route as is and add in your production.rb file:
config.force_ssl = true
This way you will have all the traffic routed via SSL, not only the login controller, which is a good practise to protect your user session cookies.

What's the best way to get the full url to a resource in a Rails model?

I'm using as_json in a Rails model to customise the returned json accessed from the controller, like so:
def as_json(options={})
{
:id => self.uuid,
:href => full_url_to_resource,
:file => self.file.url,
:filename => self.filename,
:file_size => self.file_size,
:date => self.created_at
}
end
I want to provide the full url of the resource to the client as the href attribute. I'm wondering if there is a non-hardcoded way to do this.
I've include the Url Helpers in my model
include Rails.application.routes.url_helpers
Which allows me to do this:
:href => url_for_file(:host => "example.com") + '/files/' + self.uuid,
That works fine, but I obviously don't want to hardcode the url. Is there a built in way to do this in Rails based on the current URL being accessed or the url defined in default_url_options?
Or should I create a helper to do this instead?

Rails url_for Gravatar routing error

This function is defined in the application_help.rb:
def gravatar_url_for(email, options = {})
url_for(
{
:protocol => 'http://',
:host => 'www.gravatar.com',
:controller => 'avatar',
# :controller => 'avatar.php',
:gravatar_id => Digest::MD5.hexdigest(email),
:only_path => false
}.merge(options)
)
end
It's used in views:
<%= image_tag(gravatar_url_for user.email, {:d => 'identicon', :s => 32, :r => 'g'}) %>
Occasionally, its usage will result in a routing error:
No route matches {:controller=>"avatar", :d=>"identicon", :r=>"g", :gravatar_id=>"486575e581db04b7c8ca218af8488657", :s=>32}
A valid email is being supplied when the error occurs.
If I replace the url_for() with this logic, it works as expected:
url_for("http://www.gravatar.com/avatar/" + Digest::MD5.hexdigest(email) + "?d=identicon&s=40&r=g")
** edit **
I had removed the following line from the routes.rb file:
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
match ':controller(/:action(/:id(.:format)))'
Is there a way to get the url_for to work without the 'legacy wild controller route'?
You might want to take a look at the Gravtastic plugin for Rails which supports Gravatar images in both Ruby and JavaScript.

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}/ }

Defining :id in routes to be something other than id in rails 3

I am porting a Merb app to Rails 3. In Merb we could put an Identify block around a route to define how an :id route parameter was to be supplied, e.g.,
# this is a Merb route that I want to port to Rails 3 routing; I get everything except
# how to replicate the behavior of Merb's Identify block which doesn't require one to
# futz with overriding to_param on user; a user instance gets passed to the url builder
# ala url(:edit_password_reset, user) and this tells the router to use the
# reset_password_token method on user to supply the :id value for this one route
Identify User => :reset_password_token do
match("/reset-password/:id", :method => :get).to(:controller => "password_resets", :action => "edit").name(:edit_password_reset)
end
# and then later define more routes that use the user's id without a problem
# since to_param was not overridden on user; here I have already translated to
# Rails 3 and this works fine
controller :users do
get "/register", :action => "new", :as => "new_user"
get "/users", :action => "index", :as => "users"
get "/users/:id", :action => "show", :as => "show_user"
get "/users/:id/edit", :action => "edit", :as => "edit_user"
put "/users/:id", :action => "update", :as => "update_user"
post "/users", :action => "create", :as => "create_user"
end
In Rails, as in Merb, you can override to_param to provide an alternative id value for routes, but for a case where one time you want to use an id and another time you want to use a different method on the same object (as above), Identify is convenient. What is the Rails 3 equivalent? I looked through the Rails 3 source and tests and didn't see anything equivalent to Identify. Did I miss it?
I can refactor things and maybe should to not need it in this case, but still I would like to know if I missed something.
Thanks.
I came across the same problem; turns out the best way is to skip to_param entirely when calling a url or path. For instance:
# This will set params[:id] to #user.to_param
edit_password_reset_url(#user)
# This will set params[:id] to #user.reset_password_token
edit_password_reset_url(#user.reset_password_token)
In other words, to_param is only called when passing a record to the url helpers; if you pass it a string instead, it will just parse the string.