grape-entity 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/README.markdown +9 -20
- data/grape-entity.gemspec +4 -9
- data/lib/grape_entity.rb +2 -1
- data/lib/grape_entity/entity.rb +12 -12
- data/lib/grape_entity/version.rb +1 -1
- data/spec/grape_entity/entity_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -3
- metadata +36 -5
- data/tmp/rspec_guard_result +0 -1
data/.gitignore
CHANGED
data/README.markdown
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Grape::Entity
|
|
2
2
|
|
|
3
|
-
## CI
|
|
4
3
|
[](https://travis-ci.org/agileanimal/grape-entity)
|
|
5
4
|
|
|
6
5
|
## Introduction
|
|
7
6
|
|
|
8
|
-
This gem
|
|
9
|
-
|
|
10
|
-
Grape's Entity is a great idea: a API focussed Facade that sits on top of a model object.
|
|
11
|
-
|
|
12
|
-
The intend is to allow the Entity to be used outside of Grape and provide additional exposure to parts of the entity needed to simplify testing parts of an API.
|
|
13
|
-
|
|
14
|
-
We intend to use the specs from grape to ensure we maintain compatability with Grape through our changes so that we can use the Entity to replace Grape's internal Entity.
|
|
7
|
+
This gem adds Entity support to API frameworks, such as [Grape](https://github.com/intridea/grape). Grape's Entity is an API focussed facade that sits on top of an object model.
|
|
15
8
|
|
|
16
9
|
## Goals
|
|
17
10
|
|
|
@@ -23,10 +16,6 @@ There is probably something heavier than an Entity that exists as well. A way to
|
|
|
23
16
|
|
|
24
17
|
In this spirit I want to give Entities a life of their own.
|
|
25
18
|
|
|
26
|
-
## Project Tracking
|
|
27
|
-
|
|
28
|
-
* - Need to setup something up for this -
|
|
29
|
-
|
|
30
19
|
## Reusable Responses with Entities
|
|
31
20
|
|
|
32
21
|
Entities are a reusable means for converting Ruby objects to API responses.
|
|
@@ -35,7 +24,7 @@ ever larger responses, using inheritance.
|
|
|
35
24
|
|
|
36
25
|
### Defining Entities
|
|
37
26
|
|
|
38
|
-
Entities inherit from
|
|
27
|
+
Entities inherit from Grape::Entity, and define a simple DSL. Exposures can use
|
|
39
28
|
runtime options to determine which fields should be visible, these options are
|
|
40
29
|
available to `:if`, `:unless`, and `:proc`. The option keys `:version` and `:collection`
|
|
41
30
|
will always be defined. The `:version` key is defined as `api.version`. The
|
|
@@ -61,7 +50,7 @@ array.
|
|
|
61
50
|
```ruby
|
|
62
51
|
module API
|
|
63
52
|
module Entities
|
|
64
|
-
class Status <
|
|
53
|
+
class Status < Grape::Entity
|
|
65
54
|
expose :user_name
|
|
66
55
|
expose :text, :documentation => { :type => "string", :desc => "Status update text." }
|
|
67
56
|
expose :ip, :if => { :type => :full }
|
|
@@ -88,7 +77,7 @@ of an existing class:
|
|
|
88
77
|
|
|
89
78
|
```ruby
|
|
90
79
|
class Status
|
|
91
|
-
include
|
|
80
|
+
include Grape::Entity::DSL
|
|
92
81
|
|
|
93
82
|
entity :text, :user_id do
|
|
94
83
|
expose :detailed, if: :conditional
|
|
@@ -110,7 +99,7 @@ If the entity includes documentation it can be included in an endpoint's descrip
|
|
|
110
99
|
|
|
111
100
|
```ruby
|
|
112
101
|
module API
|
|
113
|
-
class Statuses <
|
|
102
|
+
class Statuses < Grape::API
|
|
114
103
|
version 'v1'
|
|
115
104
|
|
|
116
105
|
desc 'Statuses index', {
|
|
@@ -136,7 +125,7 @@ class Status
|
|
|
136
125
|
Status.new(self)
|
|
137
126
|
end
|
|
138
127
|
|
|
139
|
-
class Entity <
|
|
128
|
+
class Entity < Grape::Entity
|
|
140
129
|
expose :text, :user_id
|
|
141
130
|
end
|
|
142
131
|
end
|
|
@@ -157,7 +146,7 @@ However, when `object.check` equals "bar" both `field_b` and `foo` will be expos
|
|
|
157
146
|
```ruby
|
|
158
147
|
module API
|
|
159
148
|
module Entities
|
|
160
|
-
class Status <
|
|
149
|
+
class Status < Grape::Entity
|
|
161
150
|
expose :field_a, :foo, :if => lambda { |object, options| object.check == "foo" }
|
|
162
151
|
expose :field_b, :foo, :if => lambda { |object, options| object.check == "bar" }
|
|
163
152
|
end
|
|
@@ -170,7 +159,7 @@ This can be problematic, when you have mixed collections. Using `respond_to?` is
|
|
|
170
159
|
```ruby
|
|
171
160
|
module API
|
|
172
161
|
module Entities
|
|
173
|
-
class Status <
|
|
162
|
+
class Status < Grape::Entity
|
|
174
163
|
expose :field_a, :if => lambda { |object, options| object.check == "foo" }
|
|
175
164
|
expose :field_b, :if => lambda { |object, options| object.check == "bar" }
|
|
176
165
|
expose :foo, :if => lambda { |object, options| object.respond_to?(:foo) }
|
data/grape-entity.gemspec
CHANGED
|
@@ -7,21 +7,16 @@ Gem::Specification.new do |s|
|
|
|
7
7
|
s.platform = Gem::Platform::RUBY
|
|
8
8
|
s.authors = ["Michael Bleigh"]
|
|
9
9
|
s.email = ["michael@intridea.com"]
|
|
10
|
-
s.homepage = "https://github.com/
|
|
10
|
+
s.homepage = "https://github.com/agileanimal/grape-entity"
|
|
11
11
|
s.summary = %q{A simple facade for managing the relationship between your model and API.}
|
|
12
12
|
s.description = %q{Extracted from Grape, A Ruby framework for rapid API development with great conventions.}
|
|
13
13
|
s.license = "MIT"
|
|
14
14
|
|
|
15
15
|
s.rubyforge_project = "grape-entity"
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
# s.add_runtime_dependency 'multi_xml', '>= 0.5.2'
|
|
21
|
-
# s.add_runtime_dependency 'hashie', '~> 1.2'
|
|
22
|
-
# s.add_runtime_dependency 'virtus'
|
|
23
|
-
# s.add_runtime_dependency 'builder'
|
|
24
|
-
|
|
17
|
+
s.add_runtime_dependency 'activesupport'
|
|
18
|
+
s.add_runtime_dependency 'multi_json', '>= 1.3.2'
|
|
19
|
+
|
|
25
20
|
s.add_development_dependency 'rake'
|
|
26
21
|
s.add_development_dependency 'maruku'
|
|
27
22
|
s.add_development_dependency 'yard'
|
data/lib/grape_entity.rb
CHANGED
data/lib/grape_entity/entity.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Grape
|
|
2
2
|
# An Entity is a lightweight structure that allows you to easily
|
|
3
3
|
# represent data from your application in a consistent and abstracted
|
|
4
4
|
# way in your API. Entities can also provide documentation for the
|
|
@@ -8,7 +8,7 @@ module GrapeEntity
|
|
|
8
8
|
#
|
|
9
9
|
# module API
|
|
10
10
|
# module Entities
|
|
11
|
-
# class User <
|
|
11
|
+
# class User < Grape::Entity
|
|
12
12
|
# expose :first_name, :last_name, :screen_name, :location
|
|
13
13
|
# expose :field, :documentation => {:type => "string", :desc => "describe the field"}
|
|
14
14
|
# expose :latest_status, :using => API::Status, :as => :status, :unless => {:collection => true}
|
|
@@ -27,7 +27,7 @@ module GrapeEntity
|
|
|
27
27
|
# @example Usage in the API Layer
|
|
28
28
|
#
|
|
29
29
|
# module API
|
|
30
|
-
# class Users <
|
|
30
|
+
# class Users < Grape::API
|
|
31
31
|
# version 'v2'
|
|
32
32
|
#
|
|
33
33
|
# desc 'User index', { :object_fields => API::Entities::User.documentation }
|
|
@@ -47,7 +47,7 @@ module GrapeEntity
|
|
|
47
47
|
def self.included(base)
|
|
48
48
|
base.extend ClassMethods
|
|
49
49
|
ancestor_entity_class = base.ancestors.detect{|a| a.entity_class if a.respond_to?(:entity_class)}
|
|
50
|
-
base.const_set(:Entity, Class.new(ancestor_entity_class ||
|
|
50
|
+
base.const_set(:Entity, Class.new(ancestor_entity_class || Grape::Entity)) unless const_defined?(:Entity)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
module ClassMethods
|
|
@@ -61,13 +61,13 @@ module GrapeEntity
|
|
|
61
61
|
|
|
62
62
|
# Call this to make exposures to the entity for this Class.
|
|
63
63
|
# Can be called with symbols for the attributes to expose,
|
|
64
|
-
# a block that yields the full Entity DSL (See
|
|
64
|
+
# a block that yields the full Entity DSL (See Grape::Entity),
|
|
65
65
|
# or both.
|
|
66
66
|
#
|
|
67
67
|
# @example Symbols only.
|
|
68
68
|
#
|
|
69
69
|
# class User
|
|
70
|
-
# include
|
|
70
|
+
# include Grape::Entity::DSL
|
|
71
71
|
#
|
|
72
72
|
# entity :name, :email
|
|
73
73
|
# end
|
|
@@ -75,7 +75,7 @@ module GrapeEntity
|
|
|
75
75
|
# @example Mixed.
|
|
76
76
|
#
|
|
77
77
|
# class User
|
|
78
|
-
# include
|
|
78
|
+
# include Grape::Entity::DSL
|
|
79
79
|
#
|
|
80
80
|
# entity :name, :email do
|
|
81
81
|
# expose :latest_status, using: Status::Entity, if: :include_status
|
|
@@ -109,7 +109,7 @@ module GrapeEntity
|
|
|
109
109
|
# it will yield the object being represented and the options passed to the
|
|
110
110
|
# representation call. Return true to prevent exposure, false to allow it.
|
|
111
111
|
# @option options :using This option allows you to map an attribute to another Grape
|
|
112
|
-
# Entity. Pass it a
|
|
112
|
+
# Entity. Pass it a Grape::Entity class and the attribute in question will
|
|
113
113
|
# automatically be transformed into a representation that will receive the same
|
|
114
114
|
# options as the parent entity when called. Note that arrays are fine here and
|
|
115
115
|
# will automatically be detected and handled appropriately.
|
|
@@ -180,7 +180,7 @@ module GrapeEntity
|
|
|
180
180
|
#
|
|
181
181
|
# module API
|
|
182
182
|
# module Entities
|
|
183
|
-
# class User <
|
|
183
|
+
# class User < Grape::Entity
|
|
184
184
|
# format_with :timestamp do |date|
|
|
185
185
|
# date.strftime('%m/%d/%Y')
|
|
186
186
|
# end
|
|
@@ -192,7 +192,7 @@ module GrapeEntity
|
|
|
192
192
|
#
|
|
193
193
|
# @example Formatters are available to all decendants
|
|
194
194
|
#
|
|
195
|
-
#
|
|
195
|
+
# Grape::Entity.format_with :timestamp do |date|
|
|
196
196
|
# date.strftime('%m/%d/%Y')
|
|
197
197
|
# end
|
|
198
198
|
#
|
|
@@ -225,7 +225,7 @@ module GrapeEntity
|
|
|
225
225
|
#
|
|
226
226
|
# module API
|
|
227
227
|
# module Entities
|
|
228
|
-
# class User <
|
|
228
|
+
# class User < Grape::Entity
|
|
229
229
|
# root 'users', 'user'
|
|
230
230
|
# expose :id
|
|
231
231
|
# end
|
|
@@ -235,7 +235,7 @@ module GrapeEntity
|
|
|
235
235
|
# @example Usage in the API Layer
|
|
236
236
|
#
|
|
237
237
|
# module API
|
|
238
|
-
# class Users <
|
|
238
|
+
# class Users < Grape::API
|
|
239
239
|
# version 'v2'
|
|
240
240
|
#
|
|
241
241
|
# # this will render { "users": [ {"id":"1"}, {"id":"2"} ] }
|
data/lib/grape_entity/version.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
describe
|
|
4
|
-
let(:fresh_class) { Class.new(
|
|
3
|
+
describe Grape::Entity do
|
|
4
|
+
let(:fresh_class) { Class.new(Grape::Entity) }
|
|
5
5
|
|
|
6
6
|
context 'class methods' do
|
|
7
7
|
subject { fresh_class }
|
|
@@ -379,7 +379,7 @@ describe GrapeEntity::Entity do
|
|
|
379
379
|
it 'disables root key name for child representations' do
|
|
380
380
|
|
|
381
381
|
module EntitySpec
|
|
382
|
-
class FriendEntity <
|
|
382
|
+
class FriendEntity < Grape::Entity
|
|
383
383
|
root 'friends', 'friend'
|
|
384
384
|
expose :name, :email
|
|
385
385
|
end
|
|
@@ -398,7 +398,7 @@ describe GrapeEntity::Entity do
|
|
|
398
398
|
|
|
399
399
|
it 'passes through custom options' do
|
|
400
400
|
module EntitySpec
|
|
401
|
-
class FriendEntity <
|
|
401
|
+
class FriendEntity < Grape::Entity
|
|
402
402
|
root 'friends', 'friend'
|
|
403
403
|
expose :name
|
|
404
404
|
expose :email, :if => { :user_type => :admin }
|
|
@@ -424,7 +424,7 @@ describe GrapeEntity::Entity do
|
|
|
424
424
|
|
|
425
425
|
it 'ignores the :collection parameter in the source options' do
|
|
426
426
|
module EntitySpec
|
|
427
|
-
class FriendEntity <
|
|
427
|
+
class FriendEntity < Grape::Entity
|
|
428
428
|
root 'friends', 'friend'
|
|
429
429
|
expose :name
|
|
430
430
|
expose :email, :if => { :collection => true }
|
|
@@ -533,12 +533,12 @@ describe GrapeEntity::Entity do
|
|
|
533
533
|
|
|
534
534
|
it 'creates an Entity class when called' do
|
|
535
535
|
subject.should_not be_const_defined :Entity
|
|
536
|
-
subject.send(:include,
|
|
536
|
+
subject.send(:include, Grape::Entity::DSL)
|
|
537
537
|
subject.should be_const_defined :Entity
|
|
538
538
|
end
|
|
539
539
|
|
|
540
540
|
context 'pre-mixed' do
|
|
541
|
-
before{ subject.send(:include,
|
|
541
|
+
before{ subject.send(:include, Grape::Entity::DSL) }
|
|
542
542
|
|
|
543
543
|
it 'is able to define entity traits through DSL' do
|
|
544
544
|
subject.entity do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -2,11 +2,9 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
|
2
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
3
3
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'support'))
|
|
4
4
|
|
|
5
|
-
# $stdout = StringIO.new
|
|
6
|
-
|
|
7
5
|
require 'rubygems'
|
|
8
6
|
require 'bundler'
|
|
7
|
+
|
|
9
8
|
Bundler.require :default, :test
|
|
10
9
|
|
|
11
10
|
require 'pry'
|
|
12
|
-
require 'base64'
|
metadata
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: grape-entity
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease:
|
|
5
|
-
version: 0.
|
|
5
|
+
version: 0.2.0
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- Michael Bleigh
|
|
@@ -11,6 +11,38 @@ bindir: bin
|
|
|
11
11
|
cert_chain: []
|
|
12
12
|
date: 2013-01-13 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
type: :runtime
|
|
16
|
+
prerelease: false
|
|
17
|
+
name: activesupport
|
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
19
|
+
none: false
|
|
20
|
+
requirements:
|
|
21
|
+
- - ! '>='
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: '0'
|
|
24
|
+
requirement: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '0'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
type: :runtime
|
|
32
|
+
prerelease: false
|
|
33
|
+
name: multi_json
|
|
34
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
35
|
+
none: false
|
|
36
|
+
requirements:
|
|
37
|
+
- - ! '>='
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 1.3.2
|
|
40
|
+
requirement: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: 1.3.2
|
|
14
46
|
- !ruby/object:Gem::Dependency
|
|
15
47
|
type: :development
|
|
16
48
|
prerelease: false
|
|
@@ -116,8 +148,7 @@ files:
|
|
|
116
148
|
- lib/grape_entity/version.rb
|
|
117
149
|
- spec/grape_entity/entity_spec.rb
|
|
118
150
|
- spec/spec_helper.rb
|
|
119
|
-
|
|
120
|
-
homepage: https://github.com/intridea/grape
|
|
151
|
+
homepage: https://github.com/agileanimal/grape-entity
|
|
121
152
|
licenses:
|
|
122
153
|
- MIT
|
|
123
154
|
post_install_message:
|
|
@@ -131,7 +162,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
131
162
|
- !ruby/object:Gem::Version
|
|
132
163
|
segments:
|
|
133
164
|
- 0
|
|
134
|
-
hash: -
|
|
165
|
+
hash: -1479047909720369637
|
|
135
166
|
version: '0'
|
|
136
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
168
|
none: false
|
|
@@ -140,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
140
171
|
- !ruby/object:Gem::Version
|
|
141
172
|
segments:
|
|
142
173
|
- 0
|
|
143
|
-
hash: -
|
|
174
|
+
hash: -1479047909720369637
|
|
144
175
|
version: '0'
|
|
145
176
|
requirements: []
|
|
146
177
|
rubyforge_project: grape-entity
|
data/tmp/rspec_guard_result
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|