OliveBranch

repository·main·Indexed 41 days ago

https://github.com/vigetlabs/olive_branch

A Ruby gem that automatically transforms JSON API keys between snake_case, camelCase, dash-case, and PascalCase. It provides middleware for Rails applications to handle key inflection via a fixed configuration or a client-controlled 'Key-Inflection' HTTP header.

Tokens
1.7K
Snippets
5
Records
7
Agent score
2%

What's inside OliveBranch

  1. Use Key-Inflection header to control casing

    main

    If you have configured the middleware without a fixed inflection setting, clients can control how keys are transformed by including the Key-Inflection HTTP header in their requests. Supported values are:

    • camel (camelCase)
    • dash (dash-case)
    • snake (snake_case)
    • pascal (PascalCase)
  2. Optimize OliveBranch performance

    main

    You can improve the performance of OliveBranch using two main methods:

    1. Use a faster JSON parser

    OliveBranch uses multi_json. By adding a faster coder like oj to your Gemfile, you can potentially reduce response times by ~20%.

    2. Implement a cached camelizer

    If you have a fixed set of keys, you can provide a custom camelize implementation that uses a cache to avoid repeated string transformations. This can significantly improve response times for complex payloads, though be cautious of memory usage if your keys are highly dynamic.

    class FastCamel
      def self.camel_cache
        @camel_cache ||= {}
      end
    
      def self.camelize(string)
        camel_cache[string] ||= string.underscore.camelize(:lower)
      end
    end
    
    # Apply in config/application.rb
    config.middleware.use OliveBranch::Middleware, camelize: FastCamel.method(:camelize)
  3. Install OliveBranch

    main

    To use OliveBranch in your Rails application, add the gem to your Gemfile and run bundle install.

    Depending on your needs, you can configure the middleware in config/application.rb in two ways:

    1. Client-controlled inflection: Use this if you want clients to specify the key casing via the Key-Inflection HTTP header.
    2. Fixed API inflection: Use this to always convert between snake_case and camelCase for specific routes (e.g., only your /api routes), keeping Ruby and JavaScript conventions separate.
    # 1. Add to Gemfile
    gem "olive_branch"
    
    # 2. Add to config/application.rb
    # Option A: Client controls behavior via 'Key-Inflection' header
    config.middleware.use OliveBranch::Middleware
    
    # Option B: Always use camelCase for specific routes (e.g., /api)
    excluded_routes = ->(env) { !env["PATH_INFO"].match(%r{^/api}) }
    config.middleware.use OliveBranch::Middleware,
                          inflection:       "camel",
                          exclude_params:   excluded_routes,
                          exclude_response: excluded_routes
  4. Troubleshoot inbound transformations

    main

    If inbound transformations (request parameters) are not working, check the following:

    1. Content-Type Header: By default, OliveBranch only transforms requests where the Content-Type is application/json. If your client (like Axios) suppresses the Content-Type header on empty-body requests (common in GET requests), the middleware will skip transformation.
    2. Force Transformation: To bypass the content-type check and force transformation on every request, use the following configuration:
    config.middleware.use OliveBranch::Middleware, content_type_check: -> (content_type) { true }
  5. Filter transformations with procs

    main

    You can control when transformations occur by providing procs to the following options:

    • exclude_params: A proc that receives the env and returns true if inbound parameter transformation should be skipped.
    • exclude_response: A proc that receives the env and returns true if outbound response transformation should be skipped.
    • content_type_check: A proc that receives the content_type string and returns true if transformation should proceed.

    Example: Excluding Rails internal routes from transformation:

    rails_routes = -> (env) { env['PATH_INFO'].match(/^/rails/) }
    config.middleware.use OliveBranch::Middleware, inflection: "camel", exclude_params: rails_routes, exclude_response: rails_routes
    # Exclude specific URL patterns for params
    config.middleware.use OliveBranch::Middleware, exclude_params: -> (env) { env['PATH_INFO'].match('/\/do_not_transform/') }
    
    # Exclude specific URL patterns for responses
    config.middleware.use OliveBranch::Middleware, exclude_response: -> (env) { env['PATH_INFO'].match('/\/do_not_transform/') }
    
    # Custom content type check
    config.middleware.use OliveBranch::Middleware, content_type_check: -> (content_type) { content_type == "my/content-type" }
  6. Configure OliveBranch middleware options

    main

    The OliveBranch::Middleware can be customized with several options during initialization in config/application.rb:

    • inflection: Sets a default inflection (e.g., 'camel') so clients don't have to send the header on every request.
    • inflection_header: Changes the name of the header used for inflection (defaults to Key-Inflection).
    • camelize: A custom method used for camelizing keys.
    • content_type_check: A proc that determines if the request should be transformed based on the Content-Type.
    # Change the header name
    config.middleware.use OliveBranch::Middleware, inflection_header: 'Inflect-With'
    
    # Set a default inflection
    config.middleware.use OliveBranch::Middleware, inflection: 'camel'