darstellung 0.0.0 → 0.0.1
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/README.md +179 -0
- data/lib/darstellung.rb +3 -0
- data/lib/darstellung/attribute.rb +79 -0
- data/lib/darstellung/definable.rb +34 -0
- data/lib/darstellung/macros.rb +138 -0
- data/lib/darstellung/registry.rb +85 -0
- data/lib/darstellung/representable.rb +126 -0
- data/lib/darstellung/version.rb +1 -1
- metadata +12 -6
data/README.md
CHANGED
@@ -1,6 +1,185 @@
|
|
1
1
|
Darstellung [](http://travis-ci.org/durran/darstellung) [](https://codeclimate.com/github/durran/darstellung)
|
2
2
|
========
|
3
3
|
|
4
|
+
Darstellung is a simple DSL for defining what should be displayed in
|
5
|
+
resource representations most of the time in API consumption. The
|
6
|
+
library is currently in an experimental phase (pre 1.0.0).
|
7
|
+
|
8
|
+
Usage
|
9
|
+
-----
|
10
|
+
|
11
|
+
Say we have a `UserResource` that is responsible for returning
|
12
|
+
representations of `User` models. With Darstellung, we tell it what
|
13
|
+
fields to display in a "detail" representation and in a "summary"
|
14
|
+
representation:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
class UserResource
|
18
|
+
include Darstellung::Representable
|
19
|
+
|
20
|
+
summary :username
|
21
|
+
|
22
|
+
detail :first_name
|
23
|
+
detail :last_name
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
Then we can initialize a new `UserResource` with a single `User` and ask for
|
28
|
+
the hash representation back:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
resource = UserResource.new(user)
|
32
|
+
resource.detail #=> { version: "none", resource: { first_name: "john", last_name: "doe" }}
|
33
|
+
resource.summary #=> { version: "none", resource: { username: "john" }}
|
34
|
+
```
|
35
|
+
|
36
|
+
If we provide the `UserResource` with an `Enumerable` of `User`s, we can ask
|
37
|
+
for a collection, which returns an array of summary representations for each
|
38
|
+
user in the list.
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
resource = UserResource.new([ user_one, user_two ])
|
42
|
+
resource.collection #=> { version: "none", resource: [{ username: "john" }, { username: "joe" }]}
|
43
|
+
```
|
44
|
+
|
45
|
+
Versioning
|
46
|
+
----------
|
47
|
+
|
48
|
+
Just like any other piece of software, your application's API is a contract
|
49
|
+
for others to use, and changes to this contract should follow a sane and
|
50
|
+
predictable pattern. Darstellung handles this by allowing you to specify versions
|
51
|
+
in which various attributes are displayed in the detail and summary views.
|
52
|
+
Clients can request a specific version of the API and get the expected results
|
53
|
+
back at all times. It is expected that the version numbers follow the
|
54
|
+
Semantic Versioning Specification in order to maintain some consistency.
|
55
|
+
|
56
|
+
Here is a `UserResource` with versioning:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
class UserResource
|
60
|
+
include Darstellung::Representable
|
61
|
+
|
62
|
+
summary :username
|
63
|
+
summary :created_at, from: "1.0.1"
|
64
|
+
|
65
|
+
detail :first_name
|
66
|
+
detail :last_name, from: "1.0.5", to: "2.0.0"
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
If we pass a version to the `detail`, `summary`, and `collection` methods on
|
71
|
+
the resource, we will only get back attributes that fall in line with the
|
72
|
+
version specified:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
resource = UserResource.new(user)
|
76
|
+
resource.detail("1.0.0")
|
77
|
+
#=> { version: "1.0.0", resource: { first_name: "john" }}
|
78
|
+
resource.detail("1.0.5")
|
79
|
+
#=> { version: "1.0.5", resource: { first_name: "john", last_name: "doe" }}
|
80
|
+
|
81
|
+
resource.summary("1.0.0")
|
82
|
+
#=> { version: "1.0.0", resource: { username: "john" }}
|
83
|
+
resource.summary("2.0.0")
|
84
|
+
#=> { version: "2.0.0", resource: { username: "john", created_at: "2012-1-1" }}
|
85
|
+
|
86
|
+
resource = UserResource.new([ user_one, user_two ])
|
87
|
+
resource.collection("2.0.0")
|
88
|
+
# => {
|
89
|
+
# version: "2.0.0",
|
90
|
+
# resource: [
|
91
|
+
# { username: "john", created_at: "2012-1-1" },
|
92
|
+
# { username: "joe", created_at: "2012-1-2" }
|
93
|
+
# ]
|
94
|
+
# }
|
95
|
+
```
|
96
|
+
|
97
|
+
Reasoning
|
98
|
+
---------
|
99
|
+
|
100
|
+
This is simply a case of SRP and maintainability. While some may argue against
|
101
|
+
SRP in Rails being overkill, I disagree and will simply show examples showing
|
102
|
+
the choices and the developer can decide for themselves. Although my personal
|
103
|
+
preference would be to use Sinatra or Webmachine in these API cases, there's a good
|
104
|
+
[blog post](http://blog.gomiso.com/2011/05/16/if-youre-using-to_json-youre-doing-it-wrong)
|
105
|
+
from the authors of RABL discussing how this gets out of hand quickly in Rails.
|
106
|
+
|
107
|
+
Speed
|
108
|
+
-----
|
109
|
+
|
110
|
+
Bypassing Active Model's serialization is going to provide you with a huge
|
111
|
+
performance benefit. Let's look at a basic Mongoid model:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
class Band
|
115
|
+
include Mongoid::Document
|
116
|
+
field :description, type: String
|
117
|
+
field :formed_on, type: Date
|
118
|
+
field :location, type: String
|
119
|
+
field :genres, type: Array, default: []
|
120
|
+
field :name, type: String
|
121
|
+
field :similarities, type: Array, default: []
|
122
|
+
field :sounds, type: Array, default: []
|
123
|
+
field :website, type: String
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
Now let's serialize the model to json (using YAJL), 100,000 times:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
bench.report do
|
131
|
+
100_000.times do
|
132
|
+
band.to_json
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
```
|
137
|
+
user system total real
|
138
|
+
37.150000 0.100000 37.250000 ( 37.250232)
|
139
|
+
```
|
140
|
+
|
141
|
+
When we create a resource for the `Band` with Darstellung and serialize it
|
142
|
+
that way, we get some serious improvement (over 6x faster).
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
class BandResource
|
146
|
+
include Darstellung::Representable
|
147
|
+
detail :description
|
148
|
+
detail :formed_on
|
149
|
+
detail :location
|
150
|
+
detail :genres
|
151
|
+
detail :name
|
152
|
+
detail :similarities
|
153
|
+
detail :sounds
|
154
|
+
detail :website
|
155
|
+
end
|
156
|
+
|
157
|
+
bench.report do
|
158
|
+
100_000.times do
|
159
|
+
BandResource.new(band).detail.to_json
|
160
|
+
end
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
```
|
165
|
+
user system total real
|
166
|
+
6.270000 0.010000 6.280000 ( 6.277472)
|
167
|
+
```
|
168
|
+
|
169
|
+
The results are drastically different in the simplest of examples, and expect
|
170
|
+
another order of magnitude gain when including relations.
|
171
|
+
|
172
|
+
Serialization
|
173
|
+
-------------
|
174
|
+
|
175
|
+
Darstellung does not deal in serialization at all. It's only purpose is to
|
176
|
+
provide hash representations of your API resources for specific versions. It's
|
177
|
+
up to you to call `to_json` or `to_xml` on them, using whatever serialization
|
178
|
+
library you want.
|
179
|
+
|
180
|
+
License
|
181
|
+
-------
|
182
|
+
|
4
183
|
Copyright (c) 2012 Durran Jordan
|
5
184
|
|
6
185
|
Permission is hereby granted, free of charge, to any person obtaining
|
data/lib/darstellung.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Darstellung
|
3
|
+
|
4
|
+
# An attribute is any field that can be represented. This class provides
|
5
|
+
# extra behavior around when and how these fields get represented.
|
6
|
+
#
|
7
|
+
# @since 0.0.0
|
8
|
+
class Attribute
|
9
|
+
|
10
|
+
# @attribute [r] name The name of the attribute.
|
11
|
+
# @attribute [r] options The attribute options.
|
12
|
+
# @attribute [r] block The block to call to get the value.
|
13
|
+
attr_reader :name, :options, :block
|
14
|
+
|
15
|
+
# Determines if the attribute is displayable in the representation given
|
16
|
+
# the provided version.
|
17
|
+
#
|
18
|
+
# @example Is the attribute displayable?
|
19
|
+
# attribute.displayable?("1.0.0")
|
20
|
+
#
|
21
|
+
# @note This method assumes that API versions are following the Semantic
|
22
|
+
# Versioning Specificaion, and does its comparison of version strings
|
23
|
+
# with this in mind.
|
24
|
+
#
|
25
|
+
# @param [ String ] version The version number.
|
26
|
+
#
|
27
|
+
# @return [ true, false ] If the attribute is displayable.
|
28
|
+
#
|
29
|
+
# @see http://semver.org/
|
30
|
+
#
|
31
|
+
# @since 0.0.0
|
32
|
+
def displayable?(version)
|
33
|
+
return true unless version
|
34
|
+
from <= version && version <= to(version)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Initialize the new attribute.
|
38
|
+
#
|
39
|
+
# @example Initialize the new attribute.
|
40
|
+
# Darstellung::Attribute.new(:name, version: "1.0.1")
|
41
|
+
#
|
42
|
+
# @param [ Symbol ] name The name of the attribute.
|
43
|
+
# @param [ Hash ] options The attribute options.
|
44
|
+
#
|
45
|
+
# @option options [ String ] :from The version the attribute is available
|
46
|
+
# from.
|
47
|
+
# @option options [ String ] :to The version the attribute is available
|
48
|
+
# to.
|
49
|
+
#
|
50
|
+
# @since 0.0.0
|
51
|
+
def initialize(name, options = {}, &block)
|
52
|
+
@name, @options, @block = name, options, block
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the value for the attribute from the provided resource.
|
56
|
+
#
|
57
|
+
# @example Get the value for the attribute.
|
58
|
+
# attribute.value(user)
|
59
|
+
#
|
60
|
+
# @param [ Object ] resource The resource to execute on.
|
61
|
+
#
|
62
|
+
# @return [ Object ] The value of the resource.
|
63
|
+
#
|
64
|
+
# @since 0.0.0
|
65
|
+
def value(resource)
|
66
|
+
block ? block.call(resource) : resource.__send__(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def from
|
72
|
+
options[:from] || "0.0.0"
|
73
|
+
end
|
74
|
+
|
75
|
+
def to(version)
|
76
|
+
options[:to] || "#{version}+"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Darstellung
|
3
|
+
|
4
|
+
# This module contains access from the instance level to the attribute
|
5
|
+
# definitions provided by the macros.
|
6
|
+
#
|
7
|
+
# @since 0.0.0
|
8
|
+
module Definable
|
9
|
+
|
10
|
+
# Get all the attributes that are used in the detail representation.
|
11
|
+
#
|
12
|
+
# @example Get all the detail attributes fields.
|
13
|
+
# user_resource.detail_attributes
|
14
|
+
#
|
15
|
+
# @return [ Hash ] The name/attribute pairs.
|
16
|
+
#
|
17
|
+
# @since 0.0.0
|
18
|
+
def detail_attributes
|
19
|
+
self.class.detail_attributes
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get all the attributes that are used in the summary representation.
|
23
|
+
#
|
24
|
+
# @example Get all the summary attributes fields.
|
25
|
+
# user_resource.summary_attributes
|
26
|
+
#
|
27
|
+
# @return [ Hash ] The name/attribute pairs.
|
28
|
+
#
|
29
|
+
# @since 0.0.0
|
30
|
+
def summary_attributes
|
31
|
+
self.class.summary_attributes
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "darstellung/registry"
|
3
|
+
|
4
|
+
module Darstellung
|
5
|
+
|
6
|
+
# This module provides all the class level macros for defining
|
7
|
+
# representations.
|
8
|
+
#
|
9
|
+
# @since 0.0.0
|
10
|
+
module Macros
|
11
|
+
|
12
|
+
# Defines an attribute to be displayed in the detail representation of the
|
13
|
+
# resource.
|
14
|
+
#
|
15
|
+
# @example Display the name field in the detail display.
|
16
|
+
# class UserResource
|
17
|
+
# include Darstellung::Representable
|
18
|
+
# detail :name
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# @example Display the name field only from version 1.0.0
|
22
|
+
# class UserResource
|
23
|
+
# include Darstellung::Representable
|
24
|
+
# detail :name, from: "1.0.0"
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# @example Display the name field only from version 1.0.0 - 1.1.0
|
28
|
+
# class UserResource
|
29
|
+
# include Darstellung::Representable
|
30
|
+
# detail :name, from: "1.0.0", to: "1.1.0"
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @example Display the name field as a custom representation.
|
34
|
+
# class UserResource
|
35
|
+
# include Darstellung::Representable
|
36
|
+
#
|
37
|
+
# detail :name do |user|
|
38
|
+
# user.full_name
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# @param [ Symbol ] name The name of the attribute.
|
43
|
+
# @param [ Hash ] options The attribute options.
|
44
|
+
#
|
45
|
+
# @option options [ String ] :from The version the field is available from.
|
46
|
+
# @option options [ String ] :to The version the field is available to.
|
47
|
+
#
|
48
|
+
# @return [ Attribute ] The attribute object for the field.
|
49
|
+
#
|
50
|
+
# @since 0.0.0
|
51
|
+
def detail(name, options = {}, &block)
|
52
|
+
create_attribute(name, detail_attributes, options, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get all the attributes that are used in the detail representation.
|
56
|
+
#
|
57
|
+
# @example Get all the detail attributes fields.
|
58
|
+
# class UserResource
|
59
|
+
# include Darstellung::Representable
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# UserResource.detail_attributes
|
63
|
+
#
|
64
|
+
# @return [ Hash ] The name/attribute pairs.
|
65
|
+
#
|
66
|
+
# @since 0.0.0
|
67
|
+
def detail_attributes
|
68
|
+
@detail_attributes ||= {}
|
69
|
+
end
|
70
|
+
|
71
|
+
# Defines an attribute to be displayed in the summary representation of the
|
72
|
+
# resource.
|
73
|
+
#
|
74
|
+
# @example Display the name field in the summary display.
|
75
|
+
# class UserResource
|
76
|
+
# include Darstellung::Representable
|
77
|
+
# summary :name
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# @example Display the name field only from version 1.0.0
|
81
|
+
# class UserResource
|
82
|
+
# include Darstellung::Representable
|
83
|
+
# summary :name, from: "1.0.0"
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# @example Display the name field only from version 1.0.0 - 1.1.0
|
87
|
+
# class UserResource
|
88
|
+
# include Darstellung::Representable
|
89
|
+
# summary :name, from: "1.0.0", to: "1.1.0"
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# @example Display the name field as a custom representation.
|
93
|
+
# class UserResource
|
94
|
+
# include Darstellung::Representable
|
95
|
+
#
|
96
|
+
# summary :name do |user|
|
97
|
+
# user.full_name
|
98
|
+
# end
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# @param [ Symbol ] name The name of the attribute.
|
102
|
+
# @param [ Hash ] options The attribute options.
|
103
|
+
#
|
104
|
+
# @option options [ String ] :from The version the field is available from.
|
105
|
+
# @option options [ String ] :to The version the field is available to.
|
106
|
+
#
|
107
|
+
# @return [ Attribute ] The attribute object for the field.
|
108
|
+
#
|
109
|
+
# @since 0.0.0
|
110
|
+
def summary(name, options = {}, &block)
|
111
|
+
create_attribute(name, summary_attributes, options, &block)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Get all the attributes that are used in the summary representation.
|
115
|
+
#
|
116
|
+
# @example Get all the summary attributes fields.
|
117
|
+
# class UserResource
|
118
|
+
# include Darstellung::Representable
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# UserResource.summary_attributes
|
122
|
+
#
|
123
|
+
# @return [ Hash ] The name/attribute pairs.
|
124
|
+
#
|
125
|
+
# @since 0.0.0
|
126
|
+
def summary_attributes
|
127
|
+
@summary_attributes ||= {}
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def create_attribute(name, attributes, options = {}, &block)
|
133
|
+
normalized = name.to_sym
|
134
|
+
attributes[normalized] = Attribute.new(normalized, options, &block)
|
135
|
+
Registry.register(options)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Darstellung
|
3
|
+
|
4
|
+
# Contains information on all versions in the API that have been registered.
|
5
|
+
# This is determined from the various "from" and "to" options provided to the
|
6
|
+
# macros.
|
7
|
+
#
|
8
|
+
# @since 0.0.0
|
9
|
+
module Registry
|
10
|
+
extend self
|
11
|
+
|
12
|
+
# Register a set of options provided to a representation macro.
|
13
|
+
#
|
14
|
+
# @example Register the options.
|
15
|
+
# Dartellung::Registry.register(from: "1.0.0", to: "2.0.0")
|
16
|
+
#
|
17
|
+
# @note This takes the "from" and "to" options and registers them as
|
18
|
+
# official API versions.
|
19
|
+
#
|
20
|
+
# @param [ Hash ] options The macro options.
|
21
|
+
#
|
22
|
+
# @return [ Array<String> ] All the registered versions.
|
23
|
+
#
|
24
|
+
# @since 0.0.0
|
25
|
+
def register(options)
|
26
|
+
from, to = options[:from], options[:to]
|
27
|
+
registered_versions[from] = true if from
|
28
|
+
registered_versions[to] = true if to
|
29
|
+
versions
|
30
|
+
end
|
31
|
+
|
32
|
+
# Is a particular version registered with the API?
|
33
|
+
#
|
34
|
+
# @example Check if the version is registered.
|
35
|
+
# Darstellung::Registry.registered?("2.1.5")
|
36
|
+
#
|
37
|
+
# @param [ String ] version The version to check.
|
38
|
+
#
|
39
|
+
# @return [ true, false ] If the version is registered.
|
40
|
+
#
|
41
|
+
# @since 0.0.0
|
42
|
+
def registered?(version)
|
43
|
+
registered_versions[version]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Validate that the provided version is registered.
|
47
|
+
#
|
48
|
+
# @example Validate the version.
|
49
|
+
# Darstellung::Registry.validate!("1.0.5")
|
50
|
+
#
|
51
|
+
# @param [ String ] version The version to validate.
|
52
|
+
#
|
53
|
+
# @raise [ NotRegistered ] If the version is not registered.
|
54
|
+
#
|
55
|
+
# @since 0.0.0
|
56
|
+
def validate!(version)
|
57
|
+
unless version.nil? || registered?(version)
|
58
|
+
raise NotRegistered.new("#{version} is not a valid API version.")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Provides a list of all registered versions in the API.
|
63
|
+
#
|
64
|
+
# @example List all versions.
|
65
|
+
# Darstellung::Registry.versions
|
66
|
+
#
|
67
|
+
# @return [ Array<String> ] All the registered versions.
|
68
|
+
#
|
69
|
+
# @since 0.0.0
|
70
|
+
def versions
|
71
|
+
registered_versions.keys
|
72
|
+
end
|
73
|
+
|
74
|
+
# Raised when validating a version that does not exist in the registry.
|
75
|
+
#
|
76
|
+
# @since 0.0.0
|
77
|
+
class NotRegistered < Exception; end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def registered_versions
|
82
|
+
@registered_versions ||= {}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "darstellung/attribute"
|
3
|
+
require "darstellung/definable"
|
4
|
+
require "darstellung/macros"
|
5
|
+
|
6
|
+
module Darstellung
|
7
|
+
|
8
|
+
# This module is included into resources that need a summary and detail view
|
9
|
+
# for display in APIs. Summary views are for display in lists, detail views
|
10
|
+
# are generally show actions.
|
11
|
+
#
|
12
|
+
# @since 0.0.0
|
13
|
+
module Representable
|
14
|
+
include Definable
|
15
|
+
|
16
|
+
# @attribute [r] resource The resource being represented.
|
17
|
+
attr_reader :resource
|
18
|
+
|
19
|
+
# Gets the collection view for a specific version of the resource. If no
|
20
|
+
# version is provided then we assume from "0.0.0" which will render
|
21
|
+
# attributes available in all versions of the API.
|
22
|
+
#
|
23
|
+
# @example Get the collection representation.
|
24
|
+
# user_resource.collection("1.0.1")
|
25
|
+
#
|
26
|
+
# @note The collection representation is a list of summary representations.
|
27
|
+
#
|
28
|
+
# @param [ String ] version The version to get of the resource.
|
29
|
+
#
|
30
|
+
# @return [ Hash ] The collection representation of the resource.
|
31
|
+
#
|
32
|
+
# @since 0.0.0
|
33
|
+
def collection(version = nil)
|
34
|
+
representation(version, multiple(summary_attributes, version))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Gets the detail view for a specific version of the resource. If no
|
38
|
+
# version is provided then we assume from "0.0.0" which will render
|
39
|
+
# attributes available in all versions of the API.
|
40
|
+
#
|
41
|
+
# @example Get the detail representation.
|
42
|
+
# user_resource.detail("1.0.1")
|
43
|
+
#
|
44
|
+
# @param [ String ] version The version to get of the resource.
|
45
|
+
#
|
46
|
+
# @return [ Hash ] The detail representation of the resource.
|
47
|
+
#
|
48
|
+
# @since 0.0.0
|
49
|
+
def detail(version = nil)
|
50
|
+
representation(version, single(detail_attributes, resource, version))
|
51
|
+
end
|
52
|
+
|
53
|
+
# Initialize the new representation with the provided resource.
|
54
|
+
#
|
55
|
+
# @example Initialize the representation.
|
56
|
+
# class UserResource
|
57
|
+
# include Darstellung::Representable
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# UserResource.new(user)
|
61
|
+
#
|
62
|
+
# @param [ Object ] resource The resource to be represented.
|
63
|
+
#
|
64
|
+
# @since 0.0.0
|
65
|
+
def initialize(resource)
|
66
|
+
@resource = resource
|
67
|
+
end
|
68
|
+
|
69
|
+
# Gets the summary view for a specific version of the resource. If no
|
70
|
+
# version is provided then we assume from "0.0.0" which will render
|
71
|
+
# attributes available in all versions of the API.
|
72
|
+
#
|
73
|
+
# @example Get the summary representation.
|
74
|
+
# user_resource.summary("1.0.1")
|
75
|
+
#
|
76
|
+
# @param [ String ] version The version to get of the resource.
|
77
|
+
#
|
78
|
+
# @return [ Hash ] The summary representation of the resource.
|
79
|
+
#
|
80
|
+
# @since 0.0.0
|
81
|
+
def summary(version = nil)
|
82
|
+
representation(version, single(summary_attributes, resource, version))
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def multiple(attributes, version, representation = [])
|
88
|
+
resource.each do |object|
|
89
|
+
representation.push(single(attributes, object, version))
|
90
|
+
end
|
91
|
+
representation
|
92
|
+
end
|
93
|
+
|
94
|
+
def representation(version, resource)
|
95
|
+
Registry.validate!(version)
|
96
|
+
Hash[ version: version || "none", resource: resource ]
|
97
|
+
end
|
98
|
+
|
99
|
+
def single(attributes, object, version, representation = {})
|
100
|
+
attributes.each do |name, attribute|
|
101
|
+
if attribute.displayable?(version)
|
102
|
+
representation[name] = attribute.value(object)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
representation
|
106
|
+
end
|
107
|
+
|
108
|
+
class << self
|
109
|
+
|
110
|
+
# Including the module will inject the necessary macros into the base
|
111
|
+
# class.
|
112
|
+
#
|
113
|
+
# @exampe Include the Representable module.
|
114
|
+
# class UserResource
|
115
|
+
# include Darstellung::Representable
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# @param [ Class ] klass The class including the module.
|
119
|
+
#
|
120
|
+
# @since 0.0.0
|
121
|
+
def included(klass)
|
122
|
+
klass.extend(Macros)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/darstellung/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: darstellung
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,16 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-25 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description:
|
14
|
+
description: Simple and fast representations for APIs in Ruby
|
15
15
|
email:
|
16
16
|
- durran@gmail.com
|
17
17
|
executables: []
|
18
18
|
extensions: []
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
+
- lib/darstellung/attribute.rb
|
22
|
+
- lib/darstellung/definable.rb
|
23
|
+
- lib/darstellung/macros.rb
|
24
|
+
- lib/darstellung/registry.rb
|
25
|
+
- lib/darstellung/representable.rb
|
21
26
|
- lib/darstellung/version.rb
|
27
|
+
- lib/darstellung.rb
|
22
28
|
- README.md
|
23
29
|
- LICENSE
|
24
30
|
- Rakefile
|
@@ -36,7 +42,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
42
|
version: '0'
|
37
43
|
segments:
|
38
44
|
- 0
|
39
|
-
hash:
|
45
|
+
hash: 220129650249248843
|
40
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
47
|
none: false
|
42
48
|
requirements:
|
@@ -45,11 +51,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
51
|
version: '0'
|
46
52
|
segments:
|
47
53
|
- 0
|
48
|
-
hash:
|
54
|
+
hash: 220129650249248843
|
49
55
|
requirements: []
|
50
56
|
rubyforge_project:
|
51
57
|
rubygems_version: 1.8.24
|
52
58
|
signing_key:
|
53
59
|
specification_version: 3
|
54
|
-
summary:
|
60
|
+
summary: Simple and fast representations for APIs in Ruby
|
55
61
|
test_files: []
|