RESTFUL URLS in rails? - rest

Hi I'm building REST api for an app, I have a requirement in URL
such that url should be something like this e.g
www.abc.com/api/param1/value1/param2/value2/param3/value3.... and so on
There are cases
case: The number of params are not limited it can change frequent
if today it is something like this
www.abc.com/api/param1/value1/param2/value2/param3/value3
tomorrow it can be like this
www.abc.com/api/param1/value1/param2/value2/param3/value3/param4/value4
Is there a configuration where once you configure the url pattern
and every thing go smooth
and in conrtoller params should contain this kind of key-value pair
{ "param1" => "value1","param2" => "value2","param3" => "value3"...and so on }
any suggestion !! how to achieve this ??

If your params are not fixed you can use wildcard in routing
for e.g
get 'items/list/*specs', controller: 'items', action: 'list'
def list
specs = params[:specs] # e.g, "base/books/fiction/dickens" #split it and place in a hash
end

Rails routing provides a way to specify fully custom routes with static and dynamic segments as explained in the Rails Routing Guide.
Your requirement should be achievable with
get '/api/param1/:param1/param2/:param2/...', to: 'controller#action'

You can use route scoping for this particular kind of problem . In other way it is nested routes
More details : http://guides.rubyonrails.org/routing.html#nested-resources
This is a example,
GET /magazines/:magazine_id/ads/:id/edit ads#edit
return an HTML form for editing an ad belonging to a specific magazine
I think this would be helpful for you.

Related

Symfony2 Form Rest Api only add to Relation

I am using Symfony2 as Rest Api for a JS Frontend App. I came across a scenario where I want users to "invite" (=add) Users to a Group. But I want to only allow them to add Users to the existing Relation and not "overwrite" the whole relation, which is the standard behaviour in combination with a regular Symfony2 Form.
What would be the best practice to achieve this behaviour?
Additional Comment:
I am using Ember-Data in the frontend and my frontend would probably send a put request with the whole Group including additional users (but not all).
My JSON Payload would look something like this:
{
"usergroup": {
"name":"yxcv2",
"stake":"sdfghj",
"imageName":null,
"userCount":5,
"users":[
5,
6,
7
],
"gameGroup":"13",
}
}
In this scenario User 1,2,3 and 4 are already members of the group. And instead of replacing 1,2,3,4 with 5,6,7, I want to ADD 5,6,7 to the already existing members.
A LINK request should be used to add an item to an existing collection instead of overwriting it with a POST request.
Using a symfony form you'd post the User (id) plus a hidden field _method with value LINK to something like /groups/{id}.
routing would be something like this:
group_invite:
path: /groups/{id}
defaults: { _controller: YourBundle:Group:inviteUser }
methods: [LINK]
You could use FOSRestBundle's implicit resource name definition, too.
For the method override to work the config setting framework.http_method_override needs to be set to true ( = default value - available since symfony version 2.3).
More information can be found in the documentation chapter:
How to use HTTP Methods beyond GET and POST in Routes

Mojo Routes: Handle asorted tags in url

I am building a Mojo app to replace a vanilla mod_perl application.
The app currently handles url structures like:
/
/type/bold/
/keyword/hello/
/audience/all/
/type/bold/keyword/hello/
/keyword/hello/audience/all/
/keyword/hello/type/bold/audience/all/
/audience/all/type/bold/keyword/hello/
key/value pairs in the URL, that can exist in any order.
I am looking for a way to handle that without simply making a route for every permutation of tag, as that gets repetitive even after 3 different types of tags
In that case you should probably just make a route that matches everything and parse the url yourself.

Use route prefix with RESTful routes in CakePHP

Working on building an API and would like to use RESTful routes.
I got it to work just fine like this:
http://www.mysite.com/events.json // returns json results with my events
http://www.mysite.com/events/123.json // returns json results with event of id '123'
BUT - I want to be able to do this using an 'api' prefix.
So, I added the api Routing prefix:
Configure::write('Routing.prefixes', array('admin', 'api'));
And changed my actions from 'view' and 'index' to 'api_view' and 'api_index'.
But now it doesn't work. (eg. I have to write the action name or it won't find the correct one based on HTTP.
The end goal would be to be able to do something like this:
GET http://www.mysite.com/api/1.0/events.json // loads events/api_index()
GET http://www.mysite.com/api/1.0/events/123.json // loads events/api_view($id)
DELETE http://www.mysite.com/api/1.0/events/123.json // loads events/api_delete($id)
...etc
I ended up having to just write the routes manually:
Router::parseExtensions('json', 'xml');
Router::connect('/api/:version/:controller/:id/*',
array('[method]'=>'GET', 'prefix'=>'api', 'action'=>'view'),
array('version'=>'[0-9]+\.[0-9]+', 'id'=>'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'));
Router::connect('/api/:version/:controller/*',
array('[method]'=>'GET', 'prefix'=>'api', 'action'=>'index'),
array('version'=>'[0-9]+\.[0-9]+'));
Router::connect('/api/*', array('controller'=>'events', 'action'=>'index', 'ext'=>'html'));
Notes:
The [method] is what forces the HTTP type (eg. RESTful)
The parseExtensions() makes it so you can have it display the data in different formats automatically by changing the extension in your URL.
The last Router:: line was just a catchall for anything /api/ that didn't match - it forwarded it to the homepage. Eventually I'll probably just route this to an API error page.
The 'ext'=>'html' of the last Router:: line was to keep parseExtensions from trying to use whatever extension was in the URL - if it's redirecting for reasons they made the call wrong, I just want it to go back to the homepage (or whatever) and use the normal view.
Try something like this.
Router::connect('/:api/:apiVersion/:controller/:action/*',
array(),
array(
'api' => 'api',
'apiVersion' => '1.0|1.1|'
)
);
With prefix routing
Router::connect('/:prefix/:apiVersion/:controller/:action/*',
array(),
array(
'prefix' => 'api',
'apiVersion' => '1.0|1.1|'
)
);
Will match only valid API versions like 1.0 and 1.1 here. If you want something else use a regex there.
I know this is an old post, but there is a routing method called mapResources which creates the special method based routing for you.
http://book.cakephp.org/2.0/en/development/rest.html
You put it in routes.php like so:
Router::mapResources(array('controller1', 'controller2'));
The docs have a nice little table showing how the requests are mapped to different actions, which you can always override if you need to.

Routing based on query parameter in Play framework

My web application will be triggered from an external system. It will call one request path of my app, but uses different query parameters for different kinds of requests.
One of the parameters is the "action" that defines what is to be done. The rest of the params depend on the "action".
So I can get request params like these:
action=sayHello&user=Joe
action=newUser&name=Joe&address=xxx
action=resetPassword
...
I would like to be able to encode it similarly in the routes file for play so it does the query param based routing and as much of the validation of other parameters as possible.
What I have instead is one routing for all of these possibilities with plenty of optional parameters. The action processing it starts with a big pattern match to do dispatch and parameter validation.
Googling and checking SO just popped up plenty of samples where the params are encoded in the request path somehow, so multiple paths are routed to the same action, but I would like the opposite: one path routed to different actions.
One of my colleagues said we could have one "dispatcher" action that would just redirect based on the "action" parameter. It would be a bit more structured then the current solution, but it would not eliminate the long list of optional parameters which should be selectively passed to the next action, so I hope one knows an even better solution :-)
BTW the external system that calls my app is developed by another company and I have no influence on this design, so it's not an option to change the way how my app is triggered.
The single dispatcher action is probably the way to go, and you don't need to specify all of your optional parameters in the route. If action is always there then that's the only one you really need.
GET /someRoute controller.dispatcher(action: String)
Then in your action method you can access request.queryString to get any of the other optional parameters.
Note: I am NOT experienced Scala developer, so maybe presented snippets can be optimized... What's important for you they are valid and working.
So...
You don't need to declare every optional param in the routes file. It is great shortcut for type param's validation and best choice would be convince 'other company' to use API prepared by you... Anyway if you haven't such possibility you can also handle their requests as required.
In general: the dispatcher approach seems to be right in this place, fortunately you don't need to declare all optional params in the routes and pass it between actions/methods as they can be fetched directly from request. In PHP it can be compared to $_GET['action'] and in Java version of Play 2 controller - DynamicForm class - form().bindFromRequest.get("action").
Let's say that you have a route:
GET /dispatcher controllers.Application.dispatcher
In that case your dispatcher action (and additional methods) can look like:
def dispatcher = Action { implicit request =>
request.queryString.get("action").flatMap(_.headOption).getOrElse("invalid") match {
case "sayHello" => sayHelloMethod
case "newUser" => newUserMethod
case _ => BadRequest("Action not allowed!")
}
}
// http://localhost:9000/dispatcher?action=sayHello&name=John
def sayHelloMethod(implicit request: RequestHeader) = {
val name = request.queryString.get("name").flatMap(_.headOption).getOrElse("")
Ok("Hello " + name )
}
// http://localhost:9000/dispatcher?action=newUser&name=John+Doe&address=john#doe.com
def newUserMethod(implicit request: RequestHeader) = {
val name = request.queryString.get("name").flatMap(_.headOption).getOrElse("")
val address = request.queryString.get("address").flatMap(_.headOption).getOrElse("")
Ok("We are creating new user " + name + " with address " + address)
}
Of course you will need to validate incoming types and values 'manually', especially when actions will be operating on the DataBase, anyway biggest part of your problem you have resolved now.

How can I check my post data in Zend?

I am a beginner and I am creating some forms to be posted into MySQL using Zend, and I am in the process of debugging but I don't really know how to debug anything using Zend. I want to submit the form and see if my custom forms are concatenating the data properly before it goes into MySQL, so I want to catch the post data to see a few things. How can I do this?
The Default route for zend framework application looks like the following
http://www.name.tld/$controller/$action/$param1/$value1/.../$paramX/$valueX
So all $_GET-Parameters simply get contenated onto the url in the above manner /param/value
Let's say you are within IndexController and indexAction() in here you call a form. Now there's possible two things happening:
You do not define a Form-Action, then you will send the form back to IndexController:indexAction()
You define a Form action via $form->setAction('/index/process') in that case you would end up at IndexController:processAction()
The way to access the Params is already defined above. Whereas $this->_getParam() equals $this->getRequest()->getParam() and $this->_getAllParams() equals $this->getRequest->getParams()
The right way yo check data of Zend Stuff is using Zend_Debug as #vascowhite has pointed out. If you want to see the final Query-String (in case you're manually building queries), then you can simply put in the insert variable into Zend_Debug::dump()
you can use $this->_getAllParams();.
For example: var_dump($this->_getAllParams()); die; will output all the parameters ZF received and halt the execution of the script. To be used in your receiving Action.
Also, $this->_getParam("param name"); will get a specific parameter from the request.
The easiest way to check variables in Zend Framework is to use Zend_Debug::dump($variable); so you can do this:-
Zend_Debug::dump($_POST);
Zend framework is built on the top of the PHP . so you can use var_dump($_POST) to check the post variables.
ZF has provided its own functions to get all the post variables.. Zend_Debug::dump($this->getRequest()->getPost())
or specifically for one variable.. you can use Zend_Debug::dump($this->getRequest()->getPost($key))
You can check post data by using zend
$request->isPost()
and for retrieving post data
$request->getPost()
For example
if ($request->isPost()) {
$postData = $request->getPost();
Zend_Debug::dump($postData );
}