Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added a look up for nested presenters #114

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Rewritten .gemspec and removed Jeweler - [@dblock](https://github.com/dblock).
* Added `GrapeEntity::VERSION` - [@dblock](https://github.com/dblock).
* Added Rubocop, Ruby-style linter - [@dblock](https://github.com/dblock).
* Adding support for generating nested models from composed Grape Entities [@dspaeth-faber](https://github.com/dspaeth-faber)
* Your Contribution Here

### 0.7.2 (February 6, 2014)
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ module API
module Entities
class Status < Grape::Entity
expose :text, :documentation => { :type => "string", :desc => "Status update text." }
expose :links, using: Link, :documentation => { type: 'link', is_array: true }
end

class Link < Grape::Entity
def self.entity_name
'link'
end

expose :href, :documentation => { :type => 'url' }
expose :rel, :documentation => { :type => 'string'}
end
end

Expand Down
22 changes: 21 additions & 1 deletion lib/grape-swagger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def self.setup(options)
route.route_entity
end

models = models.flatten.compact
models = models_with_included_presenters(models.flatten.compact)

operation = {
notes: notes.to_s,
Expand Down Expand Up @@ -378,6 +378,26 @@ def parse_entity_models(models)
result
end

def models_with_included_presenters(models)
all_models = models

models.each do |model|
properties = model.exposures
documented_properties = {}

model.documentation.keys.each_with_object(documented_properties) do |k, hash|
hash[k] = properties[k] if properties.key?(k)
end

properties_configuration = documented_properties.values
additional_models = properties_configuration.map { |config| config[:using] }.compact

all_models += additional_models
end

all_models
end

def is_primitive?(type)
%w(integer long float double string byte boolean date dateTime).include? type
end
Expand Down
115 changes: 104 additions & 11 deletions spec/api_models_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,28 @@ class Thing < Grape::Entity
end
end

module Entities
class ComposedOf < Grape::Entity
expose :part_text, documentation: { type: 'string', desc: 'Content of composedof.' }
end

class ComposedOfElse < Grape::Entity
def self.entity_name
'composed'
end
expose :part_text, documentation: { type: 'string', desc: 'Content of composedof else.' }
end

class SomeThingElse < Grape::Entity
expose :else_text, documentation: { type: 'string', desc: 'Content of something else.' }
expose :parts, using: Entities::ComposedOf, documentation: { type: 'ComposedOf',
is_array: true,
required: true }

expose :part, using: Entities::ComposedOfElse, documentation: { type: 'composes' }
end
end

class ModelsApi < Grape::API
format :json
desc 'This gets something.',
Expand All @@ -34,6 +56,15 @@ class ModelsApi < Grape::API
thing = OpenStruct.new text: 'thing'
present thing, with: Entities::Some::Thing
end

desc 'This gets somthing else.',
entity: Entities::SomeThingElse
get '/somethingelse' do
part = OpenStruct.new part_text: 'part thing'
thing = OpenStruct.new else_text: 'else thing', parts: [part], part: part

present thing, with: Entities::SomeThingElse
end
add_swagger_documentation
end
end
Expand All @@ -44,17 +75,20 @@ def app

it 'should document specified models' do
get '/swagger_doc'
JSON.parse(last_response.body).should == {
'apiVersion' => '0.1',
'swaggerVersion' => '1.2',
'info' => {},
'produces' => ['application/json'],
'apis' => [
{ 'path' => '/something.{format}', 'description' => 'Operations about somethings' },
{ 'path' => '/thing.{format}', 'description' => 'Operations about things' },
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
]
}
result = JSON.parse(last_response.body)

expect(result).to include('apiVersion' => '0.1',
'swaggerVersion' => '1.2',
'info' => {},
'produces' => ['application/json'])

expect(result['apis']).to eq [
{ 'path' => '/something.{format}', 'description' => 'Operations about somethings' },
{ 'path' => '/thing.{format}', 'description' => 'Operations about things' },
{ 'path' => '/somethingelse.{format}',
'description' => 'Operations about somethingelses' },
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
]
end

it 'should include type when specified' do
Expand Down Expand Up @@ -123,4 +157,63 @@ def app
}
end

it 'should include entities which are only used as composition' do
get '/swagger_doc/somethingelse.json'
result = JSON.parse(last_response.body)

expect(result).to include('apiVersion' => '0.1',
'swaggerVersion' => '1.2',
'basePath' => 'http://example.org',
'resourcePath' => '/somethingelse')

expect(result['apis']).to eq([{
'path' => '/somethingelse.{format}',
'operations' => [{
'notes' => '',
'type' => 'SomeThingElse',
'summary' => 'This gets somthing else.',
'nickname' => 'GET-somethingelse---format-',
'method' => 'GET',
'parameters' => []
}]
}])

expect(result['models']['SomeThingElse']).to include('id' => 'SomeThingElse',
'properties' => {
'else_text' => {
'type' => 'string',
'description' => 'Content of something else.'
},
'parts' => {
'type' => 'array',
'items' => { '$ref' => 'ComposedOf' }
},
'part' => { '$ref' => 'composes' }
},
'required' => ['parts']

)

expect(result['models']['ComposedOf']).to include(
'id' => 'ComposedOf',
'properties' => {
'part_text' => {
'type' => 'string',
'description' => 'Content of composedof.'
}
}
)

expect(result['models']['composed']).to include(
'id' => 'composed',
'properties' => {
'part_text' => {
'type' => 'string',
'description' => 'Content of composedof else.'
}

}
)
end

end