Class: Rabl::Engine

Inherits:
Object
  • Object
show all
Includes:
Partials
Defined in:
lib/rabl/engine.rb

Constant Summary collapse

FORMATS =

List of supported rendering formats

[:json, :xml, :plist, :bson, :msgpack]

Constants included from Helpers

Helpers::KNOWN_OBJECT_CLASSES

Instance Method Summary collapse

Methods included from Partials

#fetch_source, #object_to_hash, #partial

Methods included from Helpers

#collection_root_name, #context_scope, #data_name, #data_object, #data_object_attribute, #determine_object_root, #escape_output, #fetch_result_from_cache, #is_collection?, #is_name_value?, #is_object?, #object_root_name, #template_cache_configured?

Constructor Details

#initialize(source, options = {}) ⇒ Engine

Constructs a new ejs engine based on given vars, handler and declarations Rabl::Engine.new(“…source…”, { :format => “xml”, :root => true, :view_path => “/path/to/views” })



10
11
12
13
14
# File 'lib/rabl/engine.rb', line 10

def initialize(source, options={})
  @_source = source
  @_options = options
  @_view_path = options[:view_path]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object (protected)

Supports calling helpers defined for the template scope using method_missing hook



251
252
253
# File 'lib/rabl/engine.rb', line 251

def method_missing(name, *args, &block)
  context_scope.respond_to?(name, true) ? context_scope.__send__(name, *args, &block) : super
end

Instance Method Details

#attribute(*args) ⇒ Object Also known as: attributes

Indicates an attribute or method should be included in the json output attribute :foo, :as => “bar” attribute :foo => :bar, :bar => :baz attribute :foo => :bar, :bar => :baz, :if => lambda { |r| r.foo }



160
161
162
163
164
165
166
167
168
# File 'lib/rabl/engine.rb', line 160

def attribute(*args)
  if args.first.is_a?(Hash) # :foo => :bar, :bar => :baz
    attr_aliases, conds = args.first.except(:if, :unless), args.first.slice(:if, :unless)
    attr_aliases.each_pair { |k,v| self.attribute(k, conds.merge(:as => v)) }
  else # array of attributes i.e :foo, :bar, :baz
    attr_options = args.extract_options!
    args.each { |name| @_options[:attributes][name] = attr_options }
  end
end

#cache(key = nil, options = nil) ⇒ Object

Sets the cache key to be used by ActiveSupport::Cache.expand_cache_key cache @user # calls @user.cache_key cache [‘rabl’, @user] # calls @user.cache_key and prefixes with rabl/ cache ‘user’ # explicit key of ‘user’ cache # uses the current item within a collection cache ‘user’, expires_in: 1.hour options is passed through to the cache store



151
152
153
154
# File 'lib/rabl/engine.rb', line 151

def cache(key = nil, options = nil)
  key ||= @_data_object # if called but missing, use object
  @_cache = [key, options]
end

#child(data, options = {}, &block) ⇒ Object

Creates a child node that is included in json output child(@user) { attribute :full_name }



181
182
183
# File 'lib/rabl/engine.rb', line 181

def child(data, options={}, &block)
  @_options[:child].push({ :data => data, :options => options, :block => block })
end

#collection(data, options = {}) ⇒ Object

Sets the object as a collection casted to a simple array collection @users collection @users => :people collection @users, :root => :person collection @users, :object_root => :person



137
138
139
140
141
142
# File 'lib/rabl/engine.rb', line 137

def collection(data, options={})
  @_collection_name = options[:root] if options[:root]
  @_collection_name ||= data.values.first if data.respond_to?(:each_pair)
  @_object_root_name = options[:object_root] if options.has_key?(:object_root)
  self.object(Array(data_object(data)))
end

#extends(file, options = {}, &block) ⇒ Object

Extends an existing rabl template with additional attributes in the block extends(“users/show”, :object => @user) { attribute :full_name }



193
194
195
196
# File 'lib/rabl/engine.rb', line 193

def extends(file, options={}, &block)
  extend_ops = options.merge(:view_path => options.fetch(:view_path, @_options[:view_path]))
  @_options[:extends].push({ :file => file, :options => extend_ops, :block => block })
end

#glue(data, options = {}, &block) ⇒ Object

Glues data from a child node to the json_output glue(@user) { attribute :full_name => :user_full_name }



187
188
189
# File 'lib/rabl/engine.rb', line 187

def glue(data, options={}, &block)
  @_options[:glue].push({ :data => data, :options => options, :block => block })
end

#helper(*klazzes) ⇒ Object Also known as: helpers

Includes a helper module with a RABL template helper ExampleHelper



200
201
202
# File 'lib/rabl/engine.rb', line 200

def helper(*klazzes)
  klazzes.each { |klazz| self.class.__send__(:include, klazz) }
end

#node(name = nil, options = {}, &block) ⇒ Object Also known as: code

Creates an arbitrary node that is included in the json output. node(:foo) { “bar” } node(:foo, :if => lambda { … }) { “bar” }



174
175
176
# File 'lib/rabl/engine.rb', line 174

def node(name = nil, options={}, &block)
  @_options[:node].push({ :name => name, :options => options, :block => block })
end

#object(template_data) ⇒ Object

Sets the object to be used as the data source for this template object(@user) object @user => :person object @users



119
120
121
122
123
# File 'lib/rabl/engine.rb', line 119

def object(template_data)
  current_data  = (@_locals[:object].nil? || template_data == false) ? template_data : @_locals[:object]
  @_data_object = data_object(current_data)
  @_data_name   = data_name(template_data.is_a?(Hash) && !current_data.is_a?(Hash) ? template_data : current_data)
end

#render(scope, locals, &block) ⇒ Object

Renders the representation based on source, object, scope and locals Rabl::Engine.new(“…source…”, { :format => “xml” }).render(scope, { :foo => “bar”, :object => @user })



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rabl/engine.rb', line 22

def render(scope, locals, &block)
  reset_options!
  @_locals, @_scope = locals, scope
  self.copy_instance_variables_from(@_scope, [:@assigns, :@helpers])
  locals.merge!(locals.delete(:locals) || {})
  locals.each { |k,v| instance_variable_set(:"@#{k}", v) }
  @_options[:scope] = @_scope
  @_options[:format] ||= self.request_format
  data = locals[:object].nil? ? self.default_object : locals[:object]
  @_data_object = data_object(data)
  @_data_name = @_options[:object_root_name] || data_name(data)
  if @_options[:source_location]
    instance_eval(@_source, @_options[:source_location]) if @_source.present?
  else # without source location
    instance_eval(@_source) if @_source.present?
  end
  instance_exec(@_data_object, &block) if block_given?
  cache_results { self.send("to_" + @_options[:format].to_s) }
end

#root_objectObject

Returns the current object that is the topic of this template Can be the collection or the object depending on topic assigned root_object => @user



128
129
130
# File 'lib/rabl/engine.rb', line 128

def root_object
  @_data_object
end

#source=(string) ⇒ Object



16
17
18
# File 'lib/rabl/engine.rb', line 16

def source=(string)
  @_source = string
end

#to_bson(options = {}) ⇒ Object

Returns a bson representation of the data object to_bson(:root => true)



101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rabl/engine.rb', line 101

def to_bson(options={})
  include_root = Rabl.configuration.include_bson_root
  include_child_root = Rabl.configuration.include_child_root
  options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
  result = if collection_root_name
             { collection_root_name => to_hash(options) }
           elsif is_collection?(@_data_object) && @_data_object.is_a?(Array)
             { @_data_name => to_hash(options) }
           else
             to_hash(options)
           end
  Rabl.configuration.bson_engine.serialize(result).to_s
end

#to_hash(options = {}) ⇒ Object

Returns a hash representation of the data object to_hash(:root => true, :child_root => true)



44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rabl/engine.rb', line 44

def to_hash(options={})
  options = options.merge(@_options)
  data = @_data_object
  builder = Rabl::Builder.new(options)
  options[:root_name] = determine_object_root(@_data_object, @_data_name, options[:root])

  if is_object?(data) || !data # object @user
    builder.build(data, options)
  elsif is_collection?(data) # collection @users
    data.map { |object| builder.build(object, options) }
  end
end

#to_json(options = {}) ⇒ Object

Returns a json representation of the data object to_json(:root => true)



59
60
61
62
63
64
65
# File 'lib/rabl/engine.rb', line 59

def to_json(options={})
  include_root = Rabl.configuration.include_json_root
  include_child_root = Rabl.configuration.include_child_root
  options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
  result = collection_root_name ? { collection_root_name => to_hash(options) } : to_hash(options)
  format_json(result)
end

#to_msgpack(options = {}) ⇒ Object Also known as: to_mpac

Returns a msgpack representation of the data object to_msgpack(:root => true)



69
70
71
72
73
74
75
# File 'lib/rabl/engine.rb', line 69

def to_msgpack(options={})
  include_root = Rabl.configuration.include_msgpack_root
  include_child_root = Rabl.configuration.include_child_root
  options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
  result = collection_root_name ? { collection_root_name => to_hash(options) } : to_hash(options)
  Rabl.configuration.msgpack_engine.pack result
end

#to_plist(options = {}) ⇒ Object

Returns a plist representation of the data object to_plist(:root => true)



80
81
82
83
84
85
86
# File 'lib/rabl/engine.rb', line 80

def to_plist(options={})
  include_root = Rabl.configuration.include_plist_root
  include_child_root = Rabl.configuration.include_child_root
  options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
  result = defined?(@_collection_name) ? { @_collection_name => to_hash(options) } : to_hash(options)
  Rabl.configuration.plist_engine.dump(result)
end

#to_xml(options = {}) ⇒ Object

Returns an xml representation of the data object to_xml(:root => true)



90
91
92
93
94
95
96
97
# File 'lib/rabl/engine.rb', line 90

def to_xml(options={})
  include_root = Rabl.configuration.include_xml_root
  include_child_root = include_root && Rabl.configuration.include_child_root
  options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
  xml_options = Rabl.configuration.default_xml_options.merge(:root => collection_root_name || @_data_name)
  result = to_hash(options)
  result.to_xml(xml_options)
end