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,37 @@
|
|
1
|
+
Feature: push and pull a static template
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a skeleton with settings "my_settings.rb":
|
5
|
+
"""
|
6
|
+
class MySettings
|
7
|
+
include Rapid::Settings
|
8
|
+
|
9
|
+
end
|
10
|
+
"""
|
11
|
+
And a template "static.erb":
|
12
|
+
"""
|
13
|
+
class Foo < ActiveRecord::Base
|
14
|
+
|
15
|
+
def inspect
|
16
|
+
"foo"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
"""
|
21
|
+
|
22
|
+
Scenario: Push and Pull Template
|
23
|
+
When I push the skeleton through "static.erb" with:
|
24
|
+
"""
|
25
|
+
"""
|
26
|
+
Then I should get:
|
27
|
+
"""
|
28
|
+
class Foo < ActiveRecord::Base
|
29
|
+
|
30
|
+
def inspect
|
31
|
+
"foo"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
"""
|
36
|
+
And vice versa
|
37
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
Feature: template with a variable
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a skeleton with settings "my_settings.rb":
|
5
|
+
"""
|
6
|
+
class MySettings
|
7
|
+
include Rapid::Settings
|
8
|
+
|
9
|
+
setting.string :name, :default => "Dan"
|
10
|
+
setting.integer :id, :default => 5
|
11
|
+
setting.string 'foo.bar', :default => 'hey'
|
12
|
+
setting.integer 'foo.baz', :default => 20
|
13
|
+
|
14
|
+
end
|
15
|
+
"""
|
16
|
+
And a template "variables.erb":
|
17
|
+
"""
|
18
|
+
class <%= name %> < ActiveRecord::Base
|
19
|
+
|
20
|
+
def inspect
|
21
|
+
"<%= id %> <%= foo.bar %> <%= foo.baz %>"
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
"""
|
26
|
+
|
27
|
+
@wip
|
28
|
+
Scenario: Push/Pull Template
|
29
|
+
When I push the skeleton through "variables.erb" with:
|
30
|
+
"""
|
31
|
+
name: Foo
|
32
|
+
foo.baz: 10
|
33
|
+
foo.bar: hi
|
34
|
+
id: 5
|
35
|
+
"""
|
36
|
+
Then I should get:
|
37
|
+
"""
|
38
|
+
class Foo < ActiveRecord::Base
|
39
|
+
|
40
|
+
def inspect
|
41
|
+
"5 hi 10"
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
"""
|
46
|
+
And vice versa
|
47
|
+
|
48
|
+
Scenario: obey defaults
|
49
|
+
When I push the skeleton through "variables.erb" with:
|
50
|
+
"""
|
51
|
+
"""
|
52
|
+
Then I should get:
|
53
|
+
"""
|
54
|
+
class Dan < ActiveRecord::Base
|
55
|
+
|
56
|
+
def inspect
|
57
|
+
"5 hey 20"
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
"""
|
data/lib/rapid/check.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
module Rapid
|
2
|
+
|
3
|
+
class Check
|
4
|
+
|
5
|
+
attr_reader :code, :ok_count, :warning_count, :error_count
|
6
|
+
|
7
|
+
def initialize code, options = {}
|
8
|
+
@code = code
|
9
|
+
@console_output = options[:console]
|
10
|
+
@ok_count = 0
|
11
|
+
@warning_count = 0
|
12
|
+
@error_count = 0
|
13
|
+
@sections = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_count
|
17
|
+
ok_count + warning_count + error_count
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
@valid = true
|
22
|
+
@ok_count = 0
|
23
|
+
@warning_count = 0
|
24
|
+
@error_count = 0
|
25
|
+
|
26
|
+
as_current { eval code }
|
27
|
+
@valid
|
28
|
+
end
|
29
|
+
|
30
|
+
def ok filename, message
|
31
|
+
@ok_count += 1
|
32
|
+
log :ok, filename, message
|
33
|
+
end
|
34
|
+
|
35
|
+
def warning filename, message
|
36
|
+
@warning_count += 1
|
37
|
+
log :warning, filename, message
|
38
|
+
end
|
39
|
+
|
40
|
+
def error filename, message
|
41
|
+
@error_count += 1
|
42
|
+
@valid = false
|
43
|
+
log :error, "", ""
|
44
|
+
log :error, filename, message
|
45
|
+
log :error, "", ""
|
46
|
+
end
|
47
|
+
|
48
|
+
def exception filename, e
|
49
|
+
@error_count += 1
|
50
|
+
@valid = false
|
51
|
+
|
52
|
+
log :error, "", ""
|
53
|
+
log :error, filename, ""
|
54
|
+
log :error, "", ""
|
55
|
+
log :error, " problem: ", "content doesn't match"
|
56
|
+
log :error, " after: ", pretty_code(e.previous_content, "START OF FILE")
|
57
|
+
log :error, " expected:", pretty_code(e.expected_content, "END OF FILE")
|
58
|
+
log :error, " received:", pretty_code(e.content, "END OF FILE")
|
59
|
+
log :error, " current: ", clean_hash(e.result)
|
60
|
+
log :error, "", ""
|
61
|
+
end
|
62
|
+
|
63
|
+
def with_section name
|
64
|
+
puts "" if @sections.empty?
|
65
|
+
|
66
|
+
indention = " " * @sections.length
|
67
|
+
puts "#{indention}#{name}"
|
68
|
+
|
69
|
+
@sections.push name
|
70
|
+
yield
|
71
|
+
ensure
|
72
|
+
@sections.pop
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def clean_hash hash
|
78
|
+
h = {}
|
79
|
+
|
80
|
+
hash.each do |key, value|
|
81
|
+
if String === value && value.length > 50
|
82
|
+
value = value[0..25] + "..." + value[-25..25]
|
83
|
+
end
|
84
|
+
|
85
|
+
h[key] = value
|
86
|
+
end
|
87
|
+
|
88
|
+
h.inspect
|
89
|
+
end
|
90
|
+
|
91
|
+
def pretty_code code, blank_replace
|
92
|
+
if code.blank?
|
93
|
+
blank_replace
|
94
|
+
else
|
95
|
+
code[0..100].inspect
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def log type, filename, message
|
100
|
+
return unless @console_output
|
101
|
+
|
102
|
+
indention = " " * @sections.length
|
103
|
+
|
104
|
+
output = "#{indention}#{filename} #{message}"
|
105
|
+
Rapid.color_puts type, output
|
106
|
+
end
|
107
|
+
|
108
|
+
def as_current
|
109
|
+
self.class.current = self
|
110
|
+
yield
|
111
|
+
|
112
|
+
ensure
|
113
|
+
self.class.current = nil
|
114
|
+
end
|
115
|
+
|
116
|
+
class << self
|
117
|
+
attr_accessor :current, :file
|
118
|
+
|
119
|
+
def possible_files
|
120
|
+
[
|
121
|
+
'.rapid',
|
122
|
+
'rapid.rb',
|
123
|
+
File.join('config', 'rapid.rb')
|
124
|
+
]
|
125
|
+
end
|
126
|
+
|
127
|
+
def new_with_detection *args
|
128
|
+
filename = file
|
129
|
+
|
130
|
+
if filename.nil?
|
131
|
+
possible_files.each do |name|
|
132
|
+
if File.exists?(name) && !File.directory?(name)
|
133
|
+
filename ||= name
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
unless filename
|
139
|
+
raise FileNotFoundCheckError.new("could not locate your rapid.rb check file [#{Rapid::Check.possible_files.join(', ')}]. " +
|
140
|
+
"Please create it or set the location using Rapid::Check.file = '/config/checks.rb'.")
|
141
|
+
end
|
142
|
+
|
143
|
+
code = File.open(filename) {|f| f.read }
|
144
|
+
new code, *args
|
145
|
+
end
|
146
|
+
|
147
|
+
def encounters_error?
|
148
|
+
if current.nil?
|
149
|
+
yield
|
150
|
+
false
|
151
|
+
else
|
152
|
+
old_count = current.error_count
|
153
|
+
yield
|
154
|
+
old_count != current.error_count
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
data/lib/rapid/core.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erubis'
|
3
|
+
require 'active_support/core_ext/string'
|
4
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
+
require 'active_model'
|
6
|
+
|
7
|
+
require "rapid/version"
|
8
|
+
require "rapid/error"
|
9
|
+
require "rapid/module"
|
10
|
+
|
11
|
+
require "rapid/settings"
|
12
|
+
require "rapid/check"
|
13
|
+
|
14
|
+
require "rapid/skeleton/helpers/directory"
|
15
|
+
require "rapid/skeleton/helpers/gem"
|
16
|
+
require "rapid/skeleton/helpers/migration"
|
17
|
+
require "rapid/skeleton/helpers/route"
|
18
|
+
require "rapid/skeleton/helpers/script"
|
19
|
+
require "rapid/skeleton/helpers/template"
|
20
|
+
require "rapid/skeleton/helpers/view"
|
21
|
+
require "rapid/skeleton/base"
|
22
|
+
|
23
|
+
require "rapid/template/base"
|
24
|
+
require "rapid/template/parser"
|
25
|
+
|
26
|
+
require "rapid/template/pulling/base"
|
27
|
+
require "rapid/template/pulling/explicit"
|
28
|
+
require "rapid/template/pulling/forgiving"
|
29
|
+
|
30
|
+
require "rapid/template/node/base"
|
31
|
+
require "rapid/template/node/root"
|
32
|
+
require "rapid/template/node/static"
|
33
|
+
require "rapid/template/node/variable"
|
34
|
+
require "rapid/template/node/if_node"
|
35
|
+
require "rapid/template/node/comment_node"
|
36
|
+
|
37
|
+
require 'rapid/railtie' if defined? Rails
|
data/lib/rapid/error.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
module Rapid
|
2
|
+
|
3
|
+
class Exception < ::Exception ; end
|
4
|
+
|
5
|
+
class SettingError < Exception ; end
|
6
|
+
class SettingLoadError < Exception ; end
|
7
|
+
class InvalidYamlError < SettingLoadError ; end
|
8
|
+
|
9
|
+
class UnknownSettingError < SettingLoadError
|
10
|
+
attr_reader :setting_name
|
11
|
+
|
12
|
+
def initialize full_setting_name
|
13
|
+
@setting_name = full_setting_name
|
14
|
+
super "Can't find #{full_setting_name.inspect} setting"
|
15
|
+
end
|
16
|
+
|
17
|
+
def validation_message
|
18
|
+
"can't be found"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class InvalidSettingError < SettingLoadError
|
24
|
+
attr_reader :setting, :value
|
25
|
+
|
26
|
+
def initialize setting, value
|
27
|
+
@setting = setting
|
28
|
+
@value = value
|
29
|
+
super "Can't assign #{value.inspect} to #{setting.full_name}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def validation_message
|
33
|
+
"doesn't allow values of that type"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class SkeletonError < Exception ; end
|
39
|
+
class InvalidSkeletonError < SkeletonError ; end
|
40
|
+
|
41
|
+
class TemplateError < Exception ; end
|
42
|
+
class InvalidTemplateError < TemplateError ; end
|
43
|
+
class NotMatchingTemplateError < TemplateError ; end
|
44
|
+
class TemplateNotFoundError < TemplateError ; end
|
45
|
+
class UnknownMethodTemplateError < TemplateError ; end
|
46
|
+
|
47
|
+
class NotMatchingTemplateError < TemplateError
|
48
|
+
|
49
|
+
attr_reader :result, :expected_content, :content, :previous_content
|
50
|
+
|
51
|
+
def initialize result, expected_content, content, options = {}
|
52
|
+
@result, @expected_content, @content = result, expected_content, content
|
53
|
+
@previous_content = options[:previous]
|
54
|
+
end
|
55
|
+
|
56
|
+
def message
|
57
|
+
messages = [
|
58
|
+
"after: #{previous_content.nil? ? "nil" : previous_content[0..100].inspect}",
|
59
|
+
"expected: #{expected_content[0..100].inspect}",
|
60
|
+
"received: #{content[0..100].inspect}",
|
61
|
+
"current: #{result.inspect}"
|
62
|
+
]
|
63
|
+
|
64
|
+
messages.join("\n")
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
class TemplateRenderError < TemplateError
|
70
|
+
|
71
|
+
attr_reader :template_path, :original_exception
|
72
|
+
|
73
|
+
def initialize template_path, e
|
74
|
+
super "Error rendering #{template_path}: #{e.message}"
|
75
|
+
@template_path = template_path
|
76
|
+
@original_exception = e
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
class CheckError < Exception ; end
|
82
|
+
class FileNotFoundCheckError < CheckError ; end
|
83
|
+
|
84
|
+
end
|
data/lib/rapid/module.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Rapid
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
attr_accessor :view_path
|
6
|
+
|
7
|
+
# from rspec
|
8
|
+
|
9
|
+
def colorize(text, color_code)
|
10
|
+
"#{color_code}#{text}\e[0m"
|
11
|
+
end
|
12
|
+
|
13
|
+
def red(text); colorize(text, "\e[31m"); end
|
14
|
+
def green(text); colorize(text, "\e[32m"); end
|
15
|
+
def yellow(text); colorize(text, "\e[33m"); end
|
16
|
+
|
17
|
+
def color_puts type, message
|
18
|
+
case type
|
19
|
+
when :ok
|
20
|
+
puts green(message)
|
21
|
+
|
22
|
+
when :warning
|
23
|
+
puts yellow(message)
|
24
|
+
|
25
|
+
when :error
|
26
|
+
puts red(message)
|
27
|
+
|
28
|
+
else
|
29
|
+
raise "Invalid type: #{type.inspect}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rapid
|
2
|
+
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
|
5
|
+
rake_tasks do
|
6
|
+
load "rapid/tasks.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
initializer "rapid.view_paths" do
|
10
|
+
Rapid.view_path ||= File.join 'lib', 'rapid', 'views'
|
11
|
+
|
12
|
+
ActionController::Base.append_view_path Rapid.view_path
|
13
|
+
ActionMailer::Base.append_view_path Rapid.view_path
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Setting
|
3
|
+
|
4
|
+
class Base
|
5
|
+
|
6
|
+
attr_reader :namespace, :full_name, :name, :default_value
|
7
|
+
|
8
|
+
def initialize name, options = {}
|
9
|
+
@name = name.to_sym
|
10
|
+
@namespace = options[:namespace]
|
11
|
+
@default_value = options[:default]
|
12
|
+
@full_name = @namespace ? "#{@namespace.full_name}.#{name}" : name.to_s
|
13
|
+
|
14
|
+
if Rapid::Settings.reserved_name? @name
|
15
|
+
raise ArgumentError.new("#{@name} is a reserved setting name")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def load value
|
20
|
+
raise "Subclass should override this method"
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_helper_name
|
24
|
+
name
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_helper_name
|
28
|
+
"#{name}="
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Setting
|
3
|
+
|
4
|
+
class ClassHash
|
5
|
+
|
6
|
+
attr_reader :delegate
|
7
|
+
|
8
|
+
delegate :[], :to => :delegate
|
9
|
+
delegate :[]=, :to => :delegate
|
10
|
+
delegate :empty?, :to => :delegate
|
11
|
+
delegate :each, :to => :delegate
|
12
|
+
delegate :keys, :to => :delegate
|
13
|
+
delegate :values, :to => :delegate
|
14
|
+
delegate :to_hash, :to => :delegate
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@delegate = HashWithIndifferentAccess.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def namespaces
|
21
|
+
values = self.values.delete_if {|v| not v.is_a? Namespace::Base }
|
22
|
+
values
|
23
|
+
end
|
24
|
+
|
25
|
+
def scalars
|
26
|
+
values = self.values.delete_if {|v| v.is_a? Namespace::Base }
|
27
|
+
values
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Setting
|
3
|
+
|
4
|
+
module Comments
|
5
|
+
|
6
|
+
def comment_unless boolean
|
7
|
+
if boolean
|
8
|
+
nil
|
9
|
+
else
|
10
|
+
"# "
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def comment_if boolean
|
15
|
+
if boolean
|
16
|
+
"# "
|
17
|
+
else
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
module Rapid
|
2
|
+
module Setting
|
3
|
+
|
4
|
+
class Definer
|
5
|
+
|
6
|
+
def initialize klass, options = {}
|
7
|
+
@klass = klass
|
8
|
+
@delimiter = '.'
|
9
|
+
end
|
10
|
+
|
11
|
+
def boolean full_name, options = {}
|
12
|
+
namespace, name = find_namespace_and_name full_name
|
13
|
+
setting = BooleanSetting.new name, options.merge(:namespace => namespace)
|
14
|
+
define_setting setting
|
15
|
+
end
|
16
|
+
|
17
|
+
def string full_name, options = {}
|
18
|
+
namespace, name = find_namespace_and_name full_name
|
19
|
+
setting = StringSetting.new name, options.merge(:namespace => namespace)
|
20
|
+
define_setting setting
|
21
|
+
end
|
22
|
+
|
23
|
+
def integer full_name, options = {}
|
24
|
+
namespace, name = find_namespace_and_name full_name
|
25
|
+
setting = IntegerSetting.new name, options.merge(:namespace => namespace)
|
26
|
+
define_setting setting
|
27
|
+
end
|
28
|
+
|
29
|
+
def namespace full_name, options = {}
|
30
|
+
namespace, name = find_namespace_and_name full_name
|
31
|
+
setting = Namespace::Base.new name, options.merge(:namespace => namespace, :class => @klass)
|
32
|
+
define_setting setting
|
33
|
+
end
|
34
|
+
|
35
|
+
def code full_name, options = {}
|
36
|
+
namespace, name = find_namespace_and_name full_name
|
37
|
+
setting = StringSetting.new name, options.merge(:namespace => namespace)
|
38
|
+
define_setting setting
|
39
|
+
end
|
40
|
+
|
41
|
+
def class_eval namespace_name, &block
|
42
|
+
names = namespace_name.to_s.split('.')
|
43
|
+
namespace = find_namespace *names
|
44
|
+
raise ArgumentError.new("namespace not found: #{namespace_name.inspect}") unless namespace
|
45
|
+
raise ArgumentError.new("namespace does not have a custom class") unless namespace.instance_class
|
46
|
+
namespace.instance_class.class_eval &block
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_namespace *names
|
50
|
+
namespace = nil
|
51
|
+
names.each_with_index do |name, index|
|
52
|
+
if index == 0
|
53
|
+
namespace = @klass.settings[name]
|
54
|
+
else
|
55
|
+
namespace = namespace[name]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
namespace
|
59
|
+
end
|
60
|
+
|
61
|
+
def inspect
|
62
|
+
%(#<Rapid::Setting::Definer>)
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def find_or_create_namespace *names
|
68
|
+
namespace = nil
|
69
|
+
|
70
|
+
names.each_with_index do |name, index|
|
71
|
+
if index == 0
|
72
|
+
new_namespace = @klass.settings[name]
|
73
|
+
else
|
74
|
+
new_namespace = namespace[name]
|
75
|
+
end
|
76
|
+
|
77
|
+
if new_namespace.nil?
|
78
|
+
new_namespace = Namespace::Base.new name, :namespace => namespace, :class => @klass
|
79
|
+
define_setting new_namespace
|
80
|
+
end
|
81
|
+
|
82
|
+
namespace = new_namespace
|
83
|
+
end
|
84
|
+
|
85
|
+
namespace
|
86
|
+
end
|
87
|
+
|
88
|
+
def find_namespace_and_name full_name
|
89
|
+
names = full_name.to_s.split(@delimiter)
|
90
|
+
setting_name = names.pop.to_sym
|
91
|
+
|
92
|
+
namespace = find_or_create_namespace *names
|
93
|
+
return namespace, setting_name
|
94
|
+
end
|
95
|
+
|
96
|
+
def define_setting setting
|
97
|
+
if setting.namespace.nil?
|
98
|
+
define_base_setting setting
|
99
|
+
else
|
100
|
+
setting.namespace.define_setting setting
|
101
|
+
end
|
102
|
+
|
103
|
+
setting
|
104
|
+
end
|
105
|
+
|
106
|
+
def define_base_setting setting
|
107
|
+
define_methods setting
|
108
|
+
push_setting setting
|
109
|
+
end
|
110
|
+
|
111
|
+
def define_methods setting
|
112
|
+
name = setting.name
|
113
|
+
getter = setting.get_helper_name
|
114
|
+
setter = setting.set_helper_name
|
115
|
+
|
116
|
+
@klass.class_eval do
|
117
|
+
define_method getter do
|
118
|
+
settings[name]
|
119
|
+
end
|
120
|
+
|
121
|
+
define_method setter do |value|
|
122
|
+
settings[name] = value
|
123
|
+
end
|
124
|
+
|
125
|
+
if setting.is_a? BooleanSetting
|
126
|
+
define_method "#{getter}?" do
|
127
|
+
settings[name] == true
|
128
|
+
end
|
129
|
+
elsif setting.is_a? Namespace::Base
|
130
|
+
define_method "#{getter}?" do
|
131
|
+
settings[name] != nil && !settings[name].empty?
|
132
|
+
end
|
133
|
+
else
|
134
|
+
define_method "#{getter}?" do
|
135
|
+
settings[name] != nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
true
|
141
|
+
end
|
142
|
+
|
143
|
+
def push_setting setting
|
144
|
+
@klass.settings[setting.name] = setting
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|