BatedUrGonnaDie/salty_web — pull request #2 by glacials (2014-12-25 09:52:09+00:00)
Title: Refactor quotes api/routes

# I didn't mean to write this much I swear

This refactored most of the quotes endpoint and I just wanted to explain why I felt each of these changes was good. You can feel free to pick and choose which ones you'd like, if some of them don't sit well with you.

## Changes visible to consumers of this endpoint

### Route
Moves the route for quotes from `/api/quote?user=batedurgonnadie` to `/api/users/batedurgonnadie/quotes` (more on `quote` vs. `quotes` later). Making the hierarchy of the route reflect the relationship (a user owns a quote) makes it more clear what's going on when looking at the URI. It also is easy to see that a username is mandatory, where query parameters imply optionality.

### Response
The response for a successful hit to this endpoint changes from

```json
{
"status": 200,
"text": [
"quote1",
"quote2",
"quote3"
]
}
```

to
```json
{
"status": 200,
"quotes": [
{"text": "quote1"},
{"text": "quote2"},
{"text": "quote3"}
]
}
```

I know this seems convoluted at first, but this allows for expansion later if you want to start treating quotes as *objects* in responses, not just strings. e.g. if you want to add an `author` field or a `last_used` field, those fields would fit nicely into this response, where trying to put them into the array of strings would be messy without restructuring. This is one of a few standard ways of returning arrays of objects in APIs, and generally matches the typical response you'd expect a generic Rails application to give for an endpoint at this URI.

## Innards-only changes

### Move input handling into `before_action` callbacks
It's nice to keep your controller actions very small so that you can very clearly see at a glance what it's doing, and to push some of the legwork of assigning users from ids and checking for valid input into `before_action` callback methods (which can then be easily reused by other actions and controllers).

### Resourceful routing
Rails comes prebaked with all the logic to handle resourceful routing, i.e. routes that correspond directly (or mostly directly) to ActiveModel records in the db. It's handy and fast to define routes manually with `get '/path/to/thing'` and `post '/path/to/things'` but once you start to get a lot of these, the routes file becomes really hard to process in your head.

```ruby
resources :users, only: [] do # `only: []` means we're not actually generating any routes directly for `/users`
resources :quotes, only: [:index] # generate a `/users/quotes` route, which is a predefined behavior for how Rails treats the `:index` type route for a resource
end
```

This also sort of forces you to use the seven generic Rails controller method names (which is why `text_show` was renamed to `index`), which is good for letting other people easily recognize what's going on in your application's source, and for forcing you to think about splitting up controllers when a new action doesn't cleanly fit into one.

if this doesn't make any sense to you look over http://guides.rubyonrails.org/routing.html
if it still doesn't make sense yet, don't merge it. It's better to have code that you understand than perfect code.

### `quote` vs. `quotes` in the URI
I think that, since this endpoint returns an array of things (even if the default length of the array is 1), the URI should be plural. This also comes with resourceful routing, which sets the convention that under most circumstances these things should be plural (in the URL and in controller names).

## Note on serializers

if you want external services to be able to safely consume this API, you may want to think about using some sort of strict versioning and ActiveModel serializers. That `.map` call I put in QuotesController is going to start getting stinky quickly if you want to both (a) change stuff and (b) maintain backwards compatibility. If you don't care about external applications and you just care about salty_bot himself, then you don't have to worry about this.