rabl 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +44 -24
- data/TODO +7 -0
- data/examples/base.json.rabl +8 -0
- data/examples/demo.json.rabl +42 -0
- data/examples/inherited.json.rabl +11 -0
- data/lib/rabl/builder.rb +1 -1
- data/lib/rabl/engine.rb +3 -3
- data/lib/rabl/version.rb +1 -1
- metadata +12 -6
data/README.md
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# RABL #
|
2
2
|
|
3
|
-
RABL is a ruby templating system for Rails that takes a
|
3
|
+
RABL is a ruby templating system for Rails and [Padrino](http://padrinorb.com) that takes a new approach to generating JSON and other formats. Rather than using the ActiveRecord 'to_json', I generally find myself wanting a more expressive and powerful system for generating my APIs. This is especially important when the json representation is complex or doesn't match the exact schema defined in the database itself.
|
4
4
|
|
5
5
|
There were a few things in particular I wanted to do easily:
|
6
6
|
|
7
|
-
* Create arbitrary nodes named based on combining data in
|
8
|
-
* Include nodes only if a condition is met
|
9
|
-
* Pass arguments to methods and store the result as a node
|
10
|
-
*
|
11
|
-
* Easily
|
7
|
+
* Create arbitrary nodes named based on combining data in an object
|
8
|
+
* Include nodes only if a certain condition is met
|
9
|
+
* Pass arguments to methods and store the result as a child node
|
10
|
+
* Partial templates and inheritance to reduce code duplication
|
11
|
+
* Easily renaming attributes from their name in the model
|
12
|
+
* Simple way to append attributes from a child into the parent
|
12
13
|
|
13
|
-
|
14
|
+
The list goes on. Anyone who has used the 'to_json' approach used in ActiveRecord for generating a json response has felt the pain of the extremely restrictive system. RABL is a general templating system created to solve all of those problems. When I created RABL, I wanted a simple, expressive DRY ruby DSL for defining JSON responses for my APIs.
|
14
15
|
|
15
16
|
## Installation ##
|
16
17
|
|
@@ -25,17 +26,17 @@ or add to your Gemfile:
|
|
25
26
|
|
26
27
|
and run `bundle install` to install the dependency.
|
27
28
|
|
28
|
-
If you are using Rails 2.X or Padrino, RABL works
|
29
|
+
If you are using Rails 2.X or Padrino, RABL works without configuration. With Sinatra, or any other tilt-based framework, simply register:
|
29
30
|
|
30
31
|
Rabl.register!
|
31
32
|
|
32
|
-
and RABL will be initialized.
|
33
|
+
and RABL will be initialized and ready for use.
|
33
34
|
|
34
35
|
## Usage ##
|
35
36
|
|
36
37
|
### Object Assignment ###
|
37
38
|
|
38
|
-
To declare the data object
|
39
|
+
To declare the data object for use in the template:
|
39
40
|
|
40
41
|
# app/views/users/show.json.rabl
|
41
42
|
object @user
|
@@ -48,40 +49,43 @@ and this will be used as the default data object for the rendering.
|
|
48
49
|
|
49
50
|
### Attributes ###
|
50
51
|
|
51
|
-
Basic usage of the templater:
|
52
|
+
Basic usage of the templater to define a few simple attributes for the response:
|
52
53
|
|
53
54
|
# app/views/users/show.json.rabl
|
54
55
|
attributes :id, :foo, :bar
|
55
56
|
|
56
|
-
or with aliased attributes:
|
57
|
+
or use with aliased attributes:
|
57
58
|
|
58
59
|
# Take the value of model attribute `foo` and name the node `bar`
|
59
60
|
# { bar : 5 }
|
60
61
|
attribute :foo => :bar
|
61
62
|
|
62
|
-
or multiple aliased attributes:
|
63
|
+
or even multiple aliased attributes:
|
63
64
|
|
64
65
|
# { baz : <bar value>, animal : <dog value> }
|
65
66
|
attributes :bar => :baz, :dog => :animal
|
66
67
|
|
67
68
|
### Child Nodes ###
|
68
69
|
|
69
|
-
You can also add
|
70
|
+
You can also add child nodes from an arbitrary source:
|
70
71
|
|
71
72
|
child @posts => :foobar do
|
72
73
|
attributes :id, :title
|
73
74
|
end
|
74
75
|
|
75
|
-
or use existing model associations:
|
76
|
+
or simply use existing model associations:
|
76
77
|
|
78
|
+
# Renders all the 'posts' association
|
79
|
+
# from the model into a node called 'foobar'
|
77
80
|
child :posts => :foobar do
|
78
81
|
attributes :id, :title
|
79
82
|
end
|
80
83
|
|
81
|
-
###
|
84
|
+
### Gluing Attributes ###
|
82
85
|
|
83
|
-
You can also append attributes to the root node:
|
86
|
+
You can also append child attributes back to the root node:
|
84
87
|
|
88
|
+
# Appends post_id and post_name to parent json object
|
85
89
|
glue @post do
|
86
90
|
attributes :id => :post_id, :name => :post_name
|
87
91
|
end
|
@@ -90,18 +94,18 @@ Use glue to add additional attributes to the parent object.
|
|
90
94
|
|
91
95
|
### Custom Nodes ###
|
92
96
|
|
93
|
-
This will generate a json response
|
97
|
+
This will generate a json response based on the result of the code block:
|
94
98
|
|
95
99
|
# app/views/users/show.json.rabl
|
96
100
|
code :full_name do |u|
|
97
101
|
u.first_name + " " + u.last_name
|
98
102
|
end
|
99
103
|
|
100
|
-
You can use custom "code" nodes to create flexible representations of a value utilizing data from the model.
|
104
|
+
You can use custom "code" nodes to create flexible representations of a value utilizing all the data from the model.
|
101
105
|
|
102
106
|
### Partials ###
|
103
107
|
|
104
|
-
Often you need to access sub-objects in order to construct your own custom nodes for more complex associations. You can get access to the
|
108
|
+
Often you need to access sub-objects in order to construct your own custom nodes for more complex associations. You can get access to the rabl representation of another object with:
|
105
109
|
|
106
110
|
code :location do
|
107
111
|
{ :city => @city, :address => partial("web/users/address", :object => @address) }
|
@@ -113,11 +117,11 @@ or an object associated to the parent model:
|
|
113
117
|
{ :city => m.city, :address => partial("web/users/address", :object => m.address) }
|
114
118
|
end
|
115
119
|
|
116
|
-
You can use
|
120
|
+
You can use this method to construct arbitrarily complex nodes for your APIs.
|
117
121
|
|
118
122
|
### Inheritance ###
|
119
123
|
|
120
|
-
Another common
|
124
|
+
Another common issue of many template builders is unnecessary code redundancy. Typically many representations of an object across multiple endpoints share common attributes or nodes. The nodes for a 'post' object are probably the same or similar in most references throughout the various endpoints.
|
121
125
|
|
122
126
|
RABL has the ability to extend other "base" rabl templates and additional attributes:
|
123
127
|
|
@@ -128,7 +132,7 @@ RABL has the ability to extend other "base" rabl templates and additional attrib
|
|
128
132
|
m.age > 21
|
129
133
|
end
|
130
134
|
|
131
|
-
You can also extend other rabl templates
|
135
|
+
You can also extend other rabl templates while constructing child nodes to reduce duplication:
|
132
136
|
|
133
137
|
# app/views/users/show.json.rabl
|
134
138
|
child @address do
|
@@ -139,4 +143,20 @@ Using partials and inheritance can significantly reduce code duplication in your
|
|
139
143
|
|
140
144
|
## Issues ##
|
141
145
|
|
142
|
-
* I am sloppy and once again failed to unit test this. Don't use it in production until I do obviously.
|
146
|
+
* I am sloppy and once again failed to unit test this. Don't use it in production until I do obviously.
|
147
|
+
* No support for Rails 3
|
148
|
+
|
149
|
+
## Authors and Contributors ##
|
150
|
+
|
151
|
+
* [Nathan Esquenazi](https://github.com/nesquena) - Creator of the project
|
152
|
+
* [Arthur Chiu](https://github.com/achiu) - Core Maintainer, Riot Testing Guru
|
153
|
+
|
154
|
+
## Inspirations ##
|
155
|
+
|
156
|
+
There are a few excellent libraries that helped inspire RABL and they are listed below:
|
157
|
+
|
158
|
+
* [Tequila](https://github.com/inem/tequila)
|
159
|
+
* [JSON Builder](https://github.com/dewski/json_builder)
|
160
|
+
* [Argonaut](https://github.com/jbr/argonaut)
|
161
|
+
|
162
|
+
Thanks again for all of these great projects.
|
data/TODO
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Use the @media object set in route
|
2
|
+
object @media
|
3
|
+
|
4
|
+
# Include these three attributes
|
5
|
+
attributes :title, :kind, :id
|
6
|
+
# Rename 'studio' to be the 'company' node
|
7
|
+
attributes :studio => :company
|
8
|
+
|
9
|
+
# Arbitrary code blocks can be defined
|
10
|
+
# Creates a 'release_year' node
|
11
|
+
code :release_year do |m|
|
12
|
+
date = m.release_date || m.series_start
|
13
|
+
date.try(:year)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Creates a node 'users' with an array of the nested users for media
|
17
|
+
# Block is the same rabl syntax for the sub object
|
18
|
+
child @users do
|
19
|
+
attributes :full_name, :first_name
|
20
|
+
end
|
21
|
+
|
22
|
+
# Uses the associations of the parent media object
|
23
|
+
# Rename 'users' association to 'people' node
|
24
|
+
child :users => :people do
|
25
|
+
attributes :full_name, :first_name
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates the "actor" association as a 'user' node
|
29
|
+
# Use the information from another rabl template to describe the representation
|
30
|
+
child :actor => :user do
|
31
|
+
extends "users/simple"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Append attributes to the root node with prefixed names
|
35
|
+
glue @users.first do
|
36
|
+
attributes :full_name => :user_full_name, :first_name => :user_first_name
|
37
|
+
end
|
38
|
+
|
39
|
+
# Render an arbitrary hash with a partial rabl json as one of the keys
|
40
|
+
code :topics do |m|
|
41
|
+
{ :fake => partial("media/user", :object => @users.first), :raw => @users.first }
|
42
|
+
end
|
data/lib/rabl/builder.rb
CHANGED
@@ -77,7 +77,7 @@ module Rabl
|
|
77
77
|
# Extends an existing rabl template with additional attributes in the block
|
78
78
|
# extends("users/show") { attribute :full_name }
|
79
79
|
def extends(file, options={}, &block)
|
80
|
-
options = options.merge
|
80
|
+
options = options.merge(:object => @_object)
|
81
81
|
result = @options[:engine].partial(file, options, &block)
|
82
82
|
@_result.merge!(result)
|
83
83
|
end
|
data/lib/rabl/engine.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Rabl
|
2
2
|
class Engine
|
3
3
|
# Constructs a new ejs engine based on given vars, handler and declarations
|
4
|
-
# Rabl::Engine.new("...source...", { :format => "xml" })
|
4
|
+
# Rabl::Engine.new("...source...", { :format => "xml", :root => true, :view_path => "/path/to/views" })
|
5
5
|
def initialize(source, options={})
|
6
6
|
@_source = source
|
7
7
|
@_options = options.reverse_merge(:format => "json")
|
@@ -13,7 +13,7 @@ module Rabl
|
|
13
13
|
@_locals = locals
|
14
14
|
@_scope = scope
|
15
15
|
@_options = @_options.merge(:scope => @_scope, :locals => @_locals, :engine => self)
|
16
|
-
self.copy_instance_variables_from(@_scope, [:@assigns, :@helpers])
|
16
|
+
self.copy_instance_variables_from(@_scope, [:@assigns, :@helpers])
|
17
17
|
@_object = locals[:object] || self.default_object
|
18
18
|
instance_eval(@_source) if @_source.present?
|
19
19
|
instance_eval(&block) if block_given?
|
@@ -118,7 +118,7 @@ module Rabl
|
|
118
118
|
def fetch_source(file)
|
119
119
|
root_path = Rails.root if defined?(Rails)
|
120
120
|
root_path = Padrino.root if defined?(Padrino)
|
121
|
-
view_path = File.join(root_path, "app/views/")
|
121
|
+
view_path = @_options[:view_path] || File.join(root_path, "app/views/")
|
122
122
|
file_path = Dir[File.join(view_path, file + "*.rabl")].first
|
123
123
|
File.read(file_path) if file_path
|
124
124
|
end
|
data/lib/rabl/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rabl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Nathan Esquenazi
|
@@ -15,7 +15,8 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-04-12 00:00:00
|
18
|
+
date: 2011-04-12 00:00:00 -07:00
|
19
|
+
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: riot
|
@@ -63,6 +64,10 @@ files:
|
|
63
64
|
- Gemfile
|
64
65
|
- README.md
|
65
66
|
- Rakefile
|
67
|
+
- TODO
|
68
|
+
- examples/base.json.rabl
|
69
|
+
- examples/demo.json.rabl
|
70
|
+
- examples/inherited.json.rabl
|
66
71
|
- lib/rabl.rb
|
67
72
|
- lib/rabl/builder.rb
|
68
73
|
- lib/rabl/engine.rb
|
@@ -75,6 +80,7 @@ files:
|
|
75
80
|
- test/engine_test.rb
|
76
81
|
- test/template_test.rb
|
77
82
|
- test/teststrap.rb
|
83
|
+
has_rdoc: true
|
78
84
|
homepage: https://github.com/nesquena/rabl
|
79
85
|
licenses: []
|
80
86
|
|
@@ -104,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
110
|
requirements: []
|
105
111
|
|
106
112
|
rubyforge_project: rabl
|
107
|
-
rubygems_version: 1.7
|
113
|
+
rubygems_version: 1.3.7
|
108
114
|
signing_key:
|
109
115
|
specification_version: 3
|
110
116
|
summary: General ruby templating for json or xml
|