rabl 0.0.9 → 0.1.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/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
|