forked from nesquena/rabl
/
helpers.rb
106 lines (98 loc) · 4.29 KB
/
helpers.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
module Rabl
module Helpers
# data_object(data) => <AR Object>
# data_object(@user => :person) => @user
# data_object(:user => :person) => @_object.send(:user)
def data_object(data)
data = (data.is_a?(Hash) && data.keys.size == 1) ? data.keys.first : data
data.is_a?(Symbol) && @_object ? @_object.send(data) : data
end
# data_name(data) => "user"
# data_name(@user => :person) => :person
# data_name(@users) => :user
# data_name([@user]) => "user"
# data_name([]) => "array"
def data_name(data)
return nil unless data # nil or false
return data.values.first if data.is_a?(Hash) # @user => :user
if data.is_a?(Symbol)
symbolString = data.to_s.downcase
data = @_object.send(data) if @_object # :address
end
if data.respond_to?(:first)
if data.first.present?
data_name(data.first).pluralize
else
symbolString
end
else # actual data object
object_name = @_collection_name.to_s.singularize if defined? @_collection_name
object_name ||= data.class.respond_to?(:model_name) ? data.class.model_name.element : data.class.to_s.downcase
object_name
end
end
# Renders a partial hash based on another rabl template
# partial("users/show", :object => @user)
# options must have :object
# options can have :view_path, :child_root, :root
def partial(file, options={}, &block)
object, view_path = options.delete(:object), options.delete(:view_path)
source, location = self.fetch_source(file, :view_path => view_path)
engine_options = options.merge(:source => source, :source_location => location)
self.object_to_hash(object, engine_options, &block)
end
# Returns a hash based representation of any data object given ejs template block
# object_to_hash(@user) { attribute :full_name } => { ... }
# object_to_hash(@user, :source => "...") { attribute :full_name } => { ... }
# options must have :source (rabl file contents)
# options can have :source_location (source filename)
def object_to_hash(object, options={}, &block)
return object unless is_object?(object) || is_collection?(object)
engine_options = options.merge(:format => "hash", :root => (options[:root] || false))
Rabl::Engine.new(options[:source], engine_options).render(@_scope, :object => object, &block)
end
# resolve_condition(:if => true) => true
# resolve_condition(:if => lambda { |m| false }) => false
# resolve_condition(:unless => lambda { |m| true }) => true
def resolve_condition(options)
return true if options[:if].nil? && options[:unless].nil?
result = options[:if] == true || (options[:if].respond_to?(:call) && options[:if].call(@_object)) if options.has_key?(:if)
result = options[:unless] == false || (options[:unless].respond_to?(:call) && !options[:unless].call(@_object)) if options.has_key?(:unless)
result
end
# Returns true if obj is not enumerable
# is_object?(@user) => true
# is_object?([]) => false
# is_object?({}) => false
def is_object?(obj)
obj && !data_object(obj).is_a?(Enumerable)
end
# Returns true if the obj is a collection of items
def is_collection?(obj)
obj && data_object(obj).is_a?(Enumerable)
end
# Returns source for a given relative file
# fetch_source("show", :view_path => "...") => "...contents..."
def fetch_source(file, options={})
if defined? Rails
root_path = Rails.root
view_path = options[:view_path] || File.join(root_path, "app/views/")
file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
elsif defined? Padrino
root_path = Padrino.root
# use Padrino's own template resolution mechanism
file_path, _ = @_scope.instance_eval { resolve_template(file) }
# Padrino chops the extension, stitch it back on
file_path = File.join(@_scope.settings.views, (file_path.to_s + ".rabl"))
elsif defined? Sinatra
view_path = options[:view_path] || @_scope.settings.views
file_path = Dir[File.join(view_path, file + ".{*.,}rabl")].first
end
if file_path
return File.read(file_path.to_s), file_path.to_s
else # no file path specified
nil
end
end
end
end