File: jbuilder.rb

package info (click to toggle)
ruby-gon 5.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 496 kB
  • ctags: 145
  • sloc: ruby: 1,416; makefile: 5
file content (141 lines) | stat: -rw-r--r-- 3,926 bytes parent folder | download
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