rapid-core 0.1 → 0.2.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 (89) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile.lock +35 -2
  3. data/Rakefile +77 -48
  4. data/doc/server.txt +15 -0
  5. data/features/settings/double-nested/default.feature +2 -2
  6. data/features/settings/double-nested/validates/presence_of.feature +1 -1
  7. data/features/settings/nested/default.feature +1 -1
  8. data/features/settings/nested/validates/presence_of.feature +1 -1
  9. data/features/settings/not_found.feature +2 -2
  10. data/features/step_definitions/settings_steps.rb +7 -3
  11. data/features/step_definitions/template_steps.rb +3 -1
  12. data/lib/rapid/check.rb +30 -23
  13. data/lib/rapid/core.rb +12 -0
  14. data/lib/rapid/error.rb +1 -0
  15. data/lib/rapid/module.rb +10 -1
  16. data/lib/rapid/railtie.rb +6 -0
  17. data/lib/rapid/setting/base.rb +31 -8
  18. data/lib/rapid/setting/boolean_setting.rb +20 -1
  19. data/lib/rapid/setting/definer.rb +11 -47
  20. data/lib/rapid/setting/integer_setting.rb +7 -7
  21. data/lib/rapid/setting/module.rb +56 -0
  22. data/lib/rapid/setting/namespace/base.rb +35 -60
  23. data/lib/rapid/setting/namespace/instance.rb +195 -28
  24. data/lib/rapid/setting/string_setting.rb +7 -1
  25. data/lib/rapid/settings.rb +51 -65
  26. data/lib/rapid/skeleton/base.rb +39 -18
  27. data/lib/rapid/skeleton/helpers/directory.rb +5 -6
  28. data/lib/rapid/skeleton/helpers/files.rb +62 -0
  29. data/lib/rapid/skeleton/helpers/gem.rb +43 -32
  30. data/lib/rapid/skeleton/helpers/if_setting.rb +44 -0
  31. data/lib/rapid/skeleton/helpers/migration.rb +102 -32
  32. data/lib/rapid/skeleton/helpers/route.rb +8 -12
  33. data/lib/rapid/skeleton/helpers/script.rb +1 -2
  34. data/lib/rapid/skeleton/helpers/template.rb +23 -25
  35. data/lib/rapid/skeleton/helpers/view.rb +7 -7
  36. data/lib/rapid/spec/template.rb +1 -1
  37. data/lib/rapid/version.rb +1 -1
  38. data/lib/rapid/web/base.rb +35 -0
  39. data/lib/rapid/web/bootstrap.rb +98 -0
  40. data/lib/rapid/web/controller_helpers.rb +60 -0
  41. data/lib/rapid/web/navigator.rb +18 -0
  42. data/lib/rapid/web/select_helpers.rb +63 -0
  43. data/lib/rapid/web/settings_form_builder.rb +205 -0
  44. data/lib/rapid/web/static_helpers.rb +28 -0
  45. data/lib/rapid/web/tasks.rb +10 -0
  46. data/public/rapid/core/bootstrap-collapse.js +136 -0
  47. data/public/rapid/core/bootstrap-responsive.min.css +3 -0
  48. data/public/rapid/core/bootstrap.min.css +556 -0
  49. data/public/rapid/core/jquery-1.7.1.js +9253 -0
  50. data/public/rapid/core/prettify.css +30 -0
  51. data/public/rapid/core/prettify.js +28 -0
  52. data/rapid-core.gemspec +5 -0
  53. data/spec/rapid/check_spec.rb +11 -4
  54. data/spec/rapid/module_spec.rb +18 -0
  55. data/spec/rapid/setting/base_spec.rb +71 -0
  56. data/spec/rapid/setting/boolean_setting_spec.rb +95 -0
  57. data/spec/rapid/setting/definer_spec.rb +7 -13
  58. data/spec/rapid/setting/integer_setting_spec.rb +49 -0
  59. data/spec/rapid/setting/module_spec.rb +25 -0
  60. data/spec/rapid/setting/namespace/base_spec.rb +88 -54
  61. data/spec/rapid/setting/namespace/instance_spec.rb +308 -5
  62. data/spec/rapid/setting/string_setting_spec.rb +43 -0
  63. data/spec/rapid/settings_spec.rb +65 -17
  64. data/spec/rapid/skeleton/base_spec.rb +113 -7
  65. data/spec/rapid/skeleton/helpers/directory_spec.rb +8 -6
  66. data/spec/rapid/skeleton/helpers/files_spec.rb +93 -0
  67. data/spec/rapid/skeleton/helpers/gem_spec.rb +65 -36
  68. data/spec/rapid/skeleton/helpers/if_setting_spec.rb +110 -0
  69. data/spec/rapid/skeleton/helpers/migration_spec.rb +190 -1
  70. data/spec/rapid/skeleton/helpers/route_spec.rb +13 -12
  71. data/spec/rapid/skeleton/helpers/script_spec.rb +2 -1
  72. data/spec/rapid/skeleton/helpers/template_spec.rb +22 -35
  73. data/spec/rapid/spec/template_spec.rb +1 -1
  74. data/spec/rapid/web/base_spec.rb +33 -0
  75. data/spec/rapid/web/bootstrap_spec.rb +72 -0
  76. data/spec/rapid/web/controller_helpers_spec.rb +86 -0
  77. data/spec/rapid/web/navigator_spec.rb +17 -0
  78. data/spec/rapid/web/select_helpers_spec.rb +71 -0
  79. data/spec/rapid/web/settings_form_builder_spec.rb +255 -0
  80. data/spec/rapid/web/static_helpers_spec.rb +26 -0
  81. data/spec/spec_helper.rb +3 -0
  82. data/views/index.erb +11 -0
  83. data/views/layout.erb +9 -0
  84. metadata +107 -12
  85. data/lib/rapid.rb +0 -37
  86. data/lib/rapid/setting/class_hash.rb +0 -34
  87. data/lib/rapid/setting/instance_hash.rb +0 -132
  88. data/lib/rapid/setting/instance_root.rb +0 -107
  89. data/spec/rapid/setting/instance_root_spec.rb +0 -161
@@ -2,59 +2,225 @@ module Rapid
2
2
  module Setting
3
3
  module Namespace
4
4
 
5
- class Instance < Setting::InstanceHash
5
+ class Instance
6
6
 
7
7
  include ActiveModel::Validations
8
8
  validate :validate_nested_settings
9
9
  validate :validate_no_assignment_exceptions
10
10
 
11
- attr_reader :_root
11
+ def initialize namespace, parent, value = {}
12
+ @namespace = namespace
13
+ @parent = parent
14
+ @assignment_exceptions = {}
15
+ @delegate = HashWithIndifferentAccess.new
16
+
17
+ _load value
18
+ _load_scalar_defaults
19
+ end
20
+
21
+ def empty?
22
+ @is_empty
23
+ end
24
+
25
+ def on?
26
+ @is_on
27
+ end
28
+ alias :on :on?
29
+
30
+ def on= bool
31
+ _load bool
32
+ bool
33
+ end
34
+
35
+ def on!
36
+ @is_on = true
37
+ end
12
38
 
13
- def initialize root, klass, hash = {}
14
- @_root = root
39
+ def set? full_name
40
+ names = full_name.split('.')
41
+ name = names.pop
15
42
 
16
- if hash.key? :empty
17
- @default_empty = hash.delete :empty
18
- @hardcoded_empty = @default_empty
19
- elsif klass.default_empty != nil
20
- @default_empty = klass.default_empty
43
+ namespace = self
44
+ names.each do |n|
45
+ namespace = namespace[n] if namespace.is_a?(Namespace::Instance)
46
+ end
47
+
48
+ value = namespace[name] if namespace.is_a?(Namespace::Instance)
49
+
50
+ if value.is_a?(Namespace::Instance)
51
+ value.on?
21
52
  else
22
- @default_empty = true
53
+ value != nil && value != false
23
54
  end
55
+ end
56
+
57
+ def [] full_name
58
+ namespace_name, child_name = Rapid::Settings.extract_nested_namespace(full_name)
24
59
 
25
- super klass, hash
60
+ if namespace_name.nil?
61
+ setting = @namespace[full_name]
62
+ if setting
63
+ @delegate[full_name]
64
+ elsif respond_to?(full_name)
65
+ send full_name
66
+ end
67
+ else
68
+ setting = @namespace[namespace_name]
69
+ namespace = @delegate[namespace_name] if setting
70
+ namespace[child_name] if namespace
71
+ end
72
+ end
73
+
74
+ def []= key, value
75
+ namespace_name, child_name = Rapid::Settings.extract_nested_namespace(key)
76
+
77
+ if namespace_name.nil?
78
+ _set_base key, value
79
+ else
80
+ _set_child namespace_name, child_name, value
81
+ end
82
+
83
+ rescue UnknownSettingError => e
84
+ @assignment_exceptions[key] = e
85
+ nil
86
+ rescue InvalidSettingError => e
87
+ @assignment_exceptions[key] = e
88
+ nil
26
89
  end
27
90
 
28
- def root
29
- @_root
91
+ def namespaces
92
+ values = @delegate.values.delete_if {|v| not v.is_a? Namespace::Instance }
93
+ values
30
94
  end
31
95
 
32
- def empty?
33
- return @hardcoded_empty if defined? @hardcoded_empty
96
+ def scalars
97
+ values = @delegate.values.delete_if {|v| v.is_a? Namespace::Instance }
98
+ values
99
+ end
100
+
101
+ def to_hash
102
+ hash = {}
34
103
 
35
104
  @delegate.each do |key, value|
36
- if value.is_a? Instance
37
- return false if not value.empty?
105
+ if value.is_a? Namespace::Instance
106
+ child = value.to_hash
107
+ hash[key] = child unless child.empty?
38
108
  else
39
- return false if value != nil
109
+ hash[key] = value
40
110
  end
41
111
  end
42
112
 
43
- @default_empty
113
+ hash
44
114
  end
45
115
 
46
- def [] full_name
47
- namespace_name, child_name = Rapid::Settings.extract_nested_namespace(full_name)
116
+ def to_dot_hash
117
+ Rapid::Settings.to_dot_hash to_hash
118
+ end
119
+
120
+ protected
121
+
122
+ def _parent
123
+ @parent
124
+ end
125
+ alias :parent :_parent
126
+
127
+ def _root
128
+ if @parent.is_a? Namespace::Instance
129
+ @parent.send :_root
130
+ else
131
+ @parent
132
+ end
133
+ end
134
+ alias :root :_root
135
+
136
+ def _load value
137
+ if value == nil || value == false
138
+ @is_empty = true
139
+ @is_on = false
140
+ value = {}
141
+
142
+ elsif value == true || value.is_a?(Hash)
143
+ value = {} if value == true
144
+
145
+ @is_on = true
146
+ @is_empty = value.empty?
147
+
148
+ else
149
+ raise Rapid::InvalidSettingError.new(@namespace, value)
150
+ end
48
151
 
49
- if namespace_name.nil?
50
- super
152
+ _load_namespaces value
153
+ end
154
+
155
+ def _load_namespaces values
156
+ @namespace.namespaces.each do |namespace|
157
+ value = values[namespace.name]
158
+ instance = @delegate[namespace.name]
159
+
160
+ if instance.nil?
161
+ klass = namespace.instance_class || Namespace::Instance
162
+ instance = klass.new namespace, self, value
163
+ @delegate[namespace.name] = instance
164
+ else
165
+ instance.send :_load, value
166
+ end
167
+
168
+ instance.on = namespace.default_value if value.nil?
169
+
170
+ @delegate[namespace.name] = instance
171
+ end
172
+
173
+ values.each do |key, value|
174
+ self[key] = value unless value.is_a?(Namespace::Instance)
175
+ end
176
+ end
177
+
178
+ def _load_scalar_defaults
179
+ @namespace.scalars.each do |scalar|
180
+ value = @delegate[scalar.name]
181
+ if value.nil? && scalar.default_value != nil
182
+ @delegate[scalar.name] = scalar.default_value
183
+ end
184
+ end
185
+ end
186
+
187
+ def _set_base key, value
188
+ setting = @namespace[key]
189
+
190
+ if setting.is_a? Namespace::Base
191
+ namespace = @delegate[key]
192
+ namespace.send :_load, value
193
+
194
+ elsif setting != nil
195
+ value = setting.load value
196
+ on! if value != nil && value != false
197
+ @delegate[key] = value
198
+
51
199
  else
52
- namespace = @delegate[namespace_name]
53
- namespace[child_name] if namespace
200
+ writer = "#{key}="
201
+ if respond_to?(writer)
202
+ send writer, value
203
+ else
204
+ raise Rapid::UnknownSettingError.new("#{@namespace.full_name}.#{key}")
205
+ end
54
206
  end
55
207
  end
56
208
 
57
- protected
209
+ def _set_child namespace_name, rest_name, value
210
+ setting = @namespace[namespace_name]
211
+
212
+ if setting.is_a? Namespace::Base
213
+ namespace = @delegate[namespace_name]
214
+ namespace[rest_name] = value
215
+
216
+ elsif setting.is_a? Setting::Base
217
+ raise Rapid::InvalidSettingError.new(setting, value)
218
+
219
+ else
220
+ raise Rapid::UnknownSettingError.new("#{@namespace.full_name}.#{namespace_name}")
221
+ end
222
+
223
+ end
58
224
 
59
225
  def validate_nested_settings
60
226
  namespaces.each do |namespace|
@@ -62,7 +228,8 @@ module Rapid
62
228
 
63
229
  namespace.errors.each do |attribute, errors|
64
230
  errors.each do |error|
65
- self.errors.add "#{namespace.klass.name}.#{attribute}", error
231
+ name = "#{namespace.class.setting_name}.#{attribute}"
232
+ self.errors.add name, error
66
233
  end
67
234
  end
68
235
  end
@@ -71,7 +238,7 @@ module Rapid
71
238
  end
72
239
 
73
240
  def validate_no_assignment_exceptions
74
- assignment_exceptions.each do |attribute, error|
241
+ @assignment_exceptions.each do |attribute, error|
75
242
  self.errors.add attribute, error.validation_message
76
243
  end
77
244
 
@@ -4,7 +4,13 @@ module Rapid
4
4
  class StringSetting < Base
5
5
 
6
6
  def load value
7
- value.nil? ? nil : value.to_s
7
+ if value == nil || value == false
8
+ nil
9
+ elsif value.is_a?(Array) || value.is_a?(Hash)
10
+ raise Rapid::InvalidSettingError.new(self, value)
11
+ else
12
+ value.to_s
13
+ end
8
14
  end
9
15
 
10
16
  end
@@ -1,8 +1,6 @@
1
+ require 'rapid/setting/module'
1
2
  require 'rapid/setting/nested_validations'
2
3
  require 'rapid/setting/definer'
3
- require 'rapid/setting/class_hash'
4
- require 'rapid/setting/instance_hash'
5
- require 'rapid/setting/instance_root'
6
4
 
7
5
  require 'rapid/setting/base'
8
6
  require 'rapid/setting/namespace/base'
@@ -16,61 +14,6 @@ require 'rapid/setting/comments'
16
14
  module Rapid
17
15
  module Settings
18
16
 
19
- class << self
20
-
21
- def reserved_names
22
- # ActiveModel::Validations
23
- @reserved_words ||= %w(_validate_callbacks _validators errors read_attribute_for_validation
24
- run_callbacks valid validates_acceptance_of validates_confirmation_of validates_exclusion_of
25
- validates_format_of validates_inclusion_of validates_length_of validates_numericality_of
26
- validates_presence_of validates_size_of validates_with validation_context) +
27
-
28
- # internal
29
- %w(_root empty namespaces scalars validate_nested_settings validate_no_assignment_exceptions
30
- load_yaml load_hash to_yaml to_dot_hash to_hash parse_yaml get_binding)
31
- end
32
-
33
- def reserved_name? name
34
- reserved_names.include? name.to_s
35
- end
36
-
37
- def extract_nested_namespace full_name
38
- return nil, nil if full_name.nil?
39
-
40
- full_name = full_name.to_s
41
- if full_name.to_s =~ /^([^\.]+)\.(.+)$/
42
- return $1, $2
43
- else
44
- return nil, full_name
45
- end
46
- end
47
-
48
- def clean_yaml yaml
49
- yaml.gsub! /^--- \n/, ""
50
- yaml.gsub! /\n$/, ""
51
- yaml
52
- end
53
-
54
- def to_dot_hash nested_hash
55
- dot_hash = {}
56
- flatten = proc { |key, value|
57
-
58
- if value.is_a?(Hash)
59
- value.each do |k2, v2|
60
- flatten[key + [k2], v2]
61
- end
62
- else
63
- namespace = key.join('.')
64
- dot_hash[namespace] = value
65
- end
66
- }
67
-
68
- flatten[[], nested_hash]
69
- dot_hash
70
- end
71
-
72
- end
73
-
74
17
  def self.included base
75
18
  base.send :include, ActiveModel::Validations
76
19
  base.send :include, Rapid::Setting::NestedValidations
@@ -80,24 +23,67 @@ module Rapid
80
23
 
81
24
  base.validate :validate_settings
82
25
 
83
- base.delegate :load_yaml, :to => :settings
84
- base.delegate :load_hash, :to => :settings
85
- base.delegate :to_yaml, :to => :settings
86
26
  base.delegate :to_hash, :to => :settings
87
27
  base.delegate :to_dot_hash, :to => :settings
88
- base.delegate :[], :to => :settings
89
- base.delegate :[]=, :to => :settings
90
28
  base.delegate :set?, :to => :settings
91
29
  end
92
30
 
93
31
  def settings
94
- @settings ||= Setting::InstanceRoot.new(self.class.settings, self)
32
+ @settings ||= Setting::Namespace::Instance.new(self.class.settings, self)
33
+ end
34
+
35
+ def settings= settings
36
+ self.settings.send :_load, settings
95
37
  end
96
38
 
97
39
  def get_binding
98
40
  binding
99
41
  end
100
42
 
43
+ def [] full_name
44
+ namespace_name, child_name = Rapid::Settings.extract_nested_namespace(full_name)
45
+
46
+ if namespace_name.nil?
47
+ setting = self.class.settings[full_name]
48
+ if setting
49
+ settings[full_name]
50
+ elsif respond_to?(full_name)
51
+ send full_name
52
+ else
53
+ nil
54
+ end
55
+ else
56
+ settings[full_name]
57
+ end
58
+ end
59
+
60
+ def []= full_name, value
61
+ namespace_name, child_name = Rapid::Settings.extract_nested_namespace(full_name)
62
+
63
+ if namespace_name
64
+ settings[full_name] = value
65
+
66
+ elsif namespace_name.nil?
67
+ setting = self.class.settings[full_name]
68
+ if setting
69
+ settings[full_name] = value
70
+ else
71
+ writer = "#{full_name}="
72
+ if respond_to?(writer)
73
+ send writer, value
74
+ else
75
+ settings[full_name] = value
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def load hash
82
+ hash.each do |key, value|
83
+ self[key] = value
84
+ end
85
+ end
86
+
101
87
  protected
102
88
 
103
89
  def validate_settings
@@ -113,7 +99,7 @@ module Rapid
113
99
  module ClassMethods
114
100
 
115
101
  def settings
116
- @settings ||= Setting::ClassHash.new
102
+ @settings ||= Setting::Namespace::Base.new(nil)
117
103
  end
118
104
 
119
105
  protected
@@ -5,6 +5,8 @@ module Rapid
5
5
 
6
6
  include ActiveModel::Validations
7
7
 
8
+ include Skeleton::Helpers::IfSetting
9
+ include Skeleton::Helpers::Files
8
10
  include Skeleton::Helpers::Directory
9
11
  include Skeleton::Helpers::Gem
10
12
  include Skeleton::Helpers::Migration
@@ -13,7 +15,7 @@ module Rapid
13
15
  include Skeleton::Helpers::Template
14
16
  include Skeleton::Helpers::View
15
17
 
16
- attr_reader :name, :settings, :project_path, :templates_path
18
+ attr_reader :name, :check, :settings, :project_path, :templates_path
17
19
 
18
20
  delegate :get_binding, :to => :settings
19
21
  delegate :load_yaml, :to => :settings
@@ -22,7 +24,6 @@ module Rapid
22
24
  delegate :to_hash, :to => :settings
23
25
  delegate :to_dot_hash, :to => :settings
24
26
  delegate :[], :to => :settings
25
- delegate :[]=, :to => :settings
26
27
  delegate :set?, :to => :settings
27
28
 
28
29
  validate :validate_settings
@@ -32,14 +33,16 @@ module Rapid
32
33
  @project_path = options[:project_path] || File.expand_path('.')
33
34
  @templates_path = options[:templates_path] || discover_templates_path(options[:file])
34
35
  @name = options[:name] || implied_name
36
+
37
+ @check = options[:check] || Rapid::Check.current || Rapid::Check.new("", options)
35
38
  end
36
39
 
37
40
  def settings= hash
38
- settings.load_hash hash
41
+ settings.load hash
39
42
  end
40
43
 
41
- def push!
42
- if push
44
+ def push! settings = nil
45
+ if push(settings)
43
46
  true
44
47
  else
45
48
  raise Rapid::InvalidSkeletonError.new(errors.full_messages.join(', '))
@@ -48,7 +51,9 @@ module Rapid
48
51
  true
49
52
  end
50
53
 
51
- def push
54
+ def push settings = nil
55
+ self.settings = settings if settings
56
+
52
57
  @pushing = true
53
58
  is_valid = valid?
54
59
  section(name) { bones } if is_valid
@@ -67,9 +72,34 @@ module Rapid
67
72
 
68
73
  def pull
69
74
  @pulling = true
70
- !Rapid::Check.encounters_error? { section(name) { bones } }
75
+ @pulled_settings = []
76
+ !@check.encounters_error? { section(name) { bones } }
71
77
  ensure
72
78
  @pulling = false
79
+ @pulled_settings = nil
80
+ end
81
+
82
+ def []= key, value
83
+ # if this is the first time this setting has been set
84
+ if @pulled_settings.nil? || !@pulled_settings.include?(key)
85
+ @pulled_settings.push key if @pulled_settings
86
+
87
+ @check.log_value :info, key, value
88
+ @settings[key] = value
89
+
90
+ else
91
+ old_value = @settings[key]
92
+ old_value = old_value.on? if old_value.is_a?(Setting::Namespace::Instance)
93
+ @settings[key] = value
94
+ new_value = @settings[key]
95
+ new_value = new_value.on? if new_value.is_a?(Setting::Namespace::Instance)
96
+
97
+ if old_value == new_value
98
+ @check.log_value :info, key, value
99
+ else
100
+ @check.log_value :warning, key, value
101
+ end
102
+ end
73
103
  end
74
104
 
75
105
  protected
@@ -79,11 +109,7 @@ module Rapid
79
109
  end
80
110
 
81
111
  def section name, options = {}, &block
82
- if Rapid::Check.current
83
- Rapid::Check.current.with_section name do
84
- run_section name, options, &block
85
- end
86
- else
112
+ @check.with_section name do
87
113
  run_section name, options, &block
88
114
  end
89
115
  end
@@ -124,12 +150,7 @@ module Rapid
124
150
  end
125
151
 
126
152
  def log type, file, message_or_exception
127
- if Rapid::Check.current
128
- Rapid::Check.current.send type, file, message_or_exception
129
- else
130
- raise "Rapid::Check.current is not set"
131
- end
132
-
153
+ @check.send type, file, message_or_exception
133
154
  end
134
155
 
135
156
  def validate_settings