How to be RESTful in Ruby on Rails? - ruby-on-rails

I have a decent amount of experience with rails, but I've always been a bit ad hoc with my development methods. I'm curious about how to be properly RESTful in rails. Here's an example of an app I'm working on now:
I have a few models, including a User, Pack, and Product model. The models each have a controller associated with them. If I want to create a new page called 'Dashboard', on which the User can create new records on the Pack model, as well as see their account information, how do I do this in a restful way? Do I create a new controller called Dashboard? Or do I add it to a controller that defines my 'Static Pages'? What's the best practice regarding pages that aren't exclusive to the actions on one model?
Thank you in advance!

Yes, basically you want one controller per resource. In this case the resource is a combination of things but since you've identified a singular meta-resource (a "dashboard") it makes sense. So, I'd create a DashboardsController and then have a route like:
resource :dashboard, only: :show
Then you can use dashboard_url for links to the dashboard.
NOTES: The singular resource in the routes file is important because it indicates you don't have a list of resources, just a single one. This means there won't be an index action and the show action will be the default -- thus dashboard_url doesn't require a resource to show to be passed to it. And, regardless, controllers are named in the plural -- thus DashboardsController.

I would create a DashboardsController despite not having Dashboard model. Then to maintain REST principles have a controller method :new and controller method :create. Simply disply the information on the dashboards/new.html.erb but have the form post to the :create controller action.

To supplement the answers already given, REST really exists to make an easily-consumable API. (Notably, Roy Fielding's work is in the area of APIs, and REST is built on top of HTTP methods that HTML doesn't allow.)
This has been a common stumbling block since RESTful routing debuted in Rails; people get the impression that every controller now needs to be RESTful and that the front end and API should never diverge. Frequently, though, the front end and API have different needs.
For resources you want to be accessible via an API—Products, Users, Packs—trying to be RESTful is ideal. For those sorts of uses, pdobb's advice to have one controller per resource is generally exactly what you're looking for. They make sense in the context of an API being consumed by a machine.
But what about the dashboard? Dashboards are generally an HTML view intended to be rendered in a browser and viewed by a human being.
Does a "dashboard" resource make sense in the context of an API? Would it make more sense to instead make that data available in other resources? Is that data available in other resources?
Even if a "meta-resource" aggregating data still makes sense, would it be more logical if the API version had another name, like AccountSummary?

Related

How to best share routes between Rails app and Rails API

I am writing my first "real" Rails app after making a few successful learning projects and I'm still a little bit iffy on best practises for App vs API routes. Ideally, API routes will be RESTful, mainly revolving around using resources :articles or whatever, but I'm wondering which of the the following two scenarios is best
Create the app itself using RESTful routes, then bolt on an API in the "api" namespace/subdomain for example, and after authentication, piggy back off the same routes (not sure exactly how to do the piggy backing yet with different authentication, but that will come later. Or;
Create the app itself with whatever routes are semantic and work well (still ideally CRUD based), then create an entirely new set of controllers and routes for the API (RESTful)
I appreciate any feedback that anyone has.
The default "Rails way" is to make your models available to different clients through a single set of URIs, handled by a single set of controllers — /articles for browsers, /articles.json or /articles.xml for programmatic access. You can see that in Rails' emphasis on "resources", the respond_to mechanism in your controllers and so on.
This often works very well for simpler APIs that match the CRUD semantics closely. If yours for whatever reason does not, you might be better off with separating it out.
Try starting out the simple way by sticking to this 'one controller for both' approach. If you like, you could use
scope '(api)' do
resources :articles
resources :authors
resources :comments
# ...
end
to add an optional '/api/' path segment to your URLs - in this case, giving you both /api/articles and /articles, routed to the same controller. This gives you an easy way out, should you later decide to switch to separate controllers for HTML and API access.

Rails: What is an API's endpoint?

I am doing the CodeSchool course on Rails API's and they often mention the word 'endpoint' but never define it. Can someone give a clear and concise definition of it and provide an example of a request reaching an end point in the context of Rails?
An endpoint, as I imagine they may be using it in this course, is simply a route defined by your rails application. In terms of an API (which can mean many things and is worth further research on your part), hitting that endpoint will serve up a resource from your application, or perform some form of action. An example may explain this better..
Say we have an application that handles users and we want our API to expose the users resource. If we follow RESTful convention for our API we will expose seven distinct 'endpoints' linked to seven distinct 'actions' (index, show, create, update, destroy, new, edit) surrounding users.
When building our API, we would make is so anyone who visits "www.myapp.com/users" via a get request is returned some data representation of all users in our application. "/users" is the endpoint. Likewise performing a post action to "/users" with valid data is how we create new users. "/users" is still the endpoint but under different context. If you wanted data for just a single user, it may look something like "www.myapp.com/users/1" in which case "/users/1" is the endpoint.
It is important to keep in mind that this example merely follows convention and is not an end all be all.
I would check out the Rails guide on routing if you want more information - http://guides.rubyonrails.org/routing.html
Resource https://edgeguides.rubyonrails.org/api_app.html they meant providing a programmatically accessible API alongside their web application

Is it OK to create meaningless singleton resources just to stay RESTful? Rails

In the process of making an ebook, users have to edit its content, edit its metadata, choose marketing options, (such as pricing and distribution) and publish.
I started to put each everything inside the Book resource (contents, metadata, marketing options etc)
Then each step of the process (contents, metadata, marketing) is an action inside BooksController.
But Books started to grow a lot in terms of attributes and actions.
I'm wondering if it is better to force RESTfulness by creating singleton resources, each associated to their respective book.
The routes would be:
/book/12/content/edit
/book/12/metadata/edit
/book/12/marketing/edit
This seems more elegant, as each of these "resources" are RESTful and have few attributes each. But the resources are not objects (Marketings?).
Do you thing it's OK to create meaningless resources just to be RESTful and keep code in order?
Is there a better way to group similar attributes than create resources out of them? Thanks.
I'm porting a large PHP application to Rails and we have a fair few "ad-hoc"resources, such as admins have the ability to log in as another user with their permission, in order to correct issues etc. I would always complain that features such as logging in as other users should not be bundled into a huge monolithic AdminController as actions loginAsUser and logOutOfUserAccount. In our Rails app we try to visualize as much as we can in terms of resources, so using the example I just gave, we have an Admin namespace, under which there is a UsersController (/admin/users/:id) and as a sub-resource of users, we have a UserOverride resource (/admin/users/:user_id/override)... it feels really logical that we just POST and DELETE to this resource.
So getting back to your example, yes, I think you should break those sections down into separate resources. It certainly seems like BookContent should be a sub-resource of Book, and MarketingOptions too.
resources :books do
resource :content
resources :marketing_options
end
etc
This is both nicer to work with (more modular) and easier to visualize just from looking at the routes alone. You also get the benefit of really predictable path helpers:
<%= link_to("Marketing Options", book_marketing_options_path(#book)) %>
You can't try to force every conceivable route into a RESTful resource ideology though... if it feels like it's forced, then it probably is.
There's a decent blog post I wanted to link to that (despite some poor grammar) actually does a pretty good job of showing you how to think about your application in terms of resources... I can't find it though. I'll add a comment if/when I do.
EDIT | Just re-reading your original question and wanted to clarify: resource != row in database. A resource is anything you can conceive as a "thing"... I know that's a very broad statement, but just like an Object in OOP doesn't have to represent something concrete/material, nor does a resource in a RESTful design.

Rails 3 RESTful design preferred?

I'm pretty new to Rails 3 and I'm trying to understand the advantage of designing an application in a RESTful way. I don't need an API/Web Service. Don't need XML or JSON.
The application I'm building uses no CRUD at all. It is an app that gathers trade data via a socket connection and displays it to a user in many different ways.
I would like to visualize trades in different ways such as:
Most recent
Highest Yielding
Trades by State
Most active trades
Million dollar trades
Trades that are general obligation bonds
etc…
In the "Rails way" it seems that I would have a very overloaded index action. Or I could go against convention and just create methods in the trades controller like most_recent, highest_yielding, most_active, etc. But that seems to go against the whole philosophy of designing an app in Rails 3.
It just seems like the idea behind a RESTful approach in Rails is based around CRUD and falls short when CRUD isn't involved. Is there really an advantage to designing your app to be "RESTful" besides following a convention? I'm not really seeing the advantage here.
Plus, if I ever do need an API, I would imagine that it would be much better to design an API with an API in mind. My API wouldn't be a direct 1 to 1 match of my website which is built for human consumption vs a machine.
I'd appreciate any insight on this. Maybe I'm missing something here?
CRUD is actually involved when resources are involved. And since virtually every application has resources CRUD can be involved and is usually(if you ask me), the best way to do it.
The idea is that a resource has certain actions. You view a resource, you edit it, you delete it and some more. The methods like most_recent(or scope for this one) should be used in models and not controllers. Then, if you need to use that collection, you would just call something like :
#recent_posts = Post.most_recent
in your controller. Your controllers should not have much code, actually no business logic at all.
RESTful is very nice because it handles resources naturally. A controller should actually be handling a resource. If you think that something can be edited or created, then it should be handled by a controller.
Generally, i highly suggest that you take a deeper look and you will definitely see the advantages on your own.
I have idea how to do it. Code is not tested, I just wrote it without running.
Controller:
# trades_controller.rb
def index
# all scopes defined in model will be allowed here
# not good idea if you don't want it
if Trade.scopes.has_key?(params[:scope].to_sym)
#trades = Trade.send(:params[:scope])
else
# render error or what you want
end
end
Model
# trade.rb
scope :most_recent, order(:created_at)
# more scopes
View
# index.html.erb
link_to 'Most recent', trades_path(:scope => 'most_recent')
Your design should always take into account the requirements of your application first and the philosophy of the framework second.
If the philosophy doesn't fit your requirements or what you believe is the best way to develop your application then either ignore it, or, if the framework makes it too difficult for you to build like you think you should (which isn't the case in Rails imho), switch to another framework.
All of that doesn't have much to do with REST. For more info on why REST is considered a good idea (for some, not all, things), see the following SO Q&A's: Why would one use REST instead of Web services and What exactly is RESTful programming.

Should RoR urls look like /users/register or /user/register?

Should urls have pluralized words in them or singular?
I personally like:
/user/register
Is this against the 'convention'?
I think it depends on the way you think what it is.
From the perspective of syntax, it seems to me /user/register make more sense. While from the perspective of resources, the /users/register make sense.
Is there more than one User in your application?
If so, the standard /users/register would be the conventional REST url scheme for registering a new user - assuming this results in a user being created.
You might consider the more convention /users/new unless "register" really is a different action than creating a new user somehow.
Yes, that's against the RESTful convention of /users/new. However, I don't see much of an issue with using more user-friendly URLs, especially if you preserve the original REST URLs too. In all my applications, the first thing I do is setup routes to /signup, /login and /logout.
Plural form controllers are the convention, because it makes the most sense, it implies /users/ will be an index of users etc.
However, the only time I would consider using a singular form controller name here is if, for example: your application is a little more closed, and users cannot view/modify each other (no index), and you were using this controller only to allow users to register and view/update their own details. In that case the singular form can be a sensible option, but it's still a matter of preference.

Resources