grape-entity icon indicating copy to clipboard operation
grape-entity copied to clipboard

No Entity class lookup for collections

Open tscholz opened this issue 6 years ago • 0 comments

Hi there!

Thanks for the great gem. I like it a lot.

I'm new to Grape, so maybe I'm missing something. When using a custom entity with present_collection true the implicit lookup for the entity class of records in the :items array does not work.

Thank you for looking into this.

# frozen_string_literal: true

begin
  require "bundler/inline"
rescue LoadError => e
  $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
  raise e
end

gemfile(true) do
  source 'https://rubygems.org'

  gem 'grape'
  gem 'grape-entity'

  gem 'rack-test'
  gem 'rspec'
  gem 'byebug'
end

class Item
  attr_accessor :id, :name

  def initialize(id, name)
    @id, @name = id, name
  end

  def to_json(_opts = {})
    {id: id, name: name}.to_json
  end

  def entity
    Entity.new self
  end

  class Entity < Grape::Entity
    expose :id, as: 'THE_ID'
    expose :name, as: 'THE_NAME'
  end
end

class CollectionEntity < Grape::Entity
  present_collection true, :items

  expose :meta do
    expose :current_page
    expose :next_page
  end

  # No ', using: Item::Entity' here as I'd like to use the collecion
  # entity for different types of objects. I'd expect the implicit entity
  # lookup here.
  expose :items

  def next_page
    current_page + 1
  end

  def current_page
    options.fetch :current_page
  end
end

class API < Grape::API
  version 'v1'
  format :json

  resource :items do
    desc 'Get items'
    params do
      optional :page, type: Integer, default: 1
      optional :per_page, type: Integer, default: 10
    end
    get do
      items = (1..1).to_a.map { |n| Item.new(n, "Item_#{n}") }

      present items, with: CollectionEntity, current_page: params[:page]
    end

    desc 'Get a item'
    params do
      requires :id, type: Integer
    end
    route_param :id do
      get do
        id = params[:id]
        present Item.new id, "Item_#{id}"
      end
    end
  end

end

require 'json'
require 'rspec/autorun'

describe API do
  include Rack::Test::Methods

  def app
    API
  end

  context 'get /v1/items' do

    # BROKEN TEST :(
    it 'is using Item::Entity for collection members' do
      get '/v1/items'
      expect(last_response.status).to eq(200)

      json = JSON.parse last_response.body
      item = json['items'].first

      expect(item).to eq({'THE_ID' => 1, 'THE_NAME' => 'Item_1'})
    end
  end


  context 'get /v1/items/:id' do

    it 'is using Item::Entity' do
      get '/v1/items/1'
      expect(last_response.status).to eq(200)

      item = JSON.parse last_response.body

      expect(item).to eq({'THE_ID' => 1, 'THE_NAME' => 'Item_1'})
    end
  end
end

tscholz avatar Jun 28 '18 09:06 tscholz