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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
class Gon
module Jbuilder
class << self
def handler(args, global = false)
options = parse_options_from args
if global && !options[:template]
raise 'You should provide :template when use rabl with global variables'
end
controller = Gon::Base.get_controller(options)
@_controller_name = global ? '' : controller.controller_path
include_helpers
data = parse_jbuilder \
Gon::Base.get_template_path(options, 'jbuilder'),
controller,
options[:locals]
[data, options]
end
private
def include_helpers
unless self.class.include? ::ActionView::Helpers
self.class.send(:include, ::ActionView::Helpers)
end
end
def parse_options_from(args)
if old_api? args
text = "[DEPRECATION] view_path argument is now optional. "
text << "If you need to specify it, "
text << "please use gon.rabl(:template => 'path')"
warn text
args.extract_options!.merge(:template => args[0])
elsif new_api? args
args.first
else
{}
end
end
def old_api?(args)
args.first.is_a? String
end
def new_api?(args)
args.first.is_a? Hash
end
def parse_jbuilder(jbuilder_path, controller, locals)
controller.instance_variables.each do |name|
self.instance_variable_set \
name,
controller.instance_variable_get(name)
end
locals ||= {}
locals.each do |name, value|
self.class.class_eval do
define_method "#{name}" do
return value
end
end
end
lines = find_partials File.readlines(jbuilder_path)
source = lines.join('')
output = parse_source source, controller
end
def parse_source(source, controller)
output = ::JbuilderTemplate.encode(controller) do |json|
eval source
end
JSON.parse(output)
end
def parse_partial(partial_line)
path = partial_line.match(/['"]([^'"]*)['"]/)[1]
path = parse_path path
options_hash = partial_line.match(/,(.*)/)[1]
set_options_from_hash(options_hash) if options_hash.present?
find_partials File.readlines(path)
end
def set_options_from_hash(options_hash)
options = eval "{#{options_hash}}"
options.each do |name, val|
self.instance_variable_set("@#{name.to_s}", val)
eval "def #{name}; self.instance_variable_get('@' + '#{name.to_s}'); end"
end
end
def parse_path(path)
return path if File.exists?(path)
splitted = path.split('/')
if splitted.size == 2
tmp_path = construct_path(splitted[0], splitted[1])
return tmp_path if tmp_path
elsif splitted.size == 1
tmp_path = construct_path(@_controller_name, splitted[0])
return tmp_path if tmp_path
end
raise 'Something wrong with partial path in your jbuilder templates'
end
def construct_path(part1, part2)
tmp_path = "app/views/#{part1}/_#{part2}"
tmp_path = path_with_ext(tmp_path)
return tmp_path if tmp_path
tmp_path = "app/views/#{part1}/#{part2}"
tmp_path = path_with_ext(tmp_path)
return tmp_path if tmp_path
end
def path_with_ext(path)
return path if File.exists?(path)
return "#{path}.jbuilder" if File.exists?("#{path}.jbuilder")
return "#{path}.json.jbuilder" if File.exists?("#{path}.json.jbuilder")
end
def find_partials(lines = [])
lines.map do |line|
if line =~ /partial!/
parse_partial line
else
line
end
end.flatten
end
end
end
end
|