ruby-grape / ruby-grape/grape

variable scope in Grape versioned-controller

Open
#1,627 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug?
Dominant language
Ruby
Stars
10k
Forks
1.2k
Avg merge
14h 38m
Merged PRs (30d)
92

Description

Hello,
I have been using Grape to build an API within an already-existing Rails project.
I have been dealing with an error that I do not understand and I wonder if somebody could draw some light on this as it could be a bug but I am not sure.

My colleague and I were tasked with creating 4 end-points for this API:

  • /packages
  • /packages/:id
  • /options
  • /options/:id

This is what my colleague wrote (which works perfectly!):

module API
  class V1::Package < Grape::API
    get '/packages/:id' do
      @package = ::Package.find_by(id: params[:id])
      render rabl: 'v1/packages/show'
    end

    get '/packages' do
      @packages = ::Package.all
      render rabl: 'v1/packages/index'
    end
  end
end

And this is what I wrote (basically the exact same, but for options):

module API
  class V1::Option < Grape::API
    get '/options/:id' do
      @option = ::Option.find_by(id: params[:id])
      render rabl: 'v1/options/show'
    end

    get '/options' do
      @options = ::Option.all
      render rabl: 'v1/options/index'
    end
  end
end

The first end-point (/options/:id) works but the second one throws an error.

  API::V1::Option GET /api/v1/options/ returns all options
     Failure/Error: get '/api/v1/options'

     TypeError:
       no implicit conversion of Symbol into Integer

This is because basically @options is expected to be a Hash and not an Array (or ActiveRecord::Relation). Further debugging made me discover that using a different variable (something other than @options) fixed the issue!

But why is this?

In the first example (my colleague's code), @packages is set to nil before being set to whatever we set it to. But in my case @options was assigned to:

{
                   :method => [
        [0] "GET"
    ],
                     :path => [
        [0] "/options"
    ],
                      :for => API::V1::Option < Grape::API,
            :route_options => {
        :params => {}
    },
    :options_route_enabled => true
}

and (re-)assigning it to an array, a collection or an ActiveRecord::Relation broke the code. For now, I'll just re-name my variable to something else but I'd love to hear somebody else's opinion on this as I don't think this behaviour is expected.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the GET /api/v1/options failure from the issue, comparing the API::V1::Package and API::V1::Option Grape::API definitions. Inspect how the /options route and its render rabl target use @options, then verify that the endpoint works with the intended collection value and that the existing package endpoints remain unaffected.

Written by the indexing model from the issue text.

Assessment

Tech stack
rails, ruby
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.