rabl 0.1.0 → 0.1.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/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +25 -7
- data/TODO +1 -5
- data/lib/rabl.rb +2 -1
- data/lib/rabl/builder.rb +16 -45
- data/lib/rabl/engine.rb +45 -70
- data/lib/rabl/helpers.rb +72 -0
- data/lib/rabl/version.rb +1 -1
- data/rabl.gemspec +2 -0
- data/test/builder_test.rb +190 -1
- data/test/models/user.rb +9 -0
- data/test/teststrap.rb +2 -0
- metadata +31 -24
data/Gemfile
CHANGED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Nathan Esquenazi
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -43,11 +43,22 @@ To declare the data object for use in the template:
|
|
43
43
|
# app/views/users/show.json.rabl
|
44
44
|
object @user
|
45
45
|
|
46
|
-
or
|
46
|
+
or specify an alias for the object:
|
47
47
|
|
48
|
-
|
48
|
+
object @user => :person
|
49
|
+
# => { "person" : { ... } }
|
49
50
|
|
50
|
-
|
51
|
+
or pass a collection of objects:
|
52
|
+
|
53
|
+
collection @users
|
54
|
+
# => [ { "user" : { ... } } ]
|
55
|
+
|
56
|
+
or even specify a root node label for the collection:
|
57
|
+
|
58
|
+
collection @users => :people
|
59
|
+
# => { "people" : [ { "person" : { ... } } ] }
|
60
|
+
|
61
|
+
and this will be used as the default data for the rendering.
|
51
62
|
|
52
63
|
### Attributes ###
|
53
64
|
|
@@ -59,13 +70,13 @@ Basic usage of the templater to define a few simple attributes for the response:
|
|
59
70
|
or use with aliased attributes:
|
60
71
|
|
61
72
|
# Take the value of model attribute `foo` and name the node `bar`
|
62
|
-
# { bar : 5 }
|
63
73
|
attribute :foo => :bar
|
74
|
+
# => { bar : 5 }
|
64
75
|
|
65
76
|
or even multiple aliased attributes:
|
66
77
|
|
67
|
-
# { baz : <bar value>, animal : <dog value> }
|
68
78
|
attributes :bar => :baz, :dog => :animal
|
79
|
+
# => # { baz : <bar value>, animal : <dog value> }
|
69
80
|
|
70
81
|
### Child Nodes ###
|
71
82
|
|
@@ -154,7 +165,6 @@ Using partials and inheritance can significantly reduce code duplication in your
|
|
154
165
|
|
155
166
|
Check out the [Issues](https://github.com/nesquena/rabl/issues) tab for a full list:
|
156
167
|
|
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.
|
158
168
|
* No configuration options yet for how to create the json (root nodes) :(
|
159
169
|
* Better Tilt template support (precompiling templates)
|
160
170
|
* Benchmarks and performance optimizations
|
@@ -177,4 +187,12 @@ There are a few excellent libraries that helped inspire RABL and they are listed
|
|
177
187
|
* [JSON Builder](https://github.com/dewski/json_builder)
|
178
188
|
* [Argonaut](https://github.com/jbr/argonaut)
|
179
189
|
|
180
|
-
Thanks again for all of these great projects.
|
190
|
+
Thanks again for all of these great projects.
|
191
|
+
|
192
|
+
## Examples
|
193
|
+
|
194
|
+
See the [examples](https://github.com/nesquena/rabl/tree/master/examples) directory.
|
195
|
+
|
196
|
+
## Copyright
|
197
|
+
|
198
|
+
Copyright © 2011 Nathan Esquenazi. See [MIT-LICENSE](https://github.com/nesquena/rabl/blob/master/MIT-LICENSE) for details.
|
data/TODO
CHANGED
@@ -1,7 +1,3 @@
|
|
1
1
|
= TODO
|
2
2
|
|
3
|
-
|
4
|
-
- Add support for child collection with "root" for each
|
5
|
-
- Child should support collections of children
|
6
|
-
- Child should support symbol associations inside object
|
7
|
-
- Add support for Rails 3
|
3
|
+
* Support xml and json rendering in Tilt template
|
data/lib/rabl.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rabl/version'
|
2
|
+
require 'rabl/helpers'
|
2
3
|
require 'rabl/engine'
|
3
4
|
require 'rabl/builder'
|
4
5
|
|
@@ -17,4 +18,4 @@ elsif defined?(Rails) && Rails.version =~ /^2/
|
|
17
18
|
Rabl.register!
|
18
19
|
elsif defined?(Rails) && Rails.version =~ /^3/
|
19
20
|
Rabl.register!
|
20
|
-
end
|
21
|
+
end
|
data/lib/rabl/builder.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
module Rabl
|
2
2
|
class Builder
|
3
|
+
include Rabl::Helpers
|
4
|
+
|
3
5
|
# Constructs a new ejs hash based on given object and options
|
4
|
-
def initialize(
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
6
|
+
def initialize(data, options={}, &block)
|
7
|
+
@options = options
|
8
|
+
@_scope = options[:scope]
|
9
|
+
@_data = data
|
10
|
+
@_object = data_object(data)
|
11
|
+
@_result = {}
|
8
12
|
end
|
9
13
|
|
10
14
|
# Returns a hash representation of the data object
|
@@ -30,9 +34,9 @@ module Rabl
|
|
30
34
|
@options[:extends].each do |settings|
|
31
35
|
extends(settings[:file], settings[:options], &settings[:block])
|
32
36
|
end if @options.has_key?(:extends)
|
33
|
-
|
34
|
-
@_root_name ||= data_name(@
|
35
|
-
(@options[:root] || options[:root]) ? { @_root_name => @_result } : @_result
|
37
|
+
# Return Hash
|
38
|
+
@_root_name ||= data_name(@_data)
|
39
|
+
(@options[:root] || options[:root]) && @_root_name ? { @_root_name => @_result } : @_result
|
36
40
|
end
|
37
41
|
|
38
42
|
# Indicates an attribute or method should be included in the json output
|
@@ -44,7 +48,7 @@ module Rabl
|
|
44
48
|
else # array of attributes
|
45
49
|
options = args.extract_options!
|
46
50
|
args.each do |attribute|
|
47
|
-
@_result[options[:as] || attribute] = @_object.
|
51
|
+
@_result[options[:as] || attribute] = @_object.send(attribute) if @_object && @_object.respond_to?(attribute)
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -65,7 +69,8 @@ module Rabl
|
|
65
69
|
def child(data, options={}, &block)
|
66
70
|
return false unless data.present?
|
67
71
|
name, object = data_name(data), data_object(data)
|
68
|
-
|
72
|
+
include_root = object.respond_to?(:each) # @users
|
73
|
+
@_result[name] = self.object_to_hash(object, :root => include_root, &block) if resolve_condition(options)
|
69
74
|
end
|
70
75
|
|
71
76
|
# Glues data from a child node to the json_output
|
@@ -73,7 +78,7 @@ module Rabl
|
|
73
78
|
def glue(data, &block)
|
74
79
|
return false unless data.present?
|
75
80
|
object = data_object(data)
|
76
|
-
glued_attributes = self.object_to_hash(object, &block)
|
81
|
+
glued_attributes = self.object_to_hash(object, :root => false, &block)
|
77
82
|
@_result.merge!(glued_attributes) if glued_attributes
|
78
83
|
end
|
79
84
|
|
@@ -81,42 +86,8 @@ module Rabl
|
|
81
86
|
# extends("users/show") { attribute :full_name }
|
82
87
|
def extends(file, options={}, &block)
|
83
88
|
options = options.merge(:object => @_object)
|
84
|
-
result =
|
89
|
+
result = self.partial(file, options, &block)
|
85
90
|
@_result.merge!(result) if result
|
86
91
|
end
|
87
|
-
|
88
|
-
protected
|
89
|
-
|
90
|
-
# Returns a hash based representation of any data object given ejs template block
|
91
|
-
# object_to_hash(@user) { attribute :full_name } => { ... }
|
92
|
-
def object_to_hash(object, source=nil, &block)
|
93
|
-
@options[:engine].object_to_hash(object, source, &block)
|
94
|
-
end
|
95
|
-
|
96
|
-
# data_object(data) => <AR Object>
|
97
|
-
# data_object(@user => :person) => @user
|
98
|
-
# data_object(:user => :person) => @_object.send(:user)
|
99
|
-
def data_object(data)
|
100
|
-
data = (data.is_a?(Hash) && data.keys.one?) ? data.keys.first : data
|
101
|
-
data.is_a?(Symbol) ? @_object.send(data) : data
|
102
|
-
end
|
103
|
-
|
104
|
-
# data_name(data) => "user"
|
105
|
-
# data_name(@user => :person) => :person
|
106
|
-
# data_name(@users) => :user
|
107
|
-
def data_name(data)
|
108
|
-
return data.values.first if data.is_a?(Hash)
|
109
|
-
@options[:engine].model_name(data)
|
110
|
-
end
|
111
|
-
|
112
|
-
# resolve_condition(:if => true) => true
|
113
|
-
# resolve_condition(:if => lambda { |m| false }) => false
|
114
|
-
# resolve_condition(:unless => lambda { |m| true }) => true
|
115
|
-
def resolve_condition(options)
|
116
|
-
return true if options[:if].nil? && options[:unless].nil?
|
117
|
-
result = options[:if] == true || (options[:if].respond_to?(:call) && options[:if].call(@_object)) if options.has_key?(:if)
|
118
|
-
result = options[:unless] == false || (options[:unless].respond_to?(:call) && !options[:unless].call(@_object)) if options.has_key?(:unless)
|
119
|
-
result
|
120
|
-
end
|
121
92
|
end
|
122
93
|
end
|
data/lib/rabl/engine.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Rabl
|
2
2
|
class Engine
|
3
|
+
include Rabl::Helpers
|
4
|
+
|
3
5
|
# Constructs a new ejs engine based on given vars, handler and declarations
|
4
6
|
# Rabl::Engine.new("...source...", { :format => "xml", :root => true, :view_path => "/path/to/views" })
|
5
7
|
def initialize(source, options={})
|
@@ -10,20 +12,55 @@ module Rabl
|
|
10
12
|
# Renders the representation based on source, object, scope and locals
|
11
13
|
# Rabl::Engine.new("...source...", { :format => "xml" }).render(scope, { :foo => "bar", :object => @user })
|
12
14
|
def render(scope, locals, &block)
|
13
|
-
@_locals = locals
|
14
|
-
@_scope = scope
|
15
|
-
@_options = @_options.merge(:scope => @_scope, :locals => @_locals, :engine => self)
|
15
|
+
@_locals, @_scope = locals, scope
|
16
16
|
self.copy_instance_variables_from(@_scope, [:@assigns, :@helpers])
|
17
|
-
@
|
17
|
+
@_options[:scope] = @_scope
|
18
|
+
@_data = locals[:object] || self.default_object
|
18
19
|
instance_eval(@_source) if @_source.present?
|
19
20
|
instance_eval(&block) if block_given?
|
20
21
|
self.send("to_" + @_options[:format].to_s)
|
21
22
|
end
|
22
23
|
|
24
|
+
# Returns a hash representation of the data object
|
25
|
+
# to_hash(:root => true)
|
26
|
+
def to_hash(options={})
|
27
|
+
data = data_object(@_data)
|
28
|
+
if is_record?(data) || !data # object @user
|
29
|
+
Rabl::Builder.new(@_data, @_options).to_hash(options)
|
30
|
+
elsif data.respond_to?(:each) # collection @users
|
31
|
+
data.map { |object| Rabl::Builder.new({ object => data_name(object) }, @_options).to_hash(options) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a json representation of the data object
|
36
|
+
# to_json(:root => true)
|
37
|
+
def to_json(options={})
|
38
|
+
options = options.reverse_merge(:root => true)
|
39
|
+
result = @_collection_name ? { @_collection_name => to_hash(options) } : to_hash(options)
|
40
|
+
result.to_json
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns a json representation of the data object
|
44
|
+
# to_xml(:root => true)
|
45
|
+
def to_xml(options={})
|
46
|
+
options = options.reverse_merge(:root => false)
|
47
|
+
to_hash(options).to_xml(:root => data_name(@_data))
|
48
|
+
end
|
49
|
+
|
23
50
|
# Sets the object to be used as the data source for this template
|
24
51
|
# object(@user)
|
52
|
+
# object @user => :person
|
53
|
+
# object @users
|
25
54
|
def object(data)
|
26
|
-
@
|
55
|
+
@_data = data unless @_locals[:object]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sets the object as a collection casted to a simple array
|
59
|
+
# collection @users
|
60
|
+
# collection @users => :people
|
61
|
+
def collection(data)
|
62
|
+
@_collection_name = data.values.first if data.respond_to?(:each_pair)
|
63
|
+
self.object(data_object(data).to_a) if data
|
27
64
|
end
|
28
65
|
|
29
66
|
# Indicates an attribute or method should be included in the json output
|
@@ -47,6 +84,7 @@ module Rabl
|
|
47
84
|
@_options[:code] ||= {}
|
48
85
|
@_options[:code][name] = { :options => options, :block => block }
|
49
86
|
end
|
87
|
+
alias_method :node, :code
|
50
88
|
|
51
89
|
# Creates a child node that is included in json output
|
52
90
|
# child(@user) { attribute :full_name }
|
@@ -69,84 +107,21 @@ module Rabl
|
|
69
107
|
@_options[:extends].push({ :file => file, :options => options, :block => block })
|
70
108
|
end
|
71
109
|
|
72
|
-
#
|
73
|
-
# partial("users/show", :object => @user)
|
74
|
-
def partial(file, options={}, &block)
|
75
|
-
source = self.fetch_source(file)
|
76
|
-
self.object_to_hash(options[:object], source, &block)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Returns a hash representation of the data object
|
80
|
-
# to_hash(:root => true)
|
81
|
-
def to_hash(options={})
|
82
|
-
if is_record?(@_object)
|
83
|
-
Rabl::Builder.new(@_object, @_options).to_hash(options)
|
84
|
-
elsif @_object.respond_to?(:each)
|
85
|
-
@_object.map { |object| Rabl::Builder.new(object, @_options).to_hash(options) }
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Returns a json representation of the data object
|
90
|
-
# to_json(:root => true)
|
91
|
-
def to_json(options={})
|
92
|
-
options = options.reverse_merge(:root => true)
|
93
|
-
to_hash(options).to_json
|
94
|
-
end
|
95
|
-
|
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
|
-
end
|
102
|
-
|
103
|
-
# Includes a helper module for RABL
|
110
|
+
# Includes a helper module with a RABL template
|
104
111
|
# helper ExampleHelper
|
105
112
|
def helper(*klazzes)
|
106
113
|
klazzes.each { |klazz| self.class.send(:include, klazz) }
|
107
114
|
end
|
108
115
|
alias_method :helpers, :helper
|
109
116
|
|
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
|
-
|
128
117
|
protected
|
129
118
|
|
130
119
|
# Returns a guess at the default object for this template
|
120
|
+
# default_object => @user
|
131
121
|
def default_object
|
132
122
|
@_scope.respond_to?(:controller) ?
|
133
123
|
instance_variable_get("@#{@_scope.controller.controller_name}") :
|
134
124
|
nil
|
135
125
|
end
|
136
|
-
|
137
|
-
# Returns true if item is a ORM record; false otherwise
|
138
|
-
def is_record?(obj)
|
139
|
-
obj && obj.respond_to?(:valid?)
|
140
|
-
end
|
141
|
-
|
142
|
-
# Returns source for a given relative file
|
143
|
-
# fetch_source("show") => "...contents..."
|
144
|
-
def fetch_source(file)
|
145
|
-
root_path = Rails.root if defined?(Rails)
|
146
|
-
root_path = Padrino.root if defined?(Padrino)
|
147
|
-
view_path = @_options[:view_path] || File.join(root_path, "app/views/")
|
148
|
-
file_path = Dir[File.join(view_path, file + "*.rabl")].first
|
149
|
-
File.read(file_path) if file_path
|
150
|
-
end
|
151
126
|
end
|
152
127
|
end
|
data/lib/rabl/helpers.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Rabl
|
2
|
+
module Helpers
|
3
|
+
# data_object(data) => <AR Object>
|
4
|
+
# data_object(@user => :person) => @user
|
5
|
+
# data_object(:user => :person) => @_object.send(:user)
|
6
|
+
def data_object(data)
|
7
|
+
data = (data.is_a?(Hash) && data.keys.one?) ? data.keys.first : data
|
8
|
+
data.is_a?(Symbol) && @_object ? @_object.send(data) : data
|
9
|
+
end
|
10
|
+
|
11
|
+
# data_name(data) => "user"
|
12
|
+
# data_name(@user => :person) => :person
|
13
|
+
# data_name(@users) => :user
|
14
|
+
# data_name([@user]) => "user"
|
15
|
+
# data_name([]) => "array"
|
16
|
+
def data_name(data)
|
17
|
+
return nil unless data # nil or false
|
18
|
+
return data.values.first if data.is_a?(Hash) # @user => :user
|
19
|
+
data = @_object.send(data) if data.is_a?(Symbol) && @_object # :address
|
20
|
+
if data.respond_to?(:first) && data.first.respond_to?(:valid?)
|
21
|
+
data_name(data.first).pluralize
|
22
|
+
else # actual data object
|
23
|
+
object_name = @_collection_name.to_s.singularize if @_collection_name
|
24
|
+
object_name ||= data.class.respond_to?(:model_name) ? data.class.model_name.element : data.class.to_s.downcase
|
25
|
+
object_name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns true if item is a ORM record; false otherwise
|
30
|
+
# is_record?(@user) => true
|
31
|
+
# is_record?([]) => false
|
32
|
+
def is_record?(obj)
|
33
|
+
obj && data_object(obj).respond_to?(:valid?)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a hash based representation of any data object given ejs template block
|
37
|
+
# object_to_hash(@user) { attribute :full_name } => { ... }
|
38
|
+
# object_to_hash(@user, :source => "...") { attribute :full_name } => { ... }
|
39
|
+
def object_to_hash(object, options={}, &block)
|
40
|
+
return object unless is_record?(object) || object.respond_to?(:each)
|
41
|
+
engine_options = { :format => "hash", :root => (options[:root] || false) }
|
42
|
+
Rabl::Engine.new(options[:source], engine_options).render(@_scope, :object => object, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
# resolve_condition(:if => true) => true
|
46
|
+
# resolve_condition(:if => lambda { |m| false }) => false
|
47
|
+
# resolve_condition(:unless => lambda { |m| true }) => true
|
48
|
+
def resolve_condition(options)
|
49
|
+
return true if options[:if].nil? && options[:unless].nil?
|
50
|
+
result = options[:if] == true || (options[:if].respond_to?(:call) && options[:if].call(@_object)) if options.has_key?(:if)
|
51
|
+
result = options[:unless] == false || (options[:unless].respond_to?(:call) && !options[:unless].call(@_object)) if options.has_key?(:unless)
|
52
|
+
result
|
53
|
+
end
|
54
|
+
|
55
|
+
# Renders a partial hash based on another rabl template
|
56
|
+
# partial("users/show", :object => @user)
|
57
|
+
def partial(file, options={}, &block)
|
58
|
+
source = self.fetch_source(file)
|
59
|
+
self.object_to_hash(options[:object], :source => source, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns source for a given relative file
|
63
|
+
# fetch_source("show", :view_path => "...") => "...contents..."
|
64
|
+
def fetch_source(file, options={})
|
65
|
+
root_path = Rails.root if defined?(Rails)
|
66
|
+
root_path = Padrino.root if defined?(Padrino)
|
67
|
+
view_path = options[:view_path] || File.join(root_path, "app/views/")
|
68
|
+
file_path = Dir[File.join(view_path, file + "*.rabl")].first
|
69
|
+
File.read(file_path) if file_path
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/rabl/version.rb
CHANGED
data/rabl.gemspec
CHANGED
data/test/builder_test.rb
CHANGED
@@ -1 +1,190 @@
|
|
1
|
-
require File.expand_path('../teststrap',__FILE__)
|
1
|
+
require File.expand_path('../teststrap', __FILE__)
|
2
|
+
require File.expand_path('../models/user', __FILE__)
|
3
|
+
|
4
|
+
context "Rabl::Builder" do
|
5
|
+
|
6
|
+
helper(:builder) { |obj,opt| Rabl::Builder.new(obj, opt) }
|
7
|
+
helper(:get_result) { |obj| obj.instance_variable_get("@_result") }
|
8
|
+
helper(:get_hash) { |obj, root| obj.to_hash(:root => root) }
|
9
|
+
|
10
|
+
setup do
|
11
|
+
@users = [User.new, User.new]
|
12
|
+
@user = User.new
|
13
|
+
builder User.new, {}
|
14
|
+
end
|
15
|
+
|
16
|
+
context "#initialize" do
|
17
|
+
asserts_topic.assigns :_object
|
18
|
+
asserts_topic.assigns :options
|
19
|
+
asserts_topic.assigns :_result
|
20
|
+
end
|
21
|
+
|
22
|
+
context "#to_hash" do
|
23
|
+
|
24
|
+
context "when given a simple object" do
|
25
|
+
|
26
|
+
setup { builder User.new, {} }
|
27
|
+
asserts "that the object is set properly" do
|
28
|
+
topic.attribute :name
|
29
|
+
get_hash(topic, true)
|
30
|
+
end.equivalent_to({ "user" => { :name => "rabl" } })
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when given an object alias" do
|
35
|
+
|
36
|
+
setup { builder({ User.new => "person" }, {}) }
|
37
|
+
asserts "that the object is set properly" do
|
38
|
+
topic.attribute :name
|
39
|
+
get_hash(topic, true)
|
40
|
+
end.equivalent_to({ "person" => { :name => "rabl" } })
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when specified with no root" do
|
45
|
+
|
46
|
+
setup { builder User.new, {} }
|
47
|
+
asserts "that the object is set properly" do
|
48
|
+
topic.attribute :name
|
49
|
+
get_hash(topic, false)
|
50
|
+
end.equivalent_to({ :name => "rabl" })
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
context "#attribute" do
|
57
|
+
|
58
|
+
context "when given an array" do
|
59
|
+
|
60
|
+
asserts "that the node" do
|
61
|
+
topic.attribute :name, :city
|
62
|
+
get_result(topic)
|
63
|
+
end.equivalent_to({:name => 'rabl', :city => 'irvine'})
|
64
|
+
|
65
|
+
denies "that with a non-existent attribute the node" do
|
66
|
+
topic.attribute :fake
|
67
|
+
get_result(topic)[:fake]
|
68
|
+
end.exists
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when given a Hash" do
|
73
|
+
|
74
|
+
asserts "that using :as, the node" do
|
75
|
+
topic.attribute :city, :as => 'foo'
|
76
|
+
get_result(topic)
|
77
|
+
end.equals({'foo'=>'irvine'})
|
78
|
+
|
79
|
+
asserts "with multiple attributes, the node" do
|
80
|
+
topic.attributes :city => :a, :age => :b
|
81
|
+
get_result(topic)
|
82
|
+
end.equivalent_to({:a => 'irvine', :b => 24, 'foo' => 'irvine'})
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
context "#code" do
|
89
|
+
|
90
|
+
asserts "that it has node :foo" do
|
91
|
+
topic.code(:foo) { "bar" }
|
92
|
+
get_result(topic)
|
93
|
+
end.equivalent_to({:foo => 'bar'})
|
94
|
+
|
95
|
+
asserts "that using object it has node :boo" do
|
96
|
+
topic.code(:baz) { |u| u.city }
|
97
|
+
get_result(topic)
|
98
|
+
end.equivalent_to({:foo => 'bar', :baz => 'irvine'})
|
99
|
+
end
|
100
|
+
|
101
|
+
context "#child" do
|
102
|
+
|
103
|
+
denies "that it generates if no data present" do
|
104
|
+
topic.child nil
|
105
|
+
end
|
106
|
+
|
107
|
+
asserts "that it generates with a hash" do
|
108
|
+
b = builder @user, {}
|
109
|
+
mock(b).object_to_hash(@user,{ :root => false }).returns('xyz').subject
|
110
|
+
|
111
|
+
b.child(@user => :user) { attribute :name }
|
112
|
+
get_result(b)
|
113
|
+
end.equivalent_to({ :user => 'xyz'})
|
114
|
+
|
115
|
+
asserts "that it generates with a hash alias" do
|
116
|
+
b = builder @user, {}
|
117
|
+
|
118
|
+
b.child(@user => :person) { attribute :name }
|
119
|
+
get_result(b)
|
120
|
+
end.equivalent_to({ :person => { :name => "rabl" } })
|
121
|
+
|
122
|
+
asserts "that it generates with an object" do
|
123
|
+
b = builder @user, {}
|
124
|
+
mock(b).data_name(@user) { :user }
|
125
|
+
mock(b).object_to_hash(@user,{ :root => false }).returns('xyz').subject
|
126
|
+
|
127
|
+
b.child(@user) { attribute :name }
|
128
|
+
get_result(b)
|
129
|
+
end.equivalent_to({ :user => 'xyz'})
|
130
|
+
|
131
|
+
asserts "that it generates with an collection" do
|
132
|
+
b = builder @user, {}
|
133
|
+
mock(b).data_name(@users) { :users }
|
134
|
+
mock(b).object_to_hash(@users,{ :root => true }).returns('xyz').subject
|
135
|
+
|
136
|
+
b.child(@users) { attribute :name }
|
137
|
+
get_result(b)
|
138
|
+
end.equivalent_to({ :users => 'xyz'})
|
139
|
+
end
|
140
|
+
|
141
|
+
context "#glue" do
|
142
|
+
|
143
|
+
denies "that it generates if no data present" do
|
144
|
+
topic.glue nil
|
145
|
+
end
|
146
|
+
|
147
|
+
asserts "that it generates the glue attributes" do
|
148
|
+
b = builder @user, {}
|
149
|
+
mock(b).object_to_hash(@user,{ :root => false }).returns({:user => 'xyz'}).subject
|
150
|
+
|
151
|
+
b.glue(@user) { attribute :name }
|
152
|
+
get_result(b)
|
153
|
+
end.equivalent_to({ :user => 'xyz' })
|
154
|
+
|
155
|
+
asserts "that it appends the glue attributes to result" do
|
156
|
+
b = builder @user, {}
|
157
|
+
|
158
|
+
b.glue(@user) { attribute :name => :user_name }
|
159
|
+
get_result(b)
|
160
|
+
end.equivalent_to({ :user_name => 'rabl' })
|
161
|
+
|
162
|
+
asserts "that it does not generate new attributes if no glue attributes are present" do
|
163
|
+
b = builder @user, {}
|
164
|
+
mock(b).object_to_hash(@user,{ :root => false }).returns({}).subject
|
165
|
+
|
166
|
+
b.glue(@user) { attribute :name }
|
167
|
+
get_result(b)
|
168
|
+
end.equals({})
|
169
|
+
end
|
170
|
+
|
171
|
+
context "#extend" do
|
172
|
+
|
173
|
+
asserts "that it does not genereate if no data is present" do
|
174
|
+
b = builder @user, {}
|
175
|
+
mock(b).partial('users/show',{ :object => @user}).returns({}).subject
|
176
|
+
|
177
|
+
b.extends('users/show') { attribute :name }
|
178
|
+
get_result(b)
|
179
|
+
end.equals({})
|
180
|
+
|
181
|
+
asserts "that it generates if data is present" do
|
182
|
+
b = builder @user, {}
|
183
|
+
mock(b).partial('users/show',{ :object => @user}).returns({:user => 'xyz'}).subject
|
184
|
+
|
185
|
+
b.extends('users/show') { attribute :name }
|
186
|
+
get_result(b)
|
187
|
+
end.equivalent_to({:user => 'xyz'})
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
data/test/models/user.rb
ADDED
data/test/teststrap.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rabl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 27
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 0.1.0
|
5
|
+
version: 0.1.1
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Nathan Esquenazi
|
@@ -15,7 +10,8 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-18 00:00:00 -07:00
|
14
|
+
default_executable:
|
19
15
|
dependencies:
|
20
16
|
- !ruby/object:Gem::Dependency
|
21
17
|
name: riot
|
@@ -25,11 +21,6 @@ dependencies:
|
|
25
21
|
requirements:
|
26
22
|
- - ~>
|
27
23
|
- !ruby/object:Gem::Version
|
28
|
-
hash: 41
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
- 12
|
32
|
-
- 3
|
33
24
|
version: 0.12.3
|
34
25
|
type: :development
|
35
26
|
version_requirements: *id001
|
@@ -41,14 +32,31 @@ dependencies:
|
|
41
32
|
requirements:
|
42
33
|
- - ~>
|
43
34
|
- !ruby/object:Gem::Version
|
44
|
-
hash: 19
|
45
|
-
segments:
|
46
|
-
- 1
|
47
|
-
- 0
|
48
|
-
- 2
|
49
35
|
version: 1.0.2
|
50
36
|
type: :development
|
51
37
|
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: mongoid
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: bson_ext
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id004
|
52
60
|
description: General ruby templating for json or xml
|
53
61
|
email:
|
54
62
|
- nesquena@gmail.com
|
@@ -61,6 +69,7 @@ extra_rdoc_files: []
|
|
61
69
|
files:
|
62
70
|
- .gitignore
|
63
71
|
- Gemfile
|
72
|
+
- MIT-LICENSE
|
64
73
|
- README.md
|
65
74
|
- Rakefile
|
66
75
|
- TODO
|
@@ -70,14 +79,17 @@ files:
|
|
70
79
|
- lib/rabl.rb
|
71
80
|
- lib/rabl/builder.rb
|
72
81
|
- lib/rabl/engine.rb
|
82
|
+
- lib/rabl/helpers.rb
|
73
83
|
- lib/rabl/template.rb
|
74
84
|
- lib/rabl/version.rb
|
75
85
|
- rabl.gemspec
|
76
86
|
- test.watchr
|
77
87
|
- test/builder_test.rb
|
78
88
|
- test/engine_test.rb
|
89
|
+
- test/models/user.rb
|
79
90
|
- test/template_test.rb
|
80
91
|
- test/teststrap.rb
|
92
|
+
has_rdoc: true
|
81
93
|
homepage: https://github.com/nesquena/rabl
|
82
94
|
licenses: []
|
83
95
|
|
@@ -91,28 +103,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
103
|
requirements:
|
92
104
|
- - ">="
|
93
105
|
- !ruby/object:Gem::Version
|
94
|
-
hash: 3
|
95
|
-
segments:
|
96
|
-
- 0
|
97
106
|
version: "0"
|
98
107
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
108
|
none: false
|
100
109
|
requirements:
|
101
110
|
- - ">="
|
102
111
|
- !ruby/object:Gem::Version
|
103
|
-
hash: 3
|
104
|
-
segments:
|
105
|
-
- 0
|
106
112
|
version: "0"
|
107
113
|
requirements: []
|
108
114
|
|
109
115
|
rubyforge_project: rabl
|
110
|
-
rubygems_version: 1.
|
116
|
+
rubygems_version: 1.5.2
|
111
117
|
signing_key:
|
112
118
|
specification_version: 3
|
113
119
|
summary: General ruby templating for json or xml
|
114
120
|
test_files:
|
115
121
|
- test/builder_test.rb
|
116
122
|
- test/engine_test.rb
|
123
|
+
- test/models/user.rb
|
117
124
|
- test/template_test.rb
|
118
125
|
- test/teststrap.rb
|