render_me_pretty 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +7 -1
- data/lib/render_me_pretty/context.rb +115 -0
- data/lib/render_me_pretty/erb.rb +30 -0
- data/lib/render_me_pretty/version.rb +1 -1
- data/lib/render_me_pretty.rb +6 -138
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0ca366dbc0b626c3bd1fa15b7d83f8d29ab4b22a0eabd35dc6d1c68604b0925
|
4
|
+
data.tar.gz: 18a6fbec659aa7d6fde4053277aa10d5836d7703d38e2b9b29e78399a921b264
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71a16eef148da71913f34478c8981915f8844e4586344771fd490d21f61c7f5cbd3a22d83f5b61deedad188f04b696372cca8b8185687ab9e44e058751554a36
|
7
|
+
data.tar.gz: 6e68c1e4fa8c5d1fd0e133b1e4d0ec44d708deaccd888b5ba23fadd49cec30d74b1918b6d48de921be49face3ed28013309d0bfac6695515f10dcb40904743a6
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
|
5
|
+
|
6
|
+
## [0.2.0]
|
7
|
+
- add RenderMePretty.result convenience class method
|
8
|
+
|
9
|
+
## [0.1.0]
|
10
|
+
- initial release
|
11
|
+
|
data/README.md
CHANGED
@@ -39,7 +39,13 @@ erb = RenderMePretty::Erb.new("/path/to/tempate.erb", a: 3) }
|
|
39
39
|
erb.render(a: 4)
|
40
40
|
```
|
41
41
|
|
42
|
-
|
42
|
+
There's also a convenience class method:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
RenderMePretty.result("/path/to/tempate.erb", a: 5)
|
46
|
+
```
|
47
|
+
|
48
|
+
A few more examples are in the [erb_spec.rb](spec/lib/render_me_pretty/erb_spec.rb)
|
43
49
|
|
44
50
|
## Installation
|
45
51
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require "active_support/core_ext/string"
|
2
|
+
require "colorize"
|
3
|
+
|
4
|
+
=begin
|
5
|
+
## Usage examples:
|
6
|
+
|
7
|
+
Given an example template /path/to/template.erb that contains:
|
8
|
+
|
9
|
+
a: <%= @a %>
|
10
|
+
|
11
|
+
### Variables at initialization
|
12
|
+
|
13
|
+
erb = RenderMePretty::Erb.new("/path/to/template.erb", a: 1)
|
14
|
+
erb.render
|
15
|
+
|
16
|
+
Result: a: 1
|
17
|
+
|
18
|
+
### Variables at render time
|
19
|
+
|
20
|
+
erb = RenderMePretty::Erb.new("/path/to/template.erb")
|
21
|
+
erb.render(a: 2)
|
22
|
+
|
23
|
+
Result: a: 2
|
24
|
+
|
25
|
+
### Variables at both initialization and render time:
|
26
|
+
|
27
|
+
erb = RenderMePretty::Erb.new("/path/to/template.erb", a: 3)
|
28
|
+
erb.render(a: "override", a: 4)
|
29
|
+
|
30
|
+
Result: a: 4
|
31
|
+
|
32
|
+
Variables at render time will override variables at initialization time.
|
33
|
+
|
34
|
+
## Context Helpers
|
35
|
+
|
36
|
+
When no context is provided, a built-in context object is created. You can add helpers to the built-in context object with:
|
37
|
+
|
38
|
+
RenderMePretty::Context.load_helpers("lib/helpers")
|
39
|
+
|
40
|
+
This loads modules defined in `lib/helpers` folder and adds their methods of the built-in context object. The helper classes must be defined with the following convetion: FooHelper and foo_helper.rb.
|
41
|
+
|
42
|
+
Note, helpers will only work with the built-in context scope. If you are passing in your own context object to be used, then you should handle adding helper methods to that context object yourself.
|
43
|
+
|
44
|
+
## Custom Context Scope
|
45
|
+
|
46
|
+
A built-in context object is provided for convenience. If you want to use your own context object, pass it as a variable. The context variable is specially treated as a context object. Example:
|
47
|
+
|
48
|
+
person = Person.new # must implement get_binding
|
49
|
+
erb = RenderMePretty::Erb.new("/path/to/template.erb")
|
50
|
+
erb.render(context: person, a: 2)
|
51
|
+
|
52
|
+
The context will be `person`. So person methods and instance variables will be available in the ERB templates.
|
53
|
+
|
54
|
+
=end
|
55
|
+
module RenderMePretty
|
56
|
+
class Erb
|
57
|
+
def initialize(path, variables={})
|
58
|
+
@path = path
|
59
|
+
@variables = variables
|
60
|
+
if variables[:context]
|
61
|
+
@context = variables.delete(:context)
|
62
|
+
else
|
63
|
+
@context = Context.new(variables)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def render(override_vars={})
|
68
|
+
@context.override_variables!(override_vars)
|
69
|
+
template = IO.read(@path)
|
70
|
+
ERB.new(template, nil, "-").result(@context.get_binding)
|
71
|
+
rescue Exception => e
|
72
|
+
handle_exception(e)
|
73
|
+
end
|
74
|
+
|
75
|
+
# How to know where ERB stopped? - https://www.ruby-forum.com/topic/182051
|
76
|
+
# syntax errors have the (erb):xxx info in e.message
|
77
|
+
# undefined variables have (erb):xxx info in e.backtrace
|
78
|
+
def handle_exception(e)
|
79
|
+
error_info = e.message.split("\n").grep(/\(erb\)/)[0]
|
80
|
+
error_info ||= e.backtrace.grep(/\(erb\)/)[0]
|
81
|
+
raise unless error_info # unable to find the (erb):xxx: error line
|
82
|
+
|
83
|
+
line = error_info.split(':')[1].to_i
|
84
|
+
io = StringIO.new
|
85
|
+
io.puts "#{e.class} evaluating ERB template on line #{line.to_s.colorize(:red)} of: #{@path.sub(/^\.\//, '')}"
|
86
|
+
|
87
|
+
template = IO.read(@path)
|
88
|
+
template_lines = template.split("\n")
|
89
|
+
context = 5 # lines of context
|
90
|
+
top, bottom = [line-context-1, 0].max, line+context-1
|
91
|
+
spacing = template_lines.size.to_s.size
|
92
|
+
template_lines[top..bottom].each_with_index do |line_content, index|
|
93
|
+
line_number = top+index+1
|
94
|
+
if line_number == line
|
95
|
+
io.printf("%#{spacing}d %s\n".colorize(:red), line_number, line_content)
|
96
|
+
else
|
97
|
+
io.printf("%#{spacing}d %s\n", line_number, line_content)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Append the original stack trace also
|
102
|
+
io.puts("\nOriginal backtrace (last 5 lines):")
|
103
|
+
lines = ENV['FULL_STACK_TRACE'] ? e.backtrace : e.backtrace[0..4]
|
104
|
+
io.write(lines.join("\n"))
|
105
|
+
io.puts("\nRe-run with FULL_STACK_TRACE=1 to see all lines")
|
106
|
+
|
107
|
+
if ENV['TEST']
|
108
|
+
io.string
|
109
|
+
else
|
110
|
+
puts io.string
|
111
|
+
exit 1
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RenderMePretty
|
2
|
+
class Context
|
3
|
+
def initialize(hash={})
|
4
|
+
# http://stackoverflow.com/questions/1338960/ruby-templates-how-to-pass-variables-into-inlined-erb
|
5
|
+
hash.each do |key, value|
|
6
|
+
instance_variable_set('@' + key.to_s, value)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def override_variables!(vars)
|
11
|
+
vars.each do |key, value|
|
12
|
+
instance_variable_set('@' + key.to_s, value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_binding
|
17
|
+
binding
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.load_helpers(base_folder)
|
21
|
+
Dir.glob("#{base_folder}/**/*_helper.rb").each do |path|
|
22
|
+
relative_path = path.sub("#{base_folder}/", "")
|
23
|
+
class_name = File.basename(relative_path, '.rb').classify
|
24
|
+
|
25
|
+
require path
|
26
|
+
include const_get(class_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/render_me_pretty.rb
CHANGED
@@ -1,145 +1,13 @@
|
|
1
1
|
require "render_me_pretty/version"
|
2
|
-
require "active_support/core_ext/string"
|
3
|
-
require "colorize"
|
4
2
|
|
5
|
-
=begin
|
6
|
-
## Usage examples:
|
7
|
-
|
8
|
-
Given an example template /path/to/template.erb that contains:
|
9
|
-
|
10
|
-
a: <%= @a %>
|
11
|
-
|
12
|
-
### Variables at initialization
|
13
|
-
|
14
|
-
erb = RenderMePretty::Erb.new("/path/to/template.erb", a: 1)
|
15
|
-
erb.render
|
16
|
-
|
17
|
-
Result: a: 1
|
18
|
-
|
19
|
-
### Variables at render time
|
20
|
-
|
21
|
-
erb = RenderMePretty::Erb.new("/path/to/template.erb")
|
22
|
-
erb.render(a: 2)
|
23
|
-
|
24
|
-
Result: a: 2
|
25
|
-
|
26
|
-
### Variables at both initialization and render time:
|
27
|
-
|
28
|
-
erb = RenderMePretty::Erb.new("/path/to/template.erb", a: 3)
|
29
|
-
erb.render(a: "override", a: 4)
|
30
|
-
|
31
|
-
Result: a: 4
|
32
|
-
|
33
|
-
Variables at render time will override variables at initialization time.
|
34
|
-
|
35
|
-
## Context Helpers
|
36
|
-
|
37
|
-
When no context is provided, a built-in context object is created. You can add helpers to the built-in context object with:
|
38
|
-
|
39
|
-
RenderMePretty::Context.load_helpers("lib/helpers")
|
40
|
-
|
41
|
-
This loads modules defined in `lib/helpers` folder and adds their methods of the built-in context object. The helper classes must be defined with the following convetion: FooHelper and foo_helper.rb.
|
42
|
-
|
43
|
-
Note, helpers will only work with the built-in context scope. If you are passing in your own context object to be used, then you should handle adding helper methods to that context object yourself.
|
44
|
-
|
45
|
-
## Custom Context Scope
|
46
|
-
|
47
|
-
A built-in context object is provided for convenience. If you want to use your own context object, pass it as a variable. The context variable is specially treated as a context object. Example:
|
48
|
-
|
49
|
-
person = Person.new # must implement get_binding
|
50
|
-
erb = RenderMePretty::Erb.new("/path/to/template.erb")
|
51
|
-
erb.render(context: person, a: 2)
|
52
|
-
|
53
|
-
The context will be `person`. So person methods and instance variables will be available in the ERB templates.
|
54
|
-
|
55
|
-
=end
|
56
3
|
module RenderMePretty
|
57
|
-
|
58
|
-
|
59
|
-
@path = path
|
60
|
-
@variables = variables
|
61
|
-
if variables[:context]
|
62
|
-
@context = variables.delete(:context)
|
63
|
-
else
|
64
|
-
@context = Context.new(variables)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def render(override_vars={})
|
69
|
-
@context.override_variables!(override_vars)
|
70
|
-
template = IO.read(@path)
|
71
|
-
ERB.new(template, nil, "-").result(@context.get_binding)
|
72
|
-
rescue Exception => e
|
73
|
-
handle_exception(e)
|
74
|
-
end
|
75
|
-
|
76
|
-
# How to know where ERB stopped? - https://www.ruby-forum.com/topic/182051
|
77
|
-
# syntax errors have the (erb):xxx info in e.message
|
78
|
-
# undefined variables have (erb):xxx info in e.backtrace
|
79
|
-
def handle_exception(e)
|
80
|
-
error_info = e.message.split("\n").grep(/\(erb\)/)[0]
|
81
|
-
error_info ||= e.backtrace.grep(/\(erb\)/)[0]
|
82
|
-
raise unless error_info # unable to find the (erb):xxx: error line
|
4
|
+
autoload :Erb, 'render_me_pretty/erb'
|
5
|
+
autoload :Context, 'render_me_pretty/context'
|
83
6
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
template = IO.read(@path)
|
89
|
-
template_lines = template.split("\n")
|
90
|
-
context = 5 # lines of context
|
91
|
-
top, bottom = [line-context-1, 0].max, line+context-1
|
92
|
-
spacing = template_lines.size.to_s.size
|
93
|
-
template_lines[top..bottom].each_with_index do |line_content, index|
|
94
|
-
line_number = top+index+1
|
95
|
-
if line_number == line
|
96
|
-
io.printf("%#{spacing}d %s\n".colorize(:red), line_number, line_content)
|
97
|
-
else
|
98
|
-
io.printf("%#{spacing}d %s\n", line_number, line_content)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Append the original stack trace also
|
103
|
-
io.puts("\nOriginal backtrace (last 5 lines):")
|
104
|
-
lines = ENV['FULL_STACK_TRACE'] ? e.backtrace : e.backtrace[0..4]
|
105
|
-
io.write(lines.join("\n"))
|
106
|
-
io.puts("\nRe-run with FULL_STACK_TRACE=1 to see all lines")
|
107
|
-
|
108
|
-
if ENV['TEST']
|
109
|
-
io.string
|
110
|
-
else
|
111
|
-
puts io.string
|
112
|
-
exit 1
|
113
|
-
end
|
114
|
-
end
|
7
|
+
def self.result(path, variables={})
|
8
|
+
erb = Erb.new(path, variables={})
|
9
|
+
erb.render
|
115
10
|
end
|
116
11
|
|
117
|
-
|
118
|
-
class Context
|
119
|
-
def initialize(hash={})
|
120
|
-
hash.each do |key, value|
|
121
|
-
instance_variable_set('@' + key.to_s, value)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def override_variables!(vars)
|
126
|
-
vars.each do |key, value|
|
127
|
-
instance_variable_set('@' + key.to_s, value)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def get_binding
|
132
|
-
binding
|
133
|
-
end
|
134
|
-
|
135
|
-
def self.load_helpers(base_folder)
|
136
|
-
Dir.glob("#{base_folder}/**/*_helper.rb").each do |path|
|
137
|
-
relative_path = path.sub("#{base_folder}/", "")
|
138
|
-
class_name = File.basename(relative_path, '.rb').classify
|
139
|
-
|
140
|
-
require path
|
141
|
-
include const_get(class_name)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
12
|
+
extend self
|
145
13
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: render_me_pretty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
@@ -89,6 +89,7 @@ extra_rdoc_files: []
|
|
89
89
|
files:
|
90
90
|
- ".gitignore"
|
91
91
|
- ".rspec"
|
92
|
+
- CHANGELOG.md
|
92
93
|
- Gemfile
|
93
94
|
- Gemfile.lock
|
94
95
|
- README.md
|
@@ -96,6 +97,8 @@ files:
|
|
96
97
|
- bin/console
|
97
98
|
- bin/setup
|
98
99
|
- lib/render_me_pretty.rb
|
100
|
+
- lib/render_me_pretty/context.rb
|
101
|
+
- lib/render_me_pretty/erb.rb
|
99
102
|
- lib/render_me_pretty/version.rb
|
100
103
|
- render_me_pretty.gemspec
|
101
104
|
- tilt_examples.rb
|