### Install OliveBranch Gem and Mount Middleware Source: https://context7.com/vigetlabs/olive_branch/llms.txt Add the OliveBranch gem to your Gemfile and then mount the middleware in your application's configuration file. ```ruby gem "olive_branch" ``` ```ruby module MyApp class Application < Rails::Application # Header-controlled mode: client sends Key-Inflection header to opt in config.middleware.use OliveBranch::Middleware end end ``` -------------------------------- ### Custom Camelize Implementation Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Initialize the middleware with custom camelize implementations for performance optimization. This example uses a cache for faster lookups. ```ruby 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) ``` -------------------------------- ### Add OliveBranch to Gemfile Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Include this line in your Gemfile and run 'bundle install' to add the gem to your project. ```ruby gem "olive_branch" ``` -------------------------------- ### Basic Middleware Setup with Header Control Source: https://context7.com/vigetlabs/olive_branch/llms.txt Configure OliveBranch to use header-controlled inflection. Clients send the 'Key-Inflection' header to specify the desired casing for JSON keys in requests and responses. ```ruby config.middleware.use OliveBranch::Middleware ``` ```shell # Client request (JavaScript/curl): # curl -X PUT https://api.example.com/posts/1 \ # -H "Content-Type: application/json" \ # -H "Key-Inflection: camel" \ # -d '{"post": {"authorName": "Jane Doe", "publishedAt": "2024-01-01"}}' ``` ```ruby # What the Rails controller receives (auto snake_cased): # params => { post: { author_name: "Jane Doe", published_at: "2024-01-01" } } ``` ```ruby # Controller renders normal snake_case JSON: render json: { post_author_name: "Jane Doe", published_at: "2024-01-01" } ``` ```ruby # Response the client receives (auto camelCased by middleware): # {"postAuthorName":"Jane Doe","publishedAt":"2024-01-01"} ``` -------------------------------- ### Supported Inflection Modes with cURL Examples Source: https://context7.com/vigetlabs/olive_branch/llms.txt Demonstrates how to use different inflection modes (camel, dash, pascal) via the 'Key-Inflection' header with cURL requests. Snake_case is a no-op as it's the Rails default. ```shell # camel → authorName, publishedAt # dash → author-name, published-at # pascal → AuthorName, PublishedAt # snake → author_name, published_at (no-op; Rails default) # curl examples for each mode (server has no default inflection configured): # camelCase curl -H "Key-Inflection: camel" -H "Content-Type: application/json" \ https://api.example.com/posts/1 # Response: {"authorName":"Jane","publishedAt":"2024-01-01"} # dash-case curl -H "Key-Inflection: dash" -H "Content-Type: application/json" \ https://api.example.com/posts/1 # Response: {"author-name":"Jane","published-at":"2024-01-01"} # PascalCase curl -H "Key-Inflection: pascal" -H "Content-Type: application/json" \ https://api.example.com/posts/1 # Response: {"AuthorName":"Jane","PublishedAt":"2024-01-01"} ``` -------------------------------- ### Query Parameter Transformation Example Source: https://context7.com/vigetlabs/olive_branch/llms.txt OliveBranch transforms nested camelCase or PascalCase query string parameters into snake_case before they reach the controller. Path parameters are not transformed. ```shell # Client sends camelCase query params: # GET /posts?categoryFilter[categoryName][]=food&categoryFilter[categoryName][]=travel # with header: Key-Inflection: camel ``` ```ruby # Controller receives (snake_cased automatically): # params[:category_filter][:category_name] #=> ["food", "travel"] ``` ```ruby # Rails controller example: class PostsController < ApplicationController def index filter = params[:category_filter] # snake_cased by middleware names = filter&.dig(:category_name) || [] render json: { results: Post.where(category: names) } end end # Note: path parameters (e.g., :postId from /posts/:postId) are NOT transformed. ``` -------------------------------- ### Exclude Response Transformation Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Define a custom proc for 'exclude_response' to prevent response transformation for specific routes. This example excludes routes matching '/do_not_transform'. ```ruby config.middleware.use OliveBranch::Middleware, exclude_response: -> (env) { env['PATH_INFO'].match(/^\/do_not_transform/) } ``` -------------------------------- ### Exclude Params Transformation Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Define a custom proc for 'exclude_params' to prevent parameter transformation for specific routes. This example excludes routes matching '/do_not_transform'. ```ruby config.middleware.use OliveBranch::Middleware, exclude_params: -> (env) { env['PATH_INFO'].match(/^\/do_not_transform/) } ``` -------------------------------- ### Custom Content-Type Check Source: https://context7.com/vigetlabs/olive_branch/llms.txt Override the default content type check to match custom media types or force transformation on all requests. This is particularly useful for GET requests where the Content-Type header might be stripped. ```ruby # config/application.rb # Force transformation on every request regardless of Content-Type config.middleware.use OliveBranch::Middleware, content_type_check: ->(_content_type) { true } # Or match a custom media type config.middleware.use OliveBranch::Middleware, content_type_check: ->(content_type) { content_type == "application/vnd.myapp+json" } # This solves the common problem where GET requests lose their Content-Type header # (e.g., Axios strips Content-Type on GET requests with empty bodies), causing # the middleware to skip transformation silently. ``` -------------------------------- ### Configure OliveBranch Middleware (Default) Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Add this to your config/application.rb to enable the middleware. This allows clients to control key inflection via the 'Key-Inflection' HTTP header. ```ruby config.middleware.use OliveBranch::Middleware ``` -------------------------------- ### Configure OliveBranch Middleware (API Only) Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Use this configuration in config/application.rb if you want to always convert between snake_case and camelCase for your API, regardless of client headers. ```ruby excluded_routes = -> (env) { !env["PATH_INFO"].match(%r{^/api}) } config.middleware.use OliveBranch::Middleware, inflection: "camel", exclude_params: excluded_routes, exclude_response: excluded_routes ``` -------------------------------- ### Standalone Transformation Helpers Source: https://context7.com/vigetlabs/olive_branch/llms.txt Use `OliveBranch::Transformations` for low-level key-transformation methods and recursive dispatching. These can be used directly in custom middleware or service objects. ```ruby # Standalone usage of transformation helpers require "olive_branch" hash = { "author_name" => "Jane", "published_at" => "2024-01-01" } # Camelize all keys (snake_case → camelCase) OliveBranch::Transformations.transform(hash, OliveBranch::Transformations.method(:camelize)) # => { "authorName" => "Jane", "publishedAt" => "2024-01-01" } # Dasherize all keys (snake_case → dash-case) OliveBranch::Transformations.transform(hash, OliveBranch::Transformations.method(:dasherize)) # => { "author-name" => "Jane", "published-at" => "2024-01-01" } # Pascalize all keys (snake_case → PascalCase) OliveBranch::Transformations.transform(hash, OliveBranch::Transformations.method(:pascalize)) # => { "AuthorName" => "Jane", "PublishedAt" => "2024-01-01" } # Works recursively on nested hashes and arrays nested = [{ "user_id" => 1, "first_name" => "Jane" }, { "user_id" => 2, "first_name" => "John" }] OliveBranch::Transformations.transform(nested, OliveBranch::Transformations.method(:camelize)) # => [{ "userId" => 1, "firstName" => "Jane" }, { "userId" => 2, "firstName" => "John" }] ``` -------------------------------- ### Default Inflection Configuration for API Routes Source: https://context7.com/vigetlabs/olive_branch/llms.txt Configure OliveBranch to always convert keys to a specific format (e.g., camelCase) for certain routes (e.g., /api/*) without requiring a client header. This is useful for dedicated JSON APIs. ```ruby # config/application.rb — always convert to/from camelCase for /api routes only api_only = ->(env) { !env["PATH_INFO"].match(%r{^/api}) } config.middleware.use OliveBranch::Middleware, inflection: "camel", exclude_response: api_only # Now all /api/* requests are converted automatically — no header needed: # curl -X POST https://api.example.com/api/users \ # -H "Content-Type: application/json" \ # -d '{"firstName":"Jane","lastName":"Doe"}' # # Controller receives: params => { first_name: "Jane", last_name: "Doe" } # Response sent as: { "firstName": "Jane", "lastName": "Doe" } ``` -------------------------------- ### Custom Camelize/Dasherize Methods Source: https://context7.com/vigetlabs/olive_branch/llms.txt Provide cached or custom transformation functions to improve performance. A memoized implementation can significantly reduce response time for large payloads. ```ruby # config/application.rb # Memoized camelizer — safe when key space is bounded (typical for APIs) class FastCamel def self.cache @cache ||= {} end def self.camelize(string) cache[string] ||= string.underscore.camelize(:lower) end end class FastDash def self.cache @cache ||= {} end def self.dasherize(string) cache[string] ||= string.dasherize end end config.middleware.use OliveBranch::Middleware, camelize: FastCamel.method(:camelize), dasherize: FastDash.method(:dasherize) # Without cache: each key is re-computed on every request # With cache: key transformations are computed once and reused — ~75% faster # for complex payloads (benchmark from README) # WARNING: Do not use a cache if your API has unbounded/dynamic key names, # as it can cause unlimited memory growth. ``` -------------------------------- ### Check Content Type Source: https://context7.com/vigetlabs/olive_branch/llms.txt Checks if the content type is either application/json or application/vnd.api+json. Returns truthy for matching types and nil (falsy) otherwise. ```ruby OliveBranch::Checks.content_type_check("application/json") # => truthy OliveBranch::Checks.content_type_check("application/vnd.api+json") # => truthy OliveBranch::Checks.content_type_check("text/html") # => nil (falsy) ``` -------------------------------- ### Set Default Inflection Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Specify a default inflection type (e.g., 'camel') in the middleware configuration to avoid requiring the 'Key-Inflection' header on every request. ```ruby config.middleware.use OliveBranch::Middleware, inflection: 'camel' ``` -------------------------------- ### Custom Content Type Check Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Implement a custom content type check using a lambda when configuring the middleware. This allows selective application of the middleware based on the request's content type. ```ruby config.middleware.use OliveBranch::Middleware, content_type_check: -> (content_type) { content_type == "my/content-type" } ``` -------------------------------- ### Custom Inflection Header Name Source: https://context7.com/vigetlabs/olive_branch/llms.txt Replace the default `Key-Inflection` header with a custom header name. This is useful when integrating with API gateways or proxies that might reserve or rewrite the default header. ```ruby # config/application.rb config.middleware.use OliveBranch::Middleware, inflection_header: "Inflect-With" # Client sends: # curl -H "Inflect-With: camel" -H "Content-Type: application/json" \ # https://api.example.com/posts/1 # Useful when integrating with API gateways or proxies that reserve or # rewrite the default Key-Inflection header. ``` -------------------------------- ### Default Exclude Check Source: https://context7.com/vigetlabs/olive_branch/llms.txt This check always returns false, indicating that no routes are excluded by default. ```ruby OliveBranch::Checks.default_exclude({}) # => false ``` -------------------------------- ### Change Default Inflection Header Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Customize the HTTP header used for controlling inflection by modifying the 'inflection_header' option when configuring the middleware. ```ruby config.middleware.use OliveBranch::Middleware, inflection_header: 'Inflect-With' ``` -------------------------------- ### Force Inbound Transformation in OliveBranch Middleware Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Override the `content_type_check` to ensure inbound transformations occur on every request, regardless of the Content-Type header. This is useful when the default JSON check prevents transformations on non-JSON requests. ```ruby config.middleware.use OliveBranch::Middleware, content_type_check: -> (content_type) { true } ``` -------------------------------- ### Exclude Routes from Transformation Source: https://context7.com/vigetlabs/olive_branch/llms.txt Use `exclude_params` and `exclude_response` to skip transformation for specific URL paths. This is useful for Rails engine routes or legacy endpoints that should not have their keys transformed. ```ruby # config/application.rb # Exclude Rails internal routes (required when using Action Text / Active Storage) rails_routes = ->(env) { env["PATH_INFO"].match?(%r{^/rails}) } # Exclude a legacy endpoint from transformation legacy_routes = ->(env) { env["PATH_INFO"].match?(%r{^/legacy}) } combined_exclude = ->(env) { rails_routes.call(env) || legacy_routes.call(env) } config.middleware.use OliveBranch::Middleware, inflection: "camel", exclude_params: combined_exclude, exclude_response: combined_exclude # /rails/active_storage/... → keys untouched (Rails internals work correctly) # /legacy/... → keys untouched # /api/... → full camelCase conversion applied ``` -------------------------------- ### Exclude Rails Routes for Inflection Source: https://github.com/vigetlabs/olive_branch/blob/main/README.md Configure the middleware to exclude specific Rails routes (e.g., '/rails') from both parameter and response transformations when using default inflection. ```ruby rails_routes = -> (env) { env['PATH_INFO'].match(/^\/rails/) } config.middleware.use OliveBranch::Middleware, inflection: "camel", exclude_params: rails_routes, exclude_response: rails_routes ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.