Ruby On Rails REST: Customize URL pattern for POST request - ruby-on-rails

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)

Related

What is the idiomatic means of organizing this code the "rails way"

Within our Rails app, I have several webhooks, called by external services (namely PayPal IPN, Mailgun and Pusher). Currently, each type has it's own controller + necessary routes, for example:
post 'jobs/:job_id/comments/reply' => 'mailgun#incoming_email_comment'
post '/webhook' => 'pusher#webhook'
post '/paypal/ipn', :to => 'paypal#ipn', :as => :paypal_ipn
Is there a cleaner, more "rails way" to achieve this?
For example post '/webhook' => 'pusher#webhook'
pushers_controller.rb
class Pushers <ApplicationController
def webhook
....
end
end
routes.rb
resources :pushers do
collection do
post 'webhook'
end
end
now you can get url for that route like this
webhook_pushers_path
or
link_to 'some text', webhook_pushers_path
As you can see, now you don't need write url by hands. Rails automatically creates it using name of your controller and your action.
You can read more there http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

How to redirect a URL with GET variables in routes.rb without Rails stripping out the variable first?

I am building a website in Rails to replace an existing website. In routes.rb I am trying to redirect some of the old URLs to their new equivalents (some of the URL slugs are changing so a dynamic solution is not possible.)
My routes.rb looks like this:
match "/index.php?page=contact-us" => redirect("/contact-us")
match "/index.php?page=about-us" => redirect("/about-us")
match "/index.php?page=committees" => redirect("/teams")
When I visit /index.php?page=contact-us I am not redirected to /contact-us. I have determined this is because Rails is removing the get variables and only trying to match /index.php. For example, If I pass /index.php?page=contact-us into the below routes I will be redirected to /foobar:
match "/index.php?page=contact-us" => redirect("/contact-us")
match "/index.php?page=about-us" => redirect("/about-us")
match "/index.php?page=committees" => redirect("/teams")
match "/index.php" => redirect("/foobar")
How can I keep the GET variables in the string and redirect the old URLs the way I'd like? Does Rails have an intended mechanism for this?
I had a similar situation, this is what I did:
Create a controller taking care of redirects with one action
RedirectController < ApplicationController
def redirect_url
if params[:page]
redirect_to "/#{params[:page]}", :status => 301
else
raise 404 #how handle your 404
end
end
In routes.rb
match "/index.php" => "redirect#redirect_url"

Rails 3.1 Routes with fixed structured params

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

url_for generates a url with current path inserted

I am generating a url in my controller accessed from the relative path "/hangouts/test", for a url on an external site (facebook). I want to use url_for and pass in params using hashes so it can escape them. The URL I want is this:
http://www.facebook.com/connect/prompt_permissions.php?api_key=6aca22e72866c7eaaedfb15be69c4b93&...
Using this, however:
url_for(:host => "www.facebook.com/connect/prompt_permissions.php?", :api_key => Facebooker.api_key, :next => test_hangouts_url, :cancel => root_url, :ext_perm => "publish_stream")
I instead get my current path of /hangouts/test thrown in there:
http://www.facebook.com/connect/prompt_permissions.php/hangouts/test?api_key=6aca22e72866c7eaaedfb15be69c4b93&...
As you can see, I don't want "/hangouts/test" to be in there - played a bit with the options in the API docs but stumped, anybody know how to use url_for without it inserting the current path? Thanks!
You shouldn't be using the hash form of url_for to generate links outside of your application.
Instead you should just be using the string version form:
url_for "http://www.facebook.com/connect/prompt_permissions.php?api_key=6aca22e72866c7eaaedfb15be69c4b93&next=#{test_hangouts_url}&cancel=#{root_url}&ext_perm=publish_stream"
url_for will use the current action controller/action/id unless the hash given to url_for contains one of those arguments. url_for will then generate a url from a route that matches the arguments given in the hash. The arguments to url_for used in the question generates a valid url, because it can match a route using the current controller/action. You will not be able to generate the url you want with the hash form of url for without matching a route. Providing a controller in the hash you give url_for should match the default routes that rails generates for you when you create an application, but that's not very DRY.
The better solution is to use a named route:
map.prompt_fb_permissions "/connect/prompt_permissions.php",
:host => "www.facebook.com", :controller => nil, :action => nil
then you can use the following in place of url_for whenever you want to generate this this url.
prompt_fb_permissions(:api_key => Facebooker.api_key, :next => test_hangouts_url,
:cancel => root_url, :ext_perm => "publish_stream")
You left out the controller parameter, which is why it's automatically adding your controller path ("/hangouts/test"), to your base host.
Try this:
url_for(:host => "www.facebook.com", :controller=> "/connect/prompt_permissions.php", :api_key => Facebooker.api_key, :next => test_hangouts_url, :cancel => root_url, :ext_perm => "publish_stream")

Identify GET and POST parameters in Ruby on Rails

What is the simplest way to identify and separate GET and POST parameters from a controller in Ruby on Rails, which will be equivalent to $_GET and $_POST variables in PHP?
You can use the request.get? and request.post? methods to distinguish between HTTP Gets and Posts.
See http://api.rubyonrails.org/classes/ActionDispatch/Request.html
I don't know of any convenience methods in Rails for this, but you can access the querystring directly to parse out parameters that are set there. Something like the following:
request.query_string.split(/&/).inject({}) do |hash, setting|
key, val = setting.split(/=/)
hash[key.to_sym] = val
hash
end
You can do it using:
request.POST
and
request.GET
There are three very-lightly-documented hash accessors on the request object for this:
request.query_parameters - sent as part of the query string, i.e. after a ?
request.path_parameters - decoded from the URL via routing, i.e. controller, action, id
request.request_parameters - All params, including above as well as any sent as part of the POST body
You can use Hash#reject to get to the POST-only params as needed.
Source: http://guides.rubyonrails.org/v2.3.8/action_controller_overview.html section 9.1.1
I looked in an old Rails 1.2.6 app and these accessors existed back then as well.
There is a difference between GET and POST params. A POST HTTP request can still have GET params.
GET parameters are URL query parameters.
POST parameters are parameters in the body of the HTTP request.
you can access these separately from the request.GET and request.POST hashes.
request.get? will return boolean true if it is GET method,
request.post? will return boolean true if it is POST method,
If you want to check the type of request in order to prevent doing anything when the wrong method is used, be aware that you can also specify it in your routes.rb file:
map.connect '/posts/:post_id', :controller => 'posts', :action => 'update', :conditions => {:method => :post}
or
map.resources :posts, :conditions => {:method => :post}
Your PostsController's update method will now only be called when you effectively had a post. Check out the doc for resources.
I think what you want to do isn't very "Rails", if you know what I mean. Your GET requests should be idempotent - you should be able to issue the same GET request many times and get the same result each time.
You don't need to know that level of detail in the controller. Your routes and forms will cause appropriate items to be added to the params hash. Then in the controller you just access say params[:foo] to get the foo parameter and do whatever you need to with it.
The mapping between GET and POST (and PUT and DELETE) and controller actions is set up in config/routes.rb in most modern Rails code.
I think what Jesse Reiss is talking about is a situation where in your routes.rb file you have
post 'ctrllr/:a/:b' => 'ctrllr#an_action'
and you POST to "/ctrllr/foo/bar?a=not_foo" POST values {'a' => 'still_not_foo'}, you will have three different values of 'a': 'foo', 'not_foo', and 'still_not_foo'
'params' in the controller will have 'a' set to 'foo'. To find 'a' set to 'not_foo' and 'still_not_foo', you need to examine request.GET and request.POST
I wrote a gem which distinguishes between these different key=>value pairs at https://github.com/pdxrod/routesfordummies.
if request.query_parameters().to_a.empty?

Resources