grape-entity
grape-entity copied to clipboard
No Entity class lookup for collections
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