pivotal-erector 0.5.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.
Files changed (42) hide show
  1. data/README.txt +81 -0
  2. data/VERSION.yml +4 -0
  3. data/bin/erect +7 -0
  4. data/lib/erector/erect.rb +148 -0
  5. data/lib/erector/erected.rb +63 -0
  6. data/lib/erector/extensions/object.rb +18 -0
  7. data/lib/erector/indenting.rb +36 -0
  8. data/lib/erector/rails/extensions/action_controller/1.2.5/action_controller.rb +17 -0
  9. data/lib/erector/rails/extensions/action_controller/2.2.0/action_controller.rb +26 -0
  10. data/lib/erector/rails/extensions/action_controller.rb +8 -0
  11. data/lib/erector/rails/extensions/action_view.rb +21 -0
  12. data/lib/erector/rails/extensions/widget/1.2.5/widget.rb +18 -0
  13. data/lib/erector/rails/extensions/widget/2.2.0/widget.rb +36 -0
  14. data/lib/erector/rails/extensions/widget.rb +117 -0
  15. data/lib/erector/rails/supported_rails_versions.rb +14 -0
  16. data/lib/erector/rails/template_handlers/1.2.5/action_view_template_handler.rb +32 -0
  17. data/lib/erector/rails/template_handlers/2.0.0/action_view_template_handler.rb +36 -0
  18. data/lib/erector/rails/template_handlers/2.1.0/action_view_template_handler.rb +31 -0
  19. data/lib/erector/rails/template_handlers/2.2.0/action_view_template_handler.rb +46 -0
  20. data/lib/erector/rails/template_handlers/action_view_template_handler.rb +14 -0
  21. data/lib/erector/rails.rb +6 -0
  22. data/lib/erector/raw_string.rb +8 -0
  23. data/lib/erector/rhtml.treetop +156 -0
  24. data/lib/erector/unicode.rb +18185 -0
  25. data/lib/erector/unicode_builder.rb +67 -0
  26. data/lib/erector/version.rb +10 -0
  27. data/lib/erector/widget.rb +510 -0
  28. data/lib/erector/widgets/table.rb +96 -0
  29. data/lib/erector/widgets.rb +2 -0
  30. data/lib/erector.rb +16 -0
  31. data/spec/core_spec_suite.rb +3 -0
  32. data/spec/erect/erect_spec.rb +145 -0
  33. data/spec/erect/erected_spec.rb +80 -0
  34. data/spec/erect/rhtml_parser_spec.rb +318 -0
  35. data/spec/erector/indentation_spec.rb +136 -0
  36. data/spec/erector/unicode_builder_spec.rb +75 -0
  37. data/spec/erector/widget_spec.rb +657 -0
  38. data/spec/erector/widgets/table_spec.rb +99 -0
  39. data/spec/rails_spec_suite.rb +3 -0
  40. data/spec/spec_helper.rb +54 -0
  41. data/spec/spec_suite.rb +45 -0
  42. metadata +118 -0
data/README.txt ADDED
@@ -0,0 +1,81 @@
1
+ = Erector
2
+
3
+ * http://erector.rubyforge.org
4
+ * mailto:erector-devel@rubyforge.org
5
+ * http://www.pivotaltracker.com/projects/482
6
+
7
+ == DESCRIPTION
8
+
9
+ Erector is a Builder-like view framework, inspired by Markaby but overcoming
10
+ some of its flaws. In Erector all views are objects, not template files,
11
+ which allows the full power of object-oriented programming (inheritance,
12
+ modular decomposition, encapsulation) in views. See the rdoc for the
13
+ Erector::Widget class to learn how to make your own widgets, and visit the
14
+ project site at http://erector.rubyforge.org for more documentation.
15
+
16
+ == SYNOPSIS
17
+
18
+ require 'erector'
19
+
20
+ class Hello < Erector::Widget
21
+ def render
22
+ html do
23
+ head do
24
+ title "Hello"
25
+ end
26
+ body do
27
+ text "Hello, "
28
+ b "world!", :class => 'big'
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ Hello.new.to_s
35
+ => "<html><head><title>Hello</title></head><body>Hello, <b class=\"big\">world!</b></body></html>"
36
+
37
+ == REQUIREMENTS
38
+
39
+ The gem depends on rake and treetop, although this is just for using the "erect" tool,
40
+ so deployed applications won't need these. Currently it also requires rails, although
41
+ we plan to separate the rails-dependent code so you can use Erector cleanly in a non-Rails app.
42
+
43
+ == INSTALL
44
+
45
+ To install as a gem:
46
+
47
+ * sudo gem install erector
48
+
49
+ Then add "require 'erector'" to any files which need erector.
50
+
51
+ To install as a Rails plugin:
52
+
53
+ * Copy the erector source to vendor/plugins/erector in your Rails directory.
54
+
55
+ When installing this way, erector is automatically available to your Rails code
56
+ (no require directive is needed).
57
+
58
+ == LICENSE:
59
+
60
+ (The MIT License)
61
+
62
+ Copyright (c) 2007-8 Pivotal Labs
63
+
64
+ Permission is hereby granted, free of charge, to any person obtaining
65
+ a copy of this software and associated documentation files (the
66
+ "Software"), to deal in the Software without restriction, including
67
+ without limitation the rights to use, copy, modify, merge, publish,
68
+ distribute, sublicense, and/or sell copies of the Software, and to
69
+ permit persons to whom the Software is furnished to do so, subject to
70
+ the following conditions:
71
+
72
+ The above copyright notice and this permission notice shall be
73
+ included in all copies or substantial portions of the Software.
74
+
75
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
76
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
77
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
78
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
79
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
80
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
81
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 5
4
+ :patch: 1
data/bin/erect ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ dir = File.expand_path(File.dirname(__FILE__))
3
+ $LOAD_PATH.unshift("#{dir}/../lib")
4
+ require "erector"
5
+ require "erector/erect"
6
+
7
+ Erector::Erect.new(ARGV).run
@@ -0,0 +1,148 @@
1
+ require "optparse"
2
+ require "rake"
3
+ require "erector/erected" # pull this out so we don't recreate the grammar every time
4
+
5
+ module Erector
6
+ class Erect
7
+ attr_reader :files, :verbose, :mode, :output_dir
8
+ def initialize(args)
9
+ @verbose = true
10
+ @mode = :to_erector
11
+ @output_dir = nil
12
+
13
+ opts = OptionParser.new do |opts|
14
+ opts.banner = "Usage: erect [options] [file|dir]*"
15
+
16
+ opts.separator "Converts from html/rhtml files to erector widgets, or from erector widgets to html files"
17
+ opts.separator ""
18
+ opts.separator "Options:"
19
+
20
+ opts.on("-q", "--quiet",
21
+ "Operate silently except in case of error") do |quiet|
22
+ @verbose = !quiet
23
+ end
24
+
25
+ opts.on("--to-erector", "(default) Convert from html/rhtml to erector classes") do
26
+ @mode = :to_erector
27
+ end
28
+
29
+ opts.on("--to-html", "Convert from erector to html") do
30
+ @mode = :to_html
31
+ end
32
+
33
+ opts.on("-o", "--output-dir DIRECTORY", "Output files to DIRECTORY (default: output files go next to input files)") do |dir|
34
+ @output_dir = dir
35
+ end
36
+
37
+ opts.on_tail("-h", "--help", "Show this message") do
38
+ @mode = :help
39
+ puts opts
40
+ exit
41
+ end
42
+
43
+ opts.on_tail("-v", "--version", "Show version") do
44
+ puts Erector::VERSION
45
+ exit
46
+ end
47
+
48
+ end
49
+ opts.parse!(args)
50
+ @files = args
51
+ explode_dirs
52
+ end
53
+
54
+ def say(msg)
55
+ print msg if verbose
56
+ end
57
+
58
+ #todo: unit test
59
+ def explode_dirs
60
+ exploded_files = FileList.new
61
+ files.each do |file|
62
+ if File.directory?(file)
63
+ exploded_files.add(explode(file))
64
+ else
65
+ exploded_files.add(file)
66
+ end
67
+ end
68
+ @files = exploded_files
69
+ end
70
+
71
+ def explode(dir)
72
+ case mode
73
+ when :to_erector
74
+ FileList["#{dir}/**/*.rhtml", "#{dir}/**/*.html", "#{dir}/**/*.html.erb"]
75
+ when :to_html
76
+ FileList["#{dir}/**/*.rb"]
77
+ end
78
+ end
79
+
80
+ def run
81
+ self.send(mode)
82
+ end
83
+
84
+ def to_erector
85
+ files.each do |file|
86
+ say "Erecting #{file}... "
87
+ begin
88
+ e = Erector::Erected.new(file)
89
+ e.convert
90
+ say " --> #{e.filename}\n"
91
+ rescue => e
92
+ puts e
93
+ puts e.backtrace.join("\n\t")
94
+ puts
95
+ end
96
+ end
97
+ end
98
+
99
+ def to_html
100
+ files.each do |file|
101
+ say "Erecting #{file}... "
102
+ #todo: move this into Erected with better tests for the naming methods
103
+ begin
104
+ #todo: fail if file isn't a .rb file
105
+ require file
106
+ #todo: understand modulized widgets (e.g. class Foo::Bar::Baz < Erector::Widget in baz.rb)
107
+ filename = file.split('/').last.gsub(/\.rb$/, '')
108
+ widget_name = camelize(filename)
109
+ widget_class = constantize(widget_name)
110
+
111
+ if widget_class < Erector::Widget
112
+ widget = widget_class.new
113
+ #todo: skip if it's missing a no-arg constructor
114
+ dir = output_dir || File.dirname(file)
115
+ FileUtils.mkdir_p(dir)
116
+ output_file = "#{dir}/#{filename}.html"
117
+ File.open(output_file, "w") do |f|
118
+ f.puts widget.to_s
119
+ end
120
+ say " --> #{output_file}\n"
121
+ else
122
+ say " -- not a widget, skipping\n"
123
+ end
124
+ rescue => e
125
+ puts e
126
+ puts e.backtrace.join("\n\t")
127
+ end
128
+ end
129
+ end
130
+
131
+ # stolen from activesuppport/lib/inflector.rb
132
+ def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
133
+ if first_letter_in_uppercase
134
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
135
+ else
136
+ lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
137
+ end
138
+ end
139
+ def constantize(camel_cased_word)
140
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
141
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
142
+ end
143
+ Object.module_eval("::#{$1}", __FILE__, __LINE__)
144
+ end
145
+
146
+
147
+ end
148
+ end
@@ -0,0 +1,63 @@
1
+ require 'rubygems'
2
+ require 'treetop'
3
+ dir = File.dirname(__FILE__)
4
+ require "#{dir}/indenting"
5
+ Treetop.load("#{dir}/rhtml.treetop")
6
+
7
+ module Erector
8
+ class Erected
9
+ def initialize(in_file)
10
+ @in_file = in_file
11
+ end
12
+
13
+ def filename
14
+ dir + basename + ".rb"
15
+ end
16
+
17
+ def classname
18
+ base = classize(basename)
19
+ parent = File.dirname(@in_file)
20
+ grandparent = File.dirname(parent)
21
+ if File.basename(grandparent) == "views"
22
+ base = "Views::" + classize(File.basename(parent)) + "::" + base
23
+ end
24
+ base
25
+ end
26
+
27
+ def text
28
+ File.read(@in_file)
29
+ end
30
+
31
+ def convert
32
+ parser = RhtmlParser.new
33
+ parsed = parser.parse(File.read(@in_file))
34
+ if parsed.nil?
35
+ raise "Could not parse #{@in_file}\n" +
36
+ parser.failure_reason
37
+ else
38
+ File.open(filename, "w") do |f|
39
+ f.puts("class #{classname} < Erector::Widget")
40
+ f.puts(" def render")
41
+ f.puts(parsed.set_indent(2).convert)
42
+ f.puts(" end")
43
+ f.puts("end")
44
+ end
45
+ end
46
+ end
47
+
48
+ protected
49
+
50
+ def basename
51
+ @in_file.split("/").last.gsub(/\..*$/, '')
52
+ end
53
+
54
+ def dir
55
+ x = File.dirname(@in_file)
56
+ return (x == ".") ? "" : "#{x}/"
57
+ end
58
+
59
+ def classize(filename)
60
+ filename.split("_").map{|part| part.capitalize}.join
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,18 @@
1
+ class Object
2
+ def metaclass
3
+ class << self; self; end
4
+ end
5
+
6
+ def html_escape
7
+ return CGI.escapeHTML(to_s)
8
+ end
9
+
10
+ def html_unescape
11
+ CGI.unescapeHTML(to_s)
12
+ end
13
+
14
+ def escape_single_quotes
15
+ self.gsub(/[']/, '\\\\\'')
16
+ end
17
+ end
18
+
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'treetop'
3
+
4
+ module Erector
5
+ class Indenting < Treetop::Runtime::SyntaxNode #:nodoc:
6
+ @@indent = 0
7
+
8
+ def set_indent(x)
9
+ @@indent = x
10
+ self
11
+ end
12
+
13
+ def indent
14
+ [0, @@indent].max
15
+ end
16
+
17
+ def indented(s)
18
+ " " * indent + s + "\n"
19
+ end
20
+
21
+ def line(s)
22
+ indented(s)
23
+ end
24
+
25
+ def line_in(s)
26
+ s = indented(s)
27
+ @@indent += 1
28
+ s
29
+ end
30
+
31
+ def line_out(s)
32
+ @@indent -= 1
33
+ indented(s)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ ActionController::Base.class_eval do
2
+ def render_widget(widget_class, assigns=@assigns)
3
+ @__widget_class = widget_class
4
+ @__widget_assigns = assigns
5
+ add_variables_to_assigns
6
+ render :inline => "<% @__widget_class.new(self, @__widget_assigns, _erbout).render %>"
7
+ end
8
+
9
+ def render_with_erector_widget(*options, &block)
10
+ if options.first.is_a?(Hash) && widget = options.first.delete(:widget)
11
+ render_widget widget, @assigns, &block
12
+ else
13
+ render_without_erector_widget *options, &block
14
+ end
15
+ end
16
+ alias_method_chain :render, :erector_widget
17
+ end
@@ -0,0 +1,26 @@
1
+ ActionController::Base.class_eval do
2
+ def render_widget(widget_class, assigns=nil)
3
+ @__widget_class = widget_class
4
+ if assigns
5
+ @__widget_assigns = assigns
6
+ else
7
+ @__widget_assigns = {}
8
+ variables = instance_variable_names
9
+ variables -= protected_instance_variables
10
+ variables.each do |name|
11
+ @__widget_assigns[name.sub('@', "")] = instance_variable_get(name)
12
+ end
13
+ end
14
+ response.template.send(:_evaluate_assigns_and_ivars)
15
+ render :inline => "<% @__widget_class.new(self, @__widget_assigns, output_buffer).render %>"
16
+ end
17
+
18
+ def render_with_erector_widget(*options, &block)
19
+ if options.first.is_a?(Hash) && widget = options.first.delete(:widget)
20
+ render_widget widget, @assigns, &block
21
+ else
22
+ render_without_erector_widget *options, &block
23
+ end
24
+ end
25
+ alias_method_chain :render, :erector_widget
26
+ end
@@ -0,0 +1,8 @@
1
+ dir = File.dirname(__FILE__)
2
+ if (
3
+ ActionController::Base.instance_methods + ActionController::Base.private_instance_methods).
4
+ include?("add_variables_to_assigns")
5
+ require File.expand_path("#{dir}/action_controller/1.2.5/action_controller")
6
+ else
7
+ require File.expand_path("#{dir}/action_controller/2.2.0/action_controller")
8
+ end
@@ -0,0 +1,21 @@
1
+ unless ActionView.const_defined?(:Template)
2
+ ActionView::Base.class_eval do
3
+ attr_reader :template_file_path
4
+ def render_template_with_saving_file_path(template_extension, template, file_path = nil, local_assigns = {})
5
+ @template_file_path = file_path
6
+ render_template_without_saving_file_path(template_extension, template, file_path, local_assigns)
7
+ end
8
+ alias_method_chain :render_template, :saving_file_path
9
+
10
+ def render_partial_with_notification(*args, &blk)
11
+ @is_partial_template = true
12
+ render_partial_without_notification(*args, &blk)
13
+ end
14
+ alias_method_chain :render_partial, :notification
15
+
16
+ def is_partial_template?
17
+ @is_partial_template || false
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,18 @@
1
+ module Erector
2
+ Widget.class_eval do
3
+ attr_reader :_erbout
4
+
5
+ after_initialize do
6
+ @_erbout = output
7
+ end
8
+
9
+ def define_javascript_functions(*args)
10
+ begin
11
+ text raw(helpers.define_javascript_functions(*args))
12
+ rescue => e
13
+ puts e.backtrace.join("\n\t")
14
+ raise e
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ module Erector
2
+ Widget.class_eval do
3
+ def output
4
+ process_output_buffer || @output
5
+ end
6
+
7
+ def capture_with_helpers(&block)
8
+ helpers ? helpers.capture(&block) : capture_without_helpers(&block)
9
+ end
10
+
11
+ alias_method_chain :capture, :helpers
12
+
13
+ # This is here to force #helpers.capture to return the output
14
+ def __in_erb_template; end
15
+
16
+ private
17
+
18
+ def process_output_buffer
19
+ if helpers.respond_to?(:output_buffer)
20
+ buffer = helpers.output_buffer
21
+ buffer.is_a?(String) ? buffer : handle_rjs_buffer
22
+ else
23
+ nil
24
+ end
25
+ end
26
+
27
+ def handle_rjs_buffer
28
+ returning buffer = helpers.output_buffer.dup.to_s do
29
+ helpers.output_buffer.clear
30
+ helpers.with_output_buffer(buffer) do
31
+ buffer << helpers.output_buffer.to_s
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,117 @@
1
+ module Erector
2
+ Widget.class_eval do
3
+ include ActionController::UrlWriter
4
+
5
+ # helpers returning raw text
6
+ [
7
+ :image_tag,
8
+ :javascript_include_tag,
9
+ :stylesheet_link_tag,
10
+ :sortable_element,
11
+ :sortable_element_js,
12
+ :text_field_with_auto_complete,
13
+ ].each do |helper_name|
14
+ define_method helper_name do |*args|
15
+ begin
16
+ text raw(helpers.send(helper_name, *args))
17
+ rescue => e
18
+ puts e.backtrace.join("\n\t")
19
+ raise e
20
+ end
21
+ end
22
+ end
23
+
24
+ # helpers returning raw text whose first parameter is HTML escaped
25
+ [
26
+ :link_to,
27
+ :link_to_remote,
28
+ :mail_to,
29
+ :button_to,
30
+ :submit_tag,
31
+ ].each do |helper_name|
32
+
33
+ method_def =<<-METHOD_DEF
34
+ def #{helper_name}(link_text, *args, &block)
35
+ text raw(helpers.#{helper_name}(h(link_text), *args, &block))
36
+ end
37
+ METHOD_DEF
38
+ eval(method_def)
39
+ end
40
+
41
+ def error_messages_for(*args)
42
+ text raw(helpers.error_messages_for(*args))
43
+ end
44
+
45
+ # return text, take block
46
+ [
47
+ :link_to_function,
48
+ :text_field_tag,
49
+ :password_field_tag,
50
+ :check_box_tag
51
+ ].each do |method_to_proxy_with_block|
52
+ method_def =<<-METHOD_DEF
53
+ def #{method_to_proxy_with_block}(*args, &block)
54
+ text raw(helpers.#{method_to_proxy_with_block}(*args, &block))
55
+ end
56
+ METHOD_DEF
57
+ eval(method_def)
58
+ end
59
+
60
+ # render text, take block
61
+ [
62
+ :error_messages_for,
63
+ :form_tag,
64
+ :form_for,
65
+ ].each do |method_to_proxy_with_block|
66
+ method_def =<<-METHOD_DEF
67
+ def #{method_to_proxy_with_block}(*args, &block)
68
+ helpers.#{method_to_proxy_with_block}(*args, &block)
69
+ end
70
+ METHOD_DEF
71
+ eval(method_def)
72
+ end
73
+
74
+ def javascript_include_merged(key)
75
+ helpers.javascript_include_merged(key)
76
+ end
77
+
78
+ def stylesheet_link_merged(key)
79
+ helpers.stylesheet_link_merged(key)
80
+ end
81
+
82
+ def flash
83
+ helpers.controller.send(:flash)
84
+ end
85
+
86
+ def session
87
+ helpers.controller.session
88
+ end
89
+
90
+ def controller
91
+ helpers.controller
92
+ end
93
+
94
+ def cycle(*args)
95
+ helpers.cycle(*args)
96
+ end
97
+
98
+ def simple_format(string)
99
+ p raw(string.to_s.html_escape.gsub(/\r\n?/, "\n").gsub(/\n/, "<br/>\n"))
100
+ end
101
+
102
+ def time_ago_in_words(*args)
103
+ helpers.time_ago_in_words(*args)
104
+ end
105
+
106
+ def pluralize(*args)
107
+ helpers.pluralize(*args)
108
+ end
109
+ end
110
+ end
111
+
112
+ dir = File.dirname(__FILE__)
113
+ if ActionView::Base.instance_methods.include?("output_buffer")
114
+ require "#{dir}/widget/2.2.0/widget"
115
+ else
116
+ require "#{dir}/widget/1.2.5/widget"
117
+ end
@@ -0,0 +1,14 @@
1
+ module Erector
2
+ module Rails
3
+ SUPPORTED_RAILS_VERSIONS = {
4
+ # "1.2.5" => {'version' => '1.2.5', 'git_tag' => 'v1.2.5'},
5
+ "1.99.0" => {'version' => '1.99.0', 'git_tag' => 'v2.0.0_RC1'},
6
+ "2.0.2" => {'version' => '2.0.2', 'git_tag' => 'v2.0.2'},
7
+ "2.1.0" => {'version' => '2.1.0', 'git_tag' => 'v2.1.0'},
8
+ "2.2.0" => {'version' => '2.2.0', 'git_tag' => 'v2.2.0'},
9
+ "2.2.2" => {'version' => '2.2.2', 'git_tag' => 'v2.2.2'},
10
+ "2.3.2" => {'version' => '2.3.2', 'git_tag' => 'v2.3.2'},
11
+ # "edge" => {'version' => 'edge', 'git_tag' => 'master'}, #TODO: Readd edge support
12
+ }
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ module ActionView #:nodoc:
2
+ module TemplateHandlers #:nodoc:
3
+ class Erector
4
+ def self.line_offset
5
+ 2
6
+ end
7
+
8
+ attr_reader :view
9
+ def initialize(view)
10
+ @view = view
11
+ end
12
+
13
+ def compilable?
14
+ true
15
+ end
16
+
17
+ ActionView::Base.register_template_handler :rb, ActionView::TemplateHandlers::Erector
18
+
19
+ def render(template, local_assigns)
20
+ relative_path_parts = view.first_render.split('/')
21
+ require_dependency view.template_file_path
22
+
23
+ dot_rb = /\.rb$/
24
+ widget_class = relative_path_parts.inject(Views) do |mod, node|
25
+ mod.const_get(node.gsub(dot_rb, '').gsub(".html", "").camelize)
26
+ end
27
+ render_method = view.is_partial_template? ? 'render_partial' : 'render'
28
+ widget_class.new(view, view.assigns).to_s(render_method)
29
+ end
30
+ end
31
+ end
32
+ end