darstellung 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://secure.travis-ci.org/durran/darstellung.png?branch=master&.png)](http://travis-ci.org/durran/darstellung) [![Code Climate](https://codeclimate.com/badge.png)](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: []
|