Grape API Framework

repository·master·Indexed 27 days ago

https://github.com/ruby-grape/grape

A REST-like API framework for Ruby designed to run on Rack or complement frameworks like Rails and Sinatra. Grape provides a DSL for developing RESTful APIs with built-in support for versioning, content negotiation, and multiple formats. It requires Ruby 3.3 or newer.

Tokens
26.9K
Snippets
101
Records
165
Agent score
95%

What's inside Grape

  1. Use `translate` for custom validator error messages

    master

    Custom validators should use the translate method (provided by Grape::Util::Translation) instead of calling I18n.t or I18n.translate directly. This ensures consistency with built-in validators.

    • The scope defaults to 'grape.errors.messages'.
    • Interpolation variables are passed directly to I18n.
    • The format argument is no longer required as translate returns the fully interpolated string.
  2. Upgrade to Grape >= 4.0.0: Cascading Route Behavior

    master

    In Grape 4.0.0+, a route that responds with X-Cascade: pass (the default for version mismatches) now hands the request to every remaining matching route in registration order before the router gives up.

    Previously, it only handed over to the last registered route for that path. This change has two main effects:

    1. Middle versions are served: If you have mount v1; mount v2; mount v3, a request for v2 will now be served instead of returning a 406 API version not found.
    2. Catch-all fallback: If a catch-all route :any, '*path' is present, unmatched versions will fall through to it.

    To maintain the old behavior (returning a hard 406 for unmatched versions and preventing them from hitting a catch-all), declare your version with cascade: false.

  3. Altering API responses using present and error!

    master

    You can modify the response data or terminate the request flow from within callbacks.

    • present: Use this in a callback (like after_validation) to add additional data to the response payload.
    • error!: Use this to terminate the current request and rewrite the response. Calling error! in a callback prevents all subsequent steps, including the actual API call and any remaining callbacks, from executing.
    class MyAPI < Grape::API
      format :json
    
      after_validation do
        present :name, params[:name] if params[:name]
      end
    
      get '/greeting' do
        present :greeting, 'Hello!'
      end
    end
    # GET /greeting?name=Alan -> {"name":"Alan","greeting":"Hello!"}
  4. Handle parameter renaming with `as` in Grape >= 1.6.0

    master

    When using the as option to rename a parameter (e.g., optional :a, as: :b), Grape >= 1.6.0 ensures that if a client sends the new name (b) instead of the original name (a), the parameter is correctly validated and cast. In versions <= 1.5.3, sending the renamed key would result in an uncasted and unvalidated value.

    Additionally, the given block for dependent parameters now works using the original parameter name, as renaming is handled internally by the #declared(params) helper.

    # Renaming a to b
    optional :a, type: Integer, as: :b
    params = { b: '5' }
    declared(params, include_missing: false)
    # >= 1.6.0: returns { b: 5 } (casted/validated)
    # <= 1.5.3: returns { b: '5' } (uncasted/unvalidated)
    
    # Dependent params now work with the original name
    params do
      optional :a, as: :b
      given :a do
        requires :c
      end
    end
  5. Enable JSONP support

    master

    Grape supports JSONP via the rack-contrib gem. To enable it, add rack-contrib to your Gemfile and use the Rack::JSONP middleware in your API.

    require 'rack/contrib'
    
    class API < Grape::API
      use Rack::JSONP
      format :json
      get '/' do
        'Hello World'
      end
    end
  6. Handle nil values for Arrays, Hashes, and Sets in Grape >= 1.3.3

    master

    In Grape >= 1.3.3, nil values for structured types (Array, Hash, Set) remain nil. In version 1.3.2, they were converted to empty structures (e.g., [] for Arrays).

    To ensure a nil input results in an empty structure, apply a default validator.

  7. Upgrade to Grape >= 3.1: Namespace and Route Param changes

    master

    In Grape 3.1+, API#namespace and route_param use explicit keyword arguments (**options) instead of a single options hash.

    Key changes:

    • requirements is now an explicit parameter and is no longer part of the options hash. Calling requirements still works, but options[:requirements] will be empty.
    • For route_param, type is now an explicit parameter and is no longer part of the options hash.
  8. Reload API changes in Rails 6 and earlier

    master

    For older Rails versions, you must manually configure API paths and a reloader.

    1. Add API paths to config/application.rb:
    config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
    config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
    1. Create config/initializers/reload_api.rb to handle explicit unloading and file watching:
    if Rails.env.development?
      ActiveSupport::Dependencies.explicitly_unloadable_constants << 'Twitter::API'
    
      api_files = Dir[Rails.root.join('app', 'api', '**', '*.rb')]
      api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do
        Rails.application.reload_routes!
      end
      ActiveSupport::Reloader.to_prepare do
        api_reloader.execute_if_updated
      end
    end
    # Auto-load API and its subdirectories
    config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
    config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
  9. Mount Grape in a Rails application

    master

    To integrate Grape with Rails:

    1. Place API files in app/api. Follow the directory structure: app/api/module_name/class_name.rb (e.g., app/api/twitter/api.rb for Twitter::API).
    2. Mount the API in config/routes.rb using mount Twitter::API => '/'.
    3. Zeitwerk Configuration: Since Rails' default autoloader Zeitwerk inflects api as Api instead of API, you must add API as an acronym in config/initializers/inflections.rb:
    ActiveSupport::Inflector.inflections(:en) do |inflect|
      inflect.acronym 'API'
    end
  10. Upgrade to Grape >= 3.0.0: Configuration API Migration

    master
    Grape has migrated its configuration system from ActiveSupport::Configurable to Dry::Configurable. This change was made following the deprecation of ActiveSupport::Configurable in Rails.
  11. Stub Grape helpers using Grape::Testing

    master

    Because Grape helpers are mixed in based on context, they can be difficult to mock. Use the Grape::Testing module to define behavior that runs before every request on an endpoint.

    First, require the module in your test helper:

    require 'grape/testing'

    Then use Grape::Endpoint.before_each to stub helpers, and ensure you call Grape::Endpoint.reset_before_each in an after block to prevent side effects in other tests.

    describe 'an endpoint that needs helpers stubbed' do
      before do
        Grape::Endpoint.before_each do |endpoint|
          allow(endpoint).to receive(:helper_name).and_return('desired_value')
        end
      end
    
      after do
        Grape::Endpoint.reset_before_each
      end
    
      it 'stubs the helper' do
      end
    end
  12. Configure nil value coercion in Grape >= 1.5.3

    master
    In Grape >= 1.5.3, passing a nil value to a parameter with a custom coerce_with proc will trigger the coercion. In previous versions (1.3.0+), nil values skipped coercion. If a parameter is entirely missing from the request, coercion is not invoked.