rabl 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -8
- data/lib/rabl.rb +4 -3
- data/lib/rabl/builder.rb +2 -3
- data/lib/rabl/engine.rb +24 -6
- data/lib/rabl/template.rb +57 -12
- data/lib/rabl/version.rb +1 -1
- metadata +3 -4
- data/lib/rabl/register.rb +0 -20
data/README.md
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
# RABL #
|
2
2
|
|
3
|
-
RABL (Ruby API Builder Language) is a
|
3
|
+
RABL (Ruby API Builder Language) is a Rails and [Padrino](http://padrinorb.com) ruby templating system for generating JSON and XML. When using the ActiveRecord 'to_json' method, I tend to quickly find myself wanting a more expressive and powerful system for generating APIs. This is especially frustrating when the json representation is complex or doesn't match the exact schema defined in the database itself.
|
4
4
|
|
5
|
-
|
5
|
+
I wanted a simple, and flexible system for generating APIs. In particular, I wanted to easily:
|
6
6
|
|
7
7
|
* Create arbitrary nodes named based on combining data in an object
|
8
|
-
* Include nodes only if a certain condition is met
|
9
8
|
* Pass arguments to methods and store the result as a child node
|
10
9
|
* Partial templates and inheritance to reduce code duplication
|
11
10
|
* Easily renaming attributes from their name in the model
|
12
11
|
* Simple way to append attributes from a child into the parent
|
12
|
+
* Include nodes only if a certain condition is met
|
13
13
|
|
14
|
-
|
14
|
+
Anyone who has tried the 'to_json' method used in ActiveRecord for generating a json response has felt the pain of this restrictive approach. RABL is a general templating system created to solve all of those problems.
|
15
15
|
|
16
16
|
## Installation ##
|
17
17
|
|
18
|
-
Install as a gem:
|
18
|
+
Install RABL as a gem:
|
19
19
|
|
20
20
|
gem install rabl
|
21
21
|
|
@@ -26,7 +26,9 @@ or add to your Gemfile:
|
|
26
26
|
|
27
27
|
and run `bundle install` to install the dependency.
|
28
28
|
|
29
|
-
If you are using Rails 2.X or Padrino
|
29
|
+
If you are using **Rails 2.X, Rails 3 or Padrino**, RABL works without configuration.
|
30
|
+
|
31
|
+
With Sinatra, or any other tilt-based framework, simply register:
|
30
32
|
|
31
33
|
Rabl.register!
|
32
34
|
|
@@ -153,11 +155,9 @@ Using partials and inheritance can significantly reduce code duplication in your
|
|
153
155
|
Check out the [Issues](https://github.com/nesquena/rabl/issues) tab for a full list:
|
154
156
|
|
155
157
|
* I am sloppy and failed to unit test this as I cobbled it together. Don't use it in production until I do, for now this is a fun experiment.
|
156
|
-
* No support for Rails 3 yet, need a Railstie
|
157
158
|
* No configuration options yet for how to create the json (root nodes) :(
|
158
159
|
* Better Tilt template support (precompiling templates)
|
159
160
|
* Benchmarks and performance optimizations
|
160
|
-
* XML Support and potentially others
|
161
161
|
|
162
162
|
## Authors and Contributors ##
|
163
163
|
|
data/lib/rabl.rb
CHANGED
@@ -5,8 +5,7 @@ require 'rabl/builder'
|
|
5
5
|
# Rabl.register!
|
6
6
|
module Rabl
|
7
7
|
def self.register!
|
8
|
-
require 'rabl/template'
|
9
|
-
require 'rabl/register'
|
8
|
+
require 'rabl/template'
|
10
9
|
end
|
11
10
|
end
|
12
11
|
|
@@ -14,6 +13,8 @@ end
|
|
14
13
|
if defined?(Padrino)
|
15
14
|
require 'padrino-core'
|
16
15
|
Padrino.after_load { Rabl.register! }
|
17
|
-
|
16
|
+
elsif defined?(Rails) && Rails.version =~ /^2/
|
17
|
+
Rabl.register!
|
18
|
+
elsif defined?(Rails) && Rails.version =~ /^3/
|
18
19
|
Rabl.register!
|
19
20
|
end
|
data/lib/rabl/builder.rb
CHANGED
@@ -31,7 +31,7 @@ module Rabl
|
|
31
31
|
extends(settings[:file], settings[:options], &settings[:block])
|
32
32
|
end if @options.has_key?(:extends)
|
33
33
|
|
34
|
-
@_root_name ||= @_object
|
34
|
+
@_root_name ||= data_name(@_object)
|
35
35
|
(@options[:root] || options[:root]) ? { @_root_name => @_result } : @_result
|
36
36
|
end
|
37
37
|
|
@@ -106,8 +106,7 @@ module Rabl
|
|
106
106
|
# data_name(@users) => :user
|
107
107
|
def data_name(data)
|
108
108
|
return data.values.first if data.is_a?(Hash)
|
109
|
-
|
110
|
-
data.class.model_name.element
|
109
|
+
@options[:engine].model_name(data)
|
111
110
|
end
|
112
111
|
|
113
112
|
# resolve_condition(:if => true) => true
|
data/lib/rabl/engine.rb
CHANGED
@@ -17,7 +17,7 @@ module Rabl
|
|
17
17
|
@_object = locals[:object] || self.default_object
|
18
18
|
instance_eval(@_source) if @_source.present?
|
19
19
|
instance_eval(&block) if block_given?
|
20
|
-
self.send("to_" + @_options[:format])
|
20
|
+
self.send("to_" + @_options[:format].to_s)
|
21
21
|
end
|
22
22
|
|
23
23
|
# Sets the object to be used as the data source for this template
|
@@ -93,11 +93,11 @@ module Rabl
|
|
93
93
|
to_hash(options).to_json
|
94
94
|
end
|
95
95
|
|
96
|
-
# Returns a
|
97
|
-
#
|
98
|
-
def
|
99
|
-
|
100
|
-
|
96
|
+
# Returns a json representation of the data object
|
97
|
+
# to_xml(:root => true)
|
98
|
+
def to_xml(options={})
|
99
|
+
options = options.reverse_merge(:root => false)
|
100
|
+
to_hash(options).to_xml(:root => model_name(@_object))
|
101
101
|
end
|
102
102
|
|
103
103
|
# Includes a helper module for RABL
|
@@ -107,6 +107,24 @@ module Rabl
|
|
107
107
|
end
|
108
108
|
alias_method :helpers, :helper
|
109
109
|
|
110
|
+
# Returns a hash based representation of any data object given ejs template block
|
111
|
+
# object_to_hash(@user) { attribute :full_name } => { ... }
|
112
|
+
def object_to_hash(object, source=nil, &block)
|
113
|
+
return object unless is_record?(object) || object.respond_to?(:each)
|
114
|
+
self.class.new(source, :format => "hash", :root => false).render(@_scope, :object => object, &block)
|
115
|
+
end
|
116
|
+
|
117
|
+
# model_name(@user) => "user"
|
118
|
+
# model_name([@user]) => "user"
|
119
|
+
# model_name([]) => "array"
|
120
|
+
def model_name(data)
|
121
|
+
if data.respond_to?(:first) && data.first.respond_to?(:valid?)
|
122
|
+
model_name(data.first).pluralize
|
123
|
+
else # actual data object
|
124
|
+
data.class.respond_to?(:model_name) ? data.class.model_name.element : data.class.to_s.downcase
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
110
128
|
protected
|
111
129
|
|
112
130
|
# Returns a guess at the default object for this template
|
data/lib/rabl/template.rb
CHANGED
@@ -1,19 +1,64 @@
|
|
1
|
-
#
|
1
|
+
# TILT Template
|
2
|
+
if defined?(Tilt)
|
3
|
+
class RablTemplate < Tilt::Template
|
4
|
+
def initialize_engine
|
5
|
+
return if defined?(::Rabl)
|
6
|
+
require_template_library 'rabl'
|
7
|
+
end
|
8
|
+
|
9
|
+
def prepare
|
10
|
+
options = @options.merge(:format => "json")
|
11
|
+
@engine = ::Rabl::Engine.new(data, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def evaluate(scope, locals, &block)
|
15
|
+
@engine.render(scope, locals, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Tilt.register 'rabl', RablTemplate
|
20
|
+
end
|
2
21
|
|
3
|
-
|
4
|
-
|
22
|
+
# Rails 2.X Template
|
23
|
+
if defined?(Rails) && Rails.version =~ /^2/
|
24
|
+
require 'action_view/base'
|
25
|
+
require 'action_view/template'
|
5
26
|
|
6
|
-
module ActionView
|
7
|
-
|
8
|
-
|
9
|
-
|
27
|
+
module ActionView
|
28
|
+
module TemplateHandlers
|
29
|
+
class RablHandler < TemplateHandler
|
30
|
+
include Compilable
|
10
31
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
32
|
+
def compile(template) %{
|
33
|
+
::Rabl::Engine.new(#{template.source.inspect}, { :format => #{template.format.inspect} }).
|
34
|
+
render(self, assigns.merge(local_assigns))
|
35
|
+
} end
|
36
|
+
end
|
15
37
|
end
|
16
38
|
end
|
39
|
+
|
40
|
+
ActionView::Template.register_template_handler :rabl, ActionView::TemplateHandlers::RablHandler
|
17
41
|
end
|
18
42
|
|
19
|
-
|
43
|
+
# Rails 3.X Template
|
44
|
+
if defined?(Rails) && Rails.version =~ /^3/
|
45
|
+
require 'action_view/base'
|
46
|
+
require 'action_view/template'
|
47
|
+
|
48
|
+
module ActionView
|
49
|
+
module Template::Handlers
|
50
|
+
class RablHandler < Template::Handler
|
51
|
+
include Compilable
|
52
|
+
|
53
|
+
self.default_format = Mime::JSON
|
54
|
+
|
55
|
+
def compile(template) %{
|
56
|
+
::Rabl::Engine.new(#{template.source.inspect}, { :format => #{template.formats.first.inspect} }).
|
57
|
+
render(self, assigns.merge(local_assigns))
|
58
|
+
} end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
ActionView::Template.register_template_handler :rabl, ActionView::TemplateHandlers::RablHandler
|
64
|
+
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:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.9
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Nathan Esquenazi
|
@@ -70,7 +70,6 @@ files:
|
|
70
70
|
- lib/rabl.rb
|
71
71
|
- lib/rabl/builder.rb
|
72
72
|
- lib/rabl/engine.rb
|
73
|
-
- lib/rabl/register.rb
|
74
73
|
- lib/rabl/template.rb
|
75
74
|
- lib/rabl/version.rb
|
76
75
|
- rabl.gemspec
|
data/lib/rabl/register.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
## TILT ##
|
2
|
-
if defined?(Tilt)
|
3
|
-
class RablTemplate < Tilt::Template
|
4
|
-
def initialize_engine
|
5
|
-
return if defined?(::Rabl)
|
6
|
-
require_template_library 'rabl'
|
7
|
-
end
|
8
|
-
|
9
|
-
def prepare
|
10
|
-
options = @options.merge(:format => "json")
|
11
|
-
@engine = ::Rabl::Engine.new(data, options)
|
12
|
-
end
|
13
|
-
|
14
|
-
def evaluate(scope, locals, &block)
|
15
|
-
@engine.render(scope, locals, &block)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
Tilt.register 'rabl', RablTemplate
|
20
|
-
end
|