Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add best practices for building Ruby JSON APIs #365

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions best-practices/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,18 @@ Angular
[annotations]: http://robots.thoughtbot.com/avoid-angularjs-dependency-annotation-with-rails
[ngannotate]: https://github.com/kikonen/ngannotate-rails
[angular-translate]: https://github.com/angular-translate/angular-translate/wiki/Getting-Started#using-translate-directive

Ruby JSON APIs
--------------

* Review the recommended practices outlined in Heroku's [HTTP API Design Guide]
before designing a new API.
* Use a fast JSON parser, e.g. [`oj`][oj]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oj out of the box doesn't do exactly what you might expect:

irb(main):004:0> puts Oj.dump(foo: 'baz')
{":foo":"baz"}

I'd add a note here that for Ruby hashes w/ symbols you need to enable compat mode.

irb(main):005:0> Oj.default_options = {:mode => :compat }
=> {:mode=>:compat}
irb(main):006:0> puts Oj.dump(foo: 'baz')
{"foo":"baz"}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like for Rails 4.1~ there's a new gem that can be included:
https://github.com/ohler55/oj#compatibility

gem 'oj'
gem 'oj_mimic_json'

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@harlow good to know, thank you! I went ahead and merged this as-is but will see about expanding the recommendation to use oj to include some caveats about its usage in a separate PR.

* Write integration tests for your API endpoints. When the primary consumer of
the API is a JavaScript client maintained within the same code base as the
provider of the API, write [feature specs]. Otherwise write [request specs].

[HTTP API Design Guide]: https://github.com/interagent/http-api-design
[oj]: https://github.com/ohler55/oj
[feature specs]: https://www.relishapp.com/rspec/rspec-rails/docs/feature-specs/feature-spec
[request specs]: https://www.relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're using an in-app JavaScript client as the primary consumer of the API, have we generally done this? Many of the applications I've seen rely on Capybara feature specs to make sure the controllers/requests are working.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the JSON Api is being consumed by something else "in process" then I agree. If your ultimate deliverable is the JSON API, then the request specs are the edge.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jferris, @derekprior -- great point. I agree. I modified this bullet point accordingly in 3e2c9db.