rapid-core 0.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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