OliveBranch
This gem lets your API users pass in and receive camelCased or dash-cased keys, while your Rails app receives and produces snake_cased ones.
Install
- Add this to your Gemfile and then
bundle install
:
gem "olive_branch"
- Add this to
config/applcation.rb
:
config.middleware.use OliveBranch::Middleware
Use
Include a X-Key-Inflection
header with values of camel
, dash
, or snake
in your JSON API requests.
For more examples, see our blog post.
Optimizations and configuration
OliveBranch
uses multi_json
, which will choose the fastest available JSON parsing library and use that. Combined with Oj
can speed things up and save ~20% rails response time.
The middleware can be initialized with custom camelize/dasherize implementations, so if you know you have a fixed size set of keys, you can save a considerable amount of time by providing a custom camelize that caches like so:
class FastCamel
def self.camel_cache
@camel_cache ||= {}
end
def self.camelize(string)
camel_cache[string] ||= string.underscore.camelize(:lower)
end
end
...
config.middleware.use OliveBranch::Middleware, camelize: FastCamel.method(:camelize)
A default inflection can be specified so you don't have to include the X-Key-Inflection
header on every request.
config.middleware.use OliveBranch::Middleware, inflection: 'camel'
A benchmark of this compared to the standard implementation shows a saving of ~75% rails response times for a complex response payload, or a ~400% improvement, but there is a risk of memory usage ballooning if you have dynamic keys. You can make this method as complex as required, but keep in mind that it will end up being called a lot in a busy app, so it's worth thinking about how to do what you need in the fastest manner possible.
Filtering
Content type
It is also possible to include a custom content type check in the same manner
config.middleware.use OliveBranch::Middleware, content_type_check: -> (content_type) {
content_type == "my/content-type"
}
Excluding URLs
Additionally you can define a custom check by passing a proc
For params transforming
config.middleware.use OliveBranch::Middleware, exclude_params: -> (env) {
env['PATH_INFO'].match(/^\/do_not_transform/)
}
Or response transforming
config.middleware.use OliveBranch::Middleware, exclude_response: -> (env) {
env['PATH_INFO'].match(/^\/do_not_transform/)
}
Troubleshooting
We've seen a few folks raise issues that inbound transformations are not taking place. This is often due to the fact that OliveBranch, by default, is only transforming keys when a request's Content-Type is application/json
. If you would like to force inbound transformation on every request, you must define an override for the content_type_check
functionality:
config.middleware.use OliveBranch::Middleware, content_type_check: -> (content_type) { true }
OliveBranch is released under the MIT License. See MIT-LICENSE for further details.
Visit code.viget.com to see more projects from Viget.