Integrating Rails APIs with Forms - ruby-on-rails

I've read quite a few articles on good design for Rails APIs. However, I can't seem to find what I'm trying to do. And it's different enough that I'm not sure what to do.
So this Rails site has forms for generating various records for my various tables. It all works fine. No problem there. This is all admin-level stuff.
However, a few of these forms need to be also be available as an API. Right now my APIs work fine but it's poor design (I think). Currently the user will make an API request to do some action and pass some information in (i.e. add record to Foo).
My method inside the API, special_new_foo, more or less duplicates my create inside the foo controller that a form would route to. Is there a way I can reuse my standard create method? The API would then just check for good data, etc. and pass the information onto the controller...
I was thinking about just making an HTTP request to the local server on the machine (which is basically how the forms work, except they're two separate machines). Is this good practice?
Thanks!

One option is to allow you controller to respond with different formats, depending on the request. I think this is what rails generates on scaffolding. However i barely saw any real world app doing this. See also my answer to Is it necessary to build a separate API endpoint for mobile apps to access a Rails web app?
A better solution is to make an extra ServiceObject or FormObject dealing with business logic of your controllers and reuse this object in both endpoints
see http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

Related

In Rails, what is the best way to have a Model with conditionals based on whether or not a request has come via the API or the web front-end?

We are in the progress of building/migrating new features into our web application. We have a namespaced API (V1) that the mobile applications use to communicate with the app.
While we are in transition (we will launch the features for the web first), how can one differentiate between API requests and web requests, for purposes of bifurcating the logic in the shared model files? We need the models to stay the same for the mobile apps, but be different for the new big web-based features. Unfortunately code like
request.format
Isn't available in models.
Or is there a way to tell the API controllers to use different model files, and have separate models for some API vs. web app controllers?
I know that you should put as much code as possible within the model, however does this particular piece of code belong there?
It begs the question, because this seems to be 1) presentation oriented and 2) concern with the state/request.
It makes me believe that this code should actually reside within controllers.
API controllers to use different model files
Ofc, just use a different model...
You've provided little information about what you're trying to achieve, which makes things difficult.
However, this seems like some presentation oriented code based of a web state.
There for, add decorators to your application and do your conditional presentation there.

Does it make sense to separate Rails API and Rails app?

I have a project that involves both mobile and web clients. The mobile clients will mainly get content and post user updates, while the web client is mainly for creating content. As such, the web client and API share a lot of the same models and validation.
I am trying to decide the best approach in this case:
JSON-only Rails API + separate Rails web client that calls API.
Single Rails app with separation of API and client side (somehow).
The pro for me in terms of option N°1 is the separation of concerns, as I can work on the API while someone else do the web client. The con seems to be lots of duplicated code in terms of validation.
N°2 could make more sense in terms of reducing code duplication but it would get messy if more than one person is working on the same code base and setting up a process to resolve code conflicts is not something I want to do at this point since we're an early stage startup and want to get out something quickly.
Is there anything I'm missing?
The best practice is use ONE rails application for API and Web Interface
To separate those parts, just create a namespace for API like it's described there http://collectiveidea.com/blog/archives/2013/06/13/building-awesome-rails-apis-part-1/
Do it in one.
The con seems to be lots of duplicated code in terms of validation.
No, you would not have duplication the validation happens in the model, which is shared by your API <=> web controllers. Of course, you will have separate implementations for the actual authorization/session handling (if you have those), but these will not likely be duplicate but a bit different for your two access layers.

creating a web application with different server side languages

I been practicing developing an application in .NET and with other languages and server, and now I want to start sketching out an architecture I want to implement.
The reason why I want to separate the two is because I cannot focus on a specific thing when everything is Jumbled into one server. I would like to be able to have the freedom to offer features that would otherwise bottleneck one server and not another(ex. notification, chatting)
What brought me here to ask this question is because I am totally confused on why everything on the UI is always called MVC. When searching for solutions to a distributed architecture that I can implement I keep running across frameworks that use an MVC pattern.
How does this actually work when you already have your API models? Isn't an MVC pattern just going to duplicate all of the models on the API (ex django, asp.net mvc or ruby on the rails)?
One scenario that threw me off and brought me to research a whole lot more, is when I wanted to create a registration form that has steps, validating the username uniqueness was on one step and zip code was on another. I found myself wanting the tweak the API based on how I wanted to present my view and thought about having to do that for different types of clients(mobile, different user agents) and quickly backed off that idea. The problem is those fields need some sort of call to the back end and every view wont have that way of registering.
The main question is how do I implement a UI layer that I can customize toward certain views, without changing the way my API is structured?
You might be interested in this article from LinkedIn dev team.
https://engineering.linkedin.com/frontend/leaving-jsps-dust-moving-linkedin-dustjs-client-side-templates

Best approach for rails app/api

I'm developing a rails app, it's a regular site, but I need to develop an API, so I was reading and trying some stuff, the options that I've thought are (others are welcome):
Versioning the API and separate the API from the controller.
Pro: Clean and separate stuff. Cons: the need to handle 2 controllers for the same task.
Not versioning and keep everything in the same controllers, views can be done with jbuilder. Pro: not really easy way to version it. Cons: harder to expose only parts of the app. harder to route stuff like in an versioned way.
I really want to avoid duplication, but I need some way to avoid that, and make some nice routes like in a versioned way, I don't want to have more than 1 controller for some type of object, in a versioned way if you have 3 versions you'll end up with 4 controllers, that is a lot to maintain.
Please correct me if I'm wrong, and hope to get some good answers :)
Thanks.
Versioning your API is the best route to take.
If you have 4 versions, 1 controller, you still only need to maintain 2 controller (the one in the web facing application, and the most recent version of the API.)
If you have write access in your API, you would be able to take advantage of your own API in your application and not need to create a new method in both the API and in the main application (AJAX).
It is possible that your filters are different. You may need different types of authentication for the API and the main application.
The biggest argument for versioning would probably be that if you have anyone other than yourself consuming the API, their application would not break the day you deploy your changes.
Besides, you should keep to the 'thin controllers, fat models' mentality. That would prevent a lot of duplication with that alone.
I always code api within their own namespace because these points could be very different from the main app:
format rules
auth
rescue
versioning
before / after filters
Even if you have duplication in controllers, there should not be much code, and I cant see why it would be a big deal. Actually it could even force you to abstract your code and have thin controllers.

Understanding REST conceptually with Rails

I'm a little late to the party, but I'm trying to wrap my brain around how REST is supposed to work, both in general and in Ruby on Rails. I've read a bunch of articles online about this already, but still don't feel like I'm getting the big picture.
REST as I understand it, is a series of aspirational statements, with the net result at the bottom being that URLs should contain all the information necessary to handle a request, and gets should not be able to change the state on the server, and a bunch of other concrete guidelines.
As I understand it, REST in Rails is based around CRUD, which is to say, every model has a create, read, update and a delete action. Each of these actions is accessed through a similar set of URLs, generated by mapping a resource in the routes. So a login URL is creating a user session, so the URL would look like example.com/session/new with a POST, and logout would be example.com/session/destroy with a POST.
What exactly is the benefit of standardizing URLs in this fashion? It strikes me as optimizing for machine readability at the expense of human readability. I know that you could then remap in the routes file example.com/login to example.com/session/new but that is just one more step for no apparent gain to me.
Is it considered really bad practice to develop a website that uses traditional routes now?
Furthermore, each of these CRUD actions should be able to respond to requests with whatever type of response the request is looking for. So the same link to, say, example.com/tasks could also be called at example.com/tasks.xml to get an xml representation of the result, or example.com/tasks.json for a json representation.
Is this to say that a RESTful API would just be the usual links on the site but with xml appended? It strikes me as very strange and awkward that a web API would behave in this way, but this seems to be what's implied by everything I've read. I'm more used to seeing an API that has links like example.com/api/tasks to get the list of tasks. What exactly is the advantage of this approach?
Rest provides another chunk of "convention over configuration." For a widely used, limited set of common problems (crud actions against the models as a whole), rest is very useful as an application development convention.
What exactly is the benefit of
standardizing URLs in this fashion?
Programmer efficiency. Less to think about; enables more time to be spent on harder problems, etc. Better maintainability. Easier testing. Etc.
Is it considered really bad practice
to develop a website that uses
traditional routes now?
Yes, for crud actions that are interacting with an entire record of the model.
Furthermore, each of these CRUD
actions should be able to respond to
requests with whatever type of
response the request is looking for.
So the same link to, say,
example.com/tasks could also be called
at example.com/tasks.xml to get an xml
representation of the result, or
example.com/tasks.json for a json
representation.
Is this to say that a RESTful API
would just be the usual links on the
site but with xml appended?
Yes, if your api fits the rest model. I think the big issue is authentication. If you want your api to be stateless, then you'll probably need to include authentication with each call. At that point, if you don't want to use HTTP level authentication, you'd need to decide how to include the credentials.

Resources