Rails 3.1 Routes with fixed structured params - ruby-on-rails

I have an sms gateway which pushes me get-requests if a user replys an received sms.
# gateway pushes following fixed style get-params
# to my server/reply_from_gateway-action: ?id=123456&answer=Test
# => http://myserver.aaa/reply_from_gateway?id=123456&answer=Test
And now I want to add following route, since the sms gateway has a defined get parameter structure:
get "deactivate_via_sms?id=:id&answer=:answer" => "reminders#deactivate_via_sms"
:as => "deactivate_via_sms"
But that doesn't work, can you help me?

You can pull CGI-style parameters out of params by hand in your controller, you don't need (or want) them in the route:
get "deactivate_via_sms" => "reminders#deactivate_via_sms", :as => "deactivate_via_sms"
and then in RemindersController#deactivate_via_sms:
def deactivate_via_sms
id = params[:id]
answer = params[:answer]
#...
end

You can pull CGI-style parameters out of params by hand in your controller, you don't need (or want) them in the route
but in this case you can't use helpers such as
deactivate_via_sms_path(id,answer)
or you can use this code for creating helper
get "deactivate_via_sms?id=:id&answer=:answer" => "reminders#deactivate_via_sms"
:as => "deactivate_via_sms"
but your routing will fail
I resolved this issue by changing "?" to "/" in route
get "deactivate_via_sms/id=:id&answer=:answer" => "reminders#deactivate_via_sms"
:as => "deactivate_via_sms"
routing works and helper method also works fine

Related

Cant rename rails routes

I want to rename a few of my routes, for example:
get 'legal/terms_of_service', :to => 'legal#terms_of_service', :as => :datenschutz
that works, but it doesn't change the acutal URI- and I want that to be changed as well. path: does not work here.
Thank you
If you want the URI to be /datenshutz then you can do this:
get '/datenschutz', :to => 'legal#terms_of_service', :as => :datenschutz
The get '/datenschutz' determines the url browsers or other http clients use to access the controller.
The :to => 'legal#terms_of_service' specifies a controller class and controller action used to respond to the route.
The :as => :datenschutz changes the method you use in views to create links to the route (such as datenschutz_path).

Managing URL Parameters in Rails

Right now I am finding routing and URL constructing within rails to be semi-confusing. I have currently matched the following for tags that are passed in when displaying/filtering data.
match '/posts/standard/' => 'posts#standard'
match '/posts/standard/:tags' => 'posts#standard', :as => :post_tag
match '/posts/standard/:tags' => redirect { |params| "/posts/standard/#{params[:tags].gsub(' ', '+')}" }, :tags => /.+/
However, now I want to add a 'skill' parameter that can only take one state; however, I am very confused by how I want to construct this within my URL. I cannot simply have...
match '/posts/standard/:tags/:skill' => 'posts#standard', as => post_tag, as: => post_skill
So, I am very confused by this at this point, does Rails offer any type of help for constructing URL's?
One way is to just keep your main route
match '/posts/standard/:tags' => 'posts#standard', :as => :post_tag
and handle the additional URL params as params. The url would look like:
/posts/standard/1?skill=something
and it is easy enough to inject the additional params, such as by
link_to post_tag_path(:skill=> 'something')
and your controller would then do
def standard
if params[:skill] == 'something'
...
else
...
end
end
Also, not sure about this, but your first line in your routes 'match '/posts/standard/' => 'posts#standard' may catch all of your routes since there is a match. If this is the case, simply move it to after the first line.

Rails implement an API using Routes pointing to existing controller actions

I have a Rails app that does everything I need it to do via a HTML interface, now I'd like to bolt on an API providing access to bits of the functionality.
How would I do this selective forwarding of some API controller actions to another controller's actions using the Routes.rb?
I have tried the following:
My regular controller routes work fine using:
match 'stuff' => 'stuff#index'
get 'stuff/index'
get 'stuff/some_get_action'
post 'stuff/some_post_action'
But then when I try for my API:
match 'api' => 'api#index'
match 'api/some_get_action' => 'stuff#some_get_action', :via => :get
match 'api/some_post_action' => 'stuff#some_post_action', :via => :post
or...
match 'api' => 'api#index'
get 'api/some_get_action', :to => 'stuff#some_get_action'
post 'api/some_post_action', :to => 'stuff#some_post_action'
I get an error. When I navigate to /api/index to server a HTML page that contains forms for testing the API URLs the url_for raises a 'Routing error' exception saying 'No route matches...'.
You may want to include ':as => ' and define your route names that you may be using as your link paths.
get 'api/some_get_action' => 'stuff#some_get_action', :as => 'some_get_action'
and the link path in your index file will have 'some_get_action_path'. Not sure that 'match' or 'get' automatically resolves to a path name, which by setting ':as' it definitely will.
I like your idea for setting up this page for testing. I'm always doing it in the console, which is surely more difficult than simply clicking a link. Your links probably need to infer that they are :json requests, not :http.

Ruby On Rails REST: Customize URL pattern for POST request

I am new to Ruby On Rails and need some help implementing REST protocol.
Whenever you do a POST on REST you get a URL back e.g. http://my-site.com/id/1
I need a customized response in URL format which I have given in example above.
Lets say I am doing a post on parameter <main-id>123</main-id>
The customized response I am looking for is http://my-site.com/123/id/1
What I want to implement is, whatever parameter ID I passed during a post I want that as a part of the response URL output.
Thanks for any help in advance.
You can specify any URL in your controller, e.g.:
def create
... # create record here
redirect_to "/#{params[:main_id]}/id/#{#record.id}"
end
Of course, you'll probably want to use the url helper based on your defined route:
def create
... # create record here
redirect_to my_oddball_path(#record, :main_id => 123)
end
Provided you are using Rails 3, you could just add this route with the proper controller/action
match ':main_id/id/:id', :controller => 'foo', :action => "bar", :via => :post, :as => main_id
Then you can just with the helper main_id_path(main_id, #record)

rails3 routes issue

I have following routes.
pota.resources :on_k,
:as => ':klass',
:path_prefix => 'pota/klass',
:controller => 'main'
When I do rake routes this is what I get for show method:
pota_on_k GET /pota/klass/:klass/:id(.:format)
{:action=>"show", :controller=>"pota/main"}
Above code works fine in rails 2.x . However if I am using rails3 then I get following error
ActionController::RoutingError: No route matches
{:action=>"show", :controller=>"pota/main", :klass=>"vehicle/door", :id=>1}
Notice that I am passing 'vehicle/door' as :klass. If I pass a standard model like :klass => 'pet' then it works fine. However if I pass a nested model name like :klass => 'vehicle/door' then I get route error in rails3.
I guess that is because I have '/' in the value . I can solve that by having a regex but I might also pass :klass which is not nested.
On a class like Vehicle::Car I do
Vehicle::Car.underscore #=> vehicle/car
"vehicle/car".camelize.constantize #=> Vehicle::Car
This underscore and camelize/constantize on the other side makes it easier to pass nested class name.
Any idea on how to go about fixing it for rails3?
STOP!
Think about what you're doing here - you should not be calling constantize on url parameters. Assuming that you're likely to be calling find on the result you're basically giving a hacker a way to query every ActiveRecord model in your application.
A better way is to use meta programming to dynamically build static routes that can't be hacked, e.g:
%w[pet vehicle/car vehicle/bike].each do |klass|
resources :pota,
:path => "pota/#{klass.pluralize}",
:as => "pota_#{klass.tr('/','_').pluralize}",
:defaults => { :klass => klass }
end
Then you can add a helper method that calls the appropriate named route helper to generate urls based upon a passed model instance.

Resources