rapid-core 0.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.
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +53 -0
- data/Rakefile +61 -0
- data/cucumber.yml +3 -0
- data/doc/plan.txt +89 -0
- data/doc/scaffold/controller.rb +83 -0
- data/doc/scaffold/helper.rb +2 -0
- data/doc/scaffold/model.rb +5 -0
- data/doc/scaffold/rapid_scaffold.rb +5 -0
- data/doc/scaffold/views/_form.html.erb +25 -0
- data/doc/scaffold/views/edit.html.erb +6 -0
- data/doc/scaffold/views/index.html.erb +25 -0
- data/doc/scaffold/views/new.html.erb +5 -0
- data/doc/scaffold/views/show.html.erb +15 -0
- data/features/settings/boolean/default.feature +36 -0
- data/features/settings/double-nested/default.feature +50 -0
- data/features/settings/double-nested/if.feature +41 -0
- data/features/settings/double-nested/unless.feature +39 -0
- data/features/settings/double-nested/validates/exclusion_of.feature +30 -0
- data/features/settings/double-nested/validates/format_of.feature +30 -0
- data/features/settings/double-nested/validates/inclusion_of.feature +30 -0
- data/features/settings/double-nested/validates/length_of.feature +30 -0
- data/features/settings/double-nested/validates/presence_of.feature +37 -0
- data/features/settings/double-nested/validates/size_of.feature +30 -0
- data/features/settings/integer/default.feature +49 -0
- data/features/settings/nested/default.feature +50 -0
- data/features/settings/nested/if.feature +53 -0
- data/features/settings/nested/unless.feature +32 -0
- data/features/settings/nested/validates/exclusion_of.feature +30 -0
- data/features/settings/nested/validates/format_of.feature +30 -0
- data/features/settings/nested/validates/inclusion_of.feature +30 -0
- data/features/settings/nested/validates/length_of.feature +30 -0
- data/features/settings/nested/validates/presence_of.feature +37 -0
- data/features/settings/nested/validates/size_of.feature +30 -0
- data/features/settings/not_found.feature +33 -0
- data/features/settings/string/default.feature +36 -0
- data/features/settings/string/validates/exclusion_of.feature +30 -0
- data/features/settings/string/validates/format_of.feature +30 -0
- data/features/settings/string/validates/inclusion_of.feature +30 -0
- data/features/settings/string/validates/length_of.feature +30 -0
- data/features/settings/string/validates/presence_of.feature +37 -0
- data/features/settings/string/validates/size_of.feature +30 -0
- data/features/step_definitions/settings_steps.rb +92 -0
- data/features/step_definitions/skeleton_steps.rb +68 -0
- data/features/step_definitions/template_steps.rb +39 -0
- data/features/support/env.rb +6 -0
- data/features/templates/comment_if.feature +55 -0
- data/features/templates/comment_unless.feature +56 -0
- data/features/templates/for/for.feature +51 -0
- data/features/templates/if/else.feature +60 -0
- data/features/templates/if/elsif.feature +82 -0
- data/features/templates/if/if.feature +55 -0
- data/features/templates/namespaces/exist.feature +54 -0
- data/features/templates/static.feature +37 -0
- data/features/templates/variables.feature +61 -0
- data/lib/rapid/check.rb +162 -0
- data/lib/rapid/core.rb +37 -0
- data/lib/rapid/error.rb +84 -0
- data/lib/rapid/module.rb +35 -0
- data/lib/rapid/railtie.rb +18 -0
- data/lib/rapid/setting/base.rb +35 -0
- data/lib/rapid/setting/boolean_setting.rb +17 -0
- data/lib/rapid/setting/class_hash.rb +34 -0
- data/lib/rapid/setting/comments.rb +25 -0
- data/lib/rapid/setting/definer.rb +151 -0
- data/lib/rapid/setting/instance_hash.rb +132 -0
- data/lib/rapid/setting/instance_root.rb +107 -0
- data/lib/rapid/setting/integer_setting.rb +24 -0
- data/lib/rapid/setting/namespace/base.rb +113 -0
- data/lib/rapid/setting/namespace/instance.rb +84 -0
- data/lib/rapid/setting/nested_validations.rb +86 -0
- data/lib/rapid/setting/string_setting.rb +13 -0
- data/lib/rapid/settings.rb +129 -0
- data/lib/rapid/skeleton/base.rb +164 -0
- data/lib/rapid/skeleton/helpers/directory.rb +53 -0
- data/lib/rapid/skeleton/helpers/gem.rb +133 -0
- data/lib/rapid/skeleton/helpers/migration.rb +46 -0
- data/lib/rapid/skeleton/helpers/route.rb +115 -0
- data/lib/rapid/skeleton/helpers/script.rb +33 -0
- data/lib/rapid/skeleton/helpers/template.rb +73 -0
- data/lib/rapid/skeleton/helpers/view.rb +35 -0
- data/lib/rapid/spec/template.rb +104 -0
- data/lib/rapid/spec.rb +1 -0
- data/lib/rapid/tasks.rb +29 -0
- data/lib/rapid/template/base.rb +49 -0
- data/lib/rapid/template/node/base.rb +43 -0
- data/lib/rapid/template/node/comment_node.rb +42 -0
- data/lib/rapid/template/node/if_node.rb +109 -0
- data/lib/rapid/template/node/root.rb +51 -0
- data/lib/rapid/template/node/static.rb +29 -0
- data/lib/rapid/template/node/variable.rb +86 -0
- data/lib/rapid/template/parser.rb +167 -0
- data/lib/rapid/template/pulling/base.rb +91 -0
- data/lib/rapid/template/pulling/explicit.rb +92 -0
- data/lib/rapid/template/pulling/forgiving.rb +58 -0
- data/lib/rapid/version.rb +3 -0
- data/lib/rapid.rb +37 -0
- data/rapid-core.gemspec +26 -0
- data/spec/rapid/check_spec.rb +119 -0
- data/spec/rapid/error_spec.rb +14 -0
- data/spec/rapid/module_spec.rb +28 -0
- data/spec/rapid/setting/base_spec.rb +17 -0
- data/spec/rapid/setting/definer_spec.rb +318 -0
- data/spec/rapid/setting/instance_root_spec.rb +161 -0
- data/spec/rapid/setting/namespace/base_spec.rb +93 -0
- data/spec/rapid/setting/namespace/instance_spec.rb +12 -0
- data/spec/rapid/setting/nested_validations_spec.rb +72 -0
- data/spec/rapid/settings_spec.rb +51 -0
- data/spec/rapid/skeleton/base_spec.rb +224 -0
- data/spec/rapid/skeleton/helpers/directory_spec.rb +104 -0
- data/spec/rapid/skeleton/helpers/gem_spec.rb +180 -0
- data/spec/rapid/skeleton/helpers/migration_spec.rb +23 -0
- data/spec/rapid/skeleton/helpers/route_spec.rb +120 -0
- data/spec/rapid/skeleton/helpers/script_spec.rb +57 -0
- data/spec/rapid/skeleton/helpers/template_spec.rb +142 -0
- data/spec/rapid/skeleton/helpers/view_spec.rb +54 -0
- data/spec/rapid/spec/template_spec.rb +168 -0
- data/spec/rapid/template/base_spec.rb +290 -0
- data/spec/rapid/template/node/base_spec.rb +9 -0
- data/spec/rapid/template/node/comment_node_spec.rb +46 -0
- data/spec/rapid/template/node/if_node_spec.rb +28 -0
- data/spec/rapid/template/node/root_spec.rb +9 -0
- data/spec/rapid/template/node/static_spec.rb +17 -0
- data/spec/rapid/template/node/variable_spec.rb +87 -0
- data/spec/rapid/template/parser_spec.rb +187 -0
- data/spec/rapid/template/pulling/base_spec.rb +81 -0
- data/spec/rapid/template/pulling/explicit_spec.rb +33 -0
- data/spec/rapid/template/pulling/forgiving_spec.rb +132 -0
- data/spec/spec_helper.rb +10 -0
- metadata +325 -0
@@ -0,0 +1,104 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Spec
|
3
|
+
|
4
|
+
module Template
|
5
|
+
|
6
|
+
def self.included base
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
def templates_path
|
11
|
+
@templates_path
|
12
|
+
end
|
13
|
+
|
14
|
+
def template_path
|
15
|
+
@template_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def template_name
|
19
|
+
@template_name
|
20
|
+
end
|
21
|
+
|
22
|
+
def template_content
|
23
|
+
File.open(template_path) {|f| f.read } if template_path
|
24
|
+
end
|
25
|
+
|
26
|
+
def push settings_hash = nil
|
27
|
+
if respond_to? :build_skeleton
|
28
|
+
@skeleton = build_skeleton
|
29
|
+
|
30
|
+
elsif Rapid::Spec::Template.skeleton_class
|
31
|
+
skeleton_class = Rapid::Spec::Template.skeleton_class
|
32
|
+
@skeleton = skeleton_class.new
|
33
|
+
|
34
|
+
else
|
35
|
+
raise "please set define build_skeleton or set Rapid::Spec::Template.skeleton_class before running specs"
|
36
|
+
end
|
37
|
+
|
38
|
+
@skeleton.load_hash settings_hash if settings_hash
|
39
|
+
@template = Rapid::Template::Base.new template_content
|
40
|
+
@result = @template.push @skeleton
|
41
|
+
end
|
42
|
+
|
43
|
+
def pull content = {}
|
44
|
+
# render with the settings
|
45
|
+
if content.is_a? Hash
|
46
|
+
content = push content
|
47
|
+
end
|
48
|
+
|
49
|
+
@content = content
|
50
|
+
@template = Rapid::Template::Base.new template_content
|
51
|
+
@result = @template.pull @content
|
52
|
+
end
|
53
|
+
|
54
|
+
module ClassMethods
|
55
|
+
|
56
|
+
def template_spec filename
|
57
|
+
templates_path, template_path, template_name = Rapid::Spec::Template.find filename
|
58
|
+
|
59
|
+
before do
|
60
|
+
@templates_path = templates_path
|
61
|
+
@template_path = template_path
|
62
|
+
@template_name = template_name
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
class << self
|
70
|
+
attr_accessor :skeleton_class
|
71
|
+
|
72
|
+
def find filename
|
73
|
+
if filename =~ /\/spec\//
|
74
|
+
templates_path = File.join $`, 'templates'
|
75
|
+
end
|
76
|
+
|
77
|
+
raise "Templates path could not found be: #{filename.inspect}" unless templates_path
|
78
|
+
|
79
|
+
if filename =~ /\/templates\/(.+)_spec.rb$/
|
80
|
+
template_name = $1
|
81
|
+
template_path = File.join templates_path, template_name
|
82
|
+
|
83
|
+
unless File.exists?(template_path) && !File.directory?(template_path)
|
84
|
+
template_name += ".rb"
|
85
|
+
template_path = File.join templates_path, template_name
|
86
|
+
|
87
|
+
unless File.exists?(template_path)
|
88
|
+
raise "Couldn't figure out the template file location for: #{filename.inspect}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
else
|
93
|
+
raise "Not sure where the template file is for #{filename.inspect}"
|
94
|
+
end
|
95
|
+
|
96
|
+
return templates_path, template_path, template_name
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
data/lib/rapid/spec.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rapid/spec/template'
|
data/lib/rapid/tasks.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
namespace :rapid do
|
2
|
+
|
3
|
+
desc "Checks that none of your rapid skeletons are violated"
|
4
|
+
task :check => :environment do
|
5
|
+
start_time = Time.now
|
6
|
+
@check = Rapid::Check.new_with_detection :console => true
|
7
|
+
|
8
|
+
is_valid = @check.valid?
|
9
|
+
|
10
|
+
end_time = Time.now
|
11
|
+
|
12
|
+
puts "\nFinished in #{end_time - start_time} seconds"
|
13
|
+
|
14
|
+
results = []
|
15
|
+
results << "#{@check.check_count} checks"
|
16
|
+
results << "#{@check.warning_count} warnings" if @check.warning_count > 0
|
17
|
+
results << "#{@check.error_count} errors"
|
18
|
+
|
19
|
+
output = results.join(', ') << "\n"
|
20
|
+
|
21
|
+
if is_valid
|
22
|
+
Rapid.color_puts :ok, output
|
23
|
+
else
|
24
|
+
Rapid.color_puts :error, output
|
25
|
+
fail "Rapid check found some errors"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Template
|
3
|
+
|
4
|
+
class Base
|
5
|
+
|
6
|
+
attr_reader :content, :filename
|
7
|
+
|
8
|
+
def initialize content, options = {}
|
9
|
+
@content = polish_content content
|
10
|
+
@filename = options[:filename]
|
11
|
+
|
12
|
+
@erb = Erubis::Eruby.new @content
|
13
|
+
end
|
14
|
+
|
15
|
+
def push skeleton
|
16
|
+
@erb.result skeleton.get_binding
|
17
|
+
rescue Exception, SyntaxError, NameError => e
|
18
|
+
raise TemplateRenderError.new(@filename, e)
|
19
|
+
end
|
20
|
+
|
21
|
+
def pull content
|
22
|
+
content = polish_content content
|
23
|
+
|
24
|
+
nodes = Parser.new(@content).parse
|
25
|
+
|
26
|
+
result = Pulling::Forgiving.new(content)
|
27
|
+
nodes.pull result
|
28
|
+
|
29
|
+
result.empty!
|
30
|
+
result.to_hash
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def polish_content content
|
36
|
+
content
|
37
|
+
# if content.ends_with? "\n\n"
|
38
|
+
# $`
|
39
|
+
# elsif content.ends_with? "\n"
|
40
|
+
# $`
|
41
|
+
# else
|
42
|
+
# content
|
43
|
+
# end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Template
|
3
|
+
module Node
|
4
|
+
|
5
|
+
class Base
|
6
|
+
|
7
|
+
attr_reader :parent
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def pull result
|
14
|
+
raise NotImplementedError.new("pull not implemented for #{self.class}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def next_to child
|
18
|
+
# subclasses fill this in
|
19
|
+
end
|
20
|
+
|
21
|
+
def next_node
|
22
|
+
parent.next_to self if parent
|
23
|
+
end
|
24
|
+
|
25
|
+
def static?
|
26
|
+
is_a? Static
|
27
|
+
end
|
28
|
+
|
29
|
+
def content
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def parent= parent
|
36
|
+
@parent = parent
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Template
|
3
|
+
module Node
|
4
|
+
|
5
|
+
class CommentNode < Base
|
6
|
+
|
7
|
+
attr_reader :value, :variable
|
8
|
+
|
9
|
+
def initialize value, variable
|
10
|
+
@value = value
|
11
|
+
@variable = variable
|
12
|
+
|
13
|
+
if @variable.ends_with? "?"
|
14
|
+
@variable = @variable[0..-2]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def pull result
|
19
|
+
len = result.starts_with "# "
|
20
|
+
if len
|
21
|
+
result.move! len
|
22
|
+
result[variable] = value
|
23
|
+
else
|
24
|
+
result[variable] = !value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def == obj
|
29
|
+
obj.is_a?(self.class) &&
|
30
|
+
obj.variable == variable &&
|
31
|
+
obj.value == value
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
%(#<comment @value=#{@value.inspect} @variable=#{@variable.inspect}>)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Template
|
3
|
+
module Node
|
4
|
+
|
5
|
+
class IfNode < Base
|
6
|
+
|
7
|
+
attr_reader :statement, :then_node, :else_node
|
8
|
+
|
9
|
+
def initialize statement, then_nodes, else_nodes = nil
|
10
|
+
@statement = statement
|
11
|
+
|
12
|
+
@then_node = polish_nodes then_nodes
|
13
|
+
@else_node = polish_nodes else_nodes
|
14
|
+
|
15
|
+
@then_node.send :parent=, self if @then_node
|
16
|
+
@else_node.send :parent=, self if @else_node
|
17
|
+
end
|
18
|
+
|
19
|
+
def pull result
|
20
|
+
then_content = then_node.content if then_node
|
21
|
+
if then_content.nil?
|
22
|
+
raise Rapid::InvalidTemplateError.new("if statement must have content within it")
|
23
|
+
end
|
24
|
+
|
25
|
+
if result.starts_with? then_content
|
26
|
+
then_node.pull result
|
27
|
+
pull_variable result, statement, true
|
28
|
+
else
|
29
|
+
pull_variable result, statement, false
|
30
|
+
else_node.pull result if else_node
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def next_to node
|
35
|
+
parent.next_to self if parent
|
36
|
+
end
|
37
|
+
|
38
|
+
def == obj
|
39
|
+
obj.is_a?(self.class) &&
|
40
|
+
obj.statement == statement &&
|
41
|
+
obj.then_node == then_node &&
|
42
|
+
obj.else_node == @else_node
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect
|
46
|
+
%(#<if @statement=#{@statement.inspect} @then=#{@then_node.inspect} @else=#{@else_node.inspect}>)
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def pull_variable result, statement, is_success
|
52
|
+
if statement =~ /^[a-z][A-Za-z0-9\_\.]*$/
|
53
|
+
result[statement] = is_success unless result.key? statement
|
54
|
+
|
55
|
+
elsif statement =~ /^[a-z][A-Za-z0-9\_\.]*\?$/
|
56
|
+
name = statement[0..-2]
|
57
|
+
result[name] = is_success unless result.key? name
|
58
|
+
|
59
|
+
elsif statement =~ /^([a-z][A-Za-z0-9\_\.]*) == true$/
|
60
|
+
result[$1] = is_success
|
61
|
+
|
62
|
+
elsif statement =~ /^([a-z][A-Za-z0-9\_\.]*) == false$/
|
63
|
+
result[$1] = !is_success
|
64
|
+
|
65
|
+
elsif is_success
|
66
|
+
|
67
|
+
if statement =~ /^([a-z][A-Za-z0-9\_\.]*) == \"([^\"]*)\"$/
|
68
|
+
result[$1] = $2
|
69
|
+
|
70
|
+
elsif statement =~ /^([a-z][A-Za-z0-9\_\.]*) == \'([^\"]*)\'$/
|
71
|
+
result[$1] = $2
|
72
|
+
|
73
|
+
elsif statement =~ /^([a-z][A-Za-z0-9\_\.]*) == ([0-9]+)$/
|
74
|
+
result[$1] = $2.to_i
|
75
|
+
|
76
|
+
elsif statement =~ /^([a-z][A-Za-z0-9\_\.]*) == ([0-9]+\.[0-9]+)$/
|
77
|
+
result[$1] = $2.to_f
|
78
|
+
|
79
|
+
else
|
80
|
+
raise Rapid::InvalidTemplateError.new("unknown if statement #{statement.inspect}")
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def polish_nodes nodes
|
87
|
+
if nodes.is_a?(Array)
|
88
|
+
if nodes.length == 1
|
89
|
+
nodes.first
|
90
|
+
else
|
91
|
+
Root.new nodes
|
92
|
+
end
|
93
|
+
|
94
|
+
elsif nodes.is_a? Base
|
95
|
+
nodes
|
96
|
+
|
97
|
+
elsif nodes.nil?
|
98
|
+
nil
|
99
|
+
|
100
|
+
else
|
101
|
+
raise ArgumentError.new("unknown type: #{nodes.class}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Template
|
3
|
+
module Node
|
4
|
+
|
5
|
+
class Root < Base
|
6
|
+
|
7
|
+
attr_reader :nodes
|
8
|
+
|
9
|
+
def initialize nodes
|
10
|
+
@nodes = nodes
|
11
|
+
|
12
|
+
nodes.each do |n|
|
13
|
+
n.send :parent=, self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def next_to node
|
18
|
+
# OPTIMIZE need object level eql? this the best way?
|
19
|
+
index = nil
|
20
|
+
nodes.each_with_index {|n, i| index = i if node.eql? n }
|
21
|
+
return unless index
|
22
|
+
|
23
|
+
node = nodes[index+1]
|
24
|
+
return node if node
|
25
|
+
|
26
|
+
parent.next_node if parent
|
27
|
+
end
|
28
|
+
|
29
|
+
def pull result
|
30
|
+
@nodes.each do |node|
|
31
|
+
node.pull result
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def content
|
36
|
+
nodes.first.content if nodes.first
|
37
|
+
end
|
38
|
+
|
39
|
+
def == obj
|
40
|
+
obj.is_a?(self.class) && obj.nodes == @nodes
|
41
|
+
end
|
42
|
+
|
43
|
+
def inspect
|
44
|
+
%(#<root nodes=#{@nodes.inspect}>)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Template
|
3
|
+
module Node
|
4
|
+
|
5
|
+
class Static < Base
|
6
|
+
|
7
|
+
attr_accessor :content
|
8
|
+
|
9
|
+
def initialize content
|
10
|
+
@content = content
|
11
|
+
end
|
12
|
+
|
13
|
+
def pull result
|
14
|
+
result.match! @content
|
15
|
+
end
|
16
|
+
|
17
|
+
def == obj
|
18
|
+
obj.is_a?(self.class) && obj.content == @content
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
%(#<static #{@content.inspect}>)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Template
|
3
|
+
module Node
|
4
|
+
|
5
|
+
class Variable < Base
|
6
|
+
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def initialize name
|
10
|
+
if name.blank?
|
11
|
+
raise Rapid::InvalidTemplateError.new("Empty ERB statements aren't allowed")
|
12
|
+
end
|
13
|
+
|
14
|
+
@name = name
|
15
|
+
end
|
16
|
+
|
17
|
+
def pull result
|
18
|
+
next_piece = next_node
|
19
|
+
if next_piece.nil?
|
20
|
+
result[name] = result.content.clone
|
21
|
+
result.move! result.content.length
|
22
|
+
return
|
23
|
+
end
|
24
|
+
|
25
|
+
unless next_piece.static?
|
26
|
+
raise Rapid::InvalidTemplateError.new("Two ERB variables can't be touching #{result.content[0..20].inspect}")
|
27
|
+
end
|
28
|
+
|
29
|
+
index = result.index next_piece.content
|
30
|
+
if index.nil?
|
31
|
+
next_piece_does_not_match result, next_piece.content
|
32
|
+
end
|
33
|
+
|
34
|
+
if index == 0
|
35
|
+
value = ""
|
36
|
+
else
|
37
|
+
value = result.content[0..index-1]
|
38
|
+
result.move! index
|
39
|
+
end
|
40
|
+
|
41
|
+
result[name] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def == obj
|
45
|
+
obj.is_a?(self.class) && obj.name == @name
|
46
|
+
end
|
47
|
+
|
48
|
+
def inspect
|
49
|
+
%(#<variable #{@name.inspect}>)
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def next_piece_does_not_match result, content
|
55
|
+
# try and match the variable before throwing the error because it's
|
56
|
+
# likely the error isn't on the variable, but the text following the variable
|
57
|
+
if content.length > 20
|
58
|
+
start = content[0..20]
|
59
|
+
index = result.index start
|
60
|
+
|
61
|
+
if index.nil?
|
62
|
+
# do nothing
|
63
|
+
|
64
|
+
elsif index == 0
|
65
|
+
value = ""
|
66
|
+
else
|
67
|
+
value = result.content[0..index-1]
|
68
|
+
result.move! index
|
69
|
+
end
|
70
|
+
|
71
|
+
result[name] = value if value
|
72
|
+
|
73
|
+
success, result_match, content_match = result.match content
|
74
|
+
result.move! result_match if result_match > 0
|
75
|
+
|
76
|
+
content = content[content_match..-1] if content_match > 0
|
77
|
+
end
|
78
|
+
|
79
|
+
result.raise_not_matching content
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|