ruhoh 2.5 → 2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/Gemfile +1 -1
  2. data/bin/ruhoh +10 -3
  3. data/features/_root.feature +11 -0
  4. data/features/data.feature +78 -0
  5. data/features/javascripts.feature +36 -0
  6. data/features/permalinks.feature +23 -0
  7. data/features/plugins.feature +84 -0
  8. data/features/sort_order.feature +121 -0
  9. data/features/step_defs.rb +3 -3
  10. data/features/support/helpers.rb +3 -5
  11. data/history.json +21 -0
  12. data/lib/ruhoh.rb +28 -123
  13. data/lib/ruhoh/base/collectable.rb +273 -0
  14. data/lib/ruhoh/base/compilable.rb +30 -0
  15. data/lib/ruhoh/base/compilable_asset.rb +30 -0
  16. data/lib/ruhoh/base/model_viewable.rb +30 -0
  17. data/lib/ruhoh/base/modelable.rb +44 -0
  18. data/lib/ruhoh/base/page_like.rb +111 -0
  19. data/lib/ruhoh/base/page_viewable.rb +92 -0
  20. data/lib/ruhoh/base/routable.rb +20 -0
  21. data/lib/ruhoh/base/watchable.rb +18 -0
  22. data/lib/ruhoh/cascade.rb +93 -0
  23. data/lib/ruhoh/client.rb +1 -3
  24. data/lib/ruhoh/collections.rb +2 -1
  25. data/lib/ruhoh/config.rb +67 -0
  26. data/lib/ruhoh/console_methods.rb +0 -2
  27. data/lib/ruhoh/parse.rb +7 -5
  28. data/lib/ruhoh/plugins/initializer.rb +24 -0
  29. data/lib/ruhoh/plugins/local_plugins_plugin.rb +10 -0
  30. data/lib/ruhoh/plugins/plugin.rb +27 -0
  31. data/lib/ruhoh/programs/compile.rb +2 -6
  32. data/lib/ruhoh/programs/preview.rb +5 -2
  33. data/lib/ruhoh/programs/watch.rb +4 -6
  34. data/lib/ruhoh/publish/rsync.rb +2 -2
  35. data/lib/ruhoh/resources/_base/collection.rb +6 -0
  36. data/lib/ruhoh/resources/_base/compiler.rb +3 -0
  37. data/lib/ruhoh/resources/_base/model.rb +3 -0
  38. data/lib/ruhoh/resources/_base/model_view.rb +3 -0
  39. data/lib/ruhoh/resources/_base/watcher.rb +4 -0
  40. data/lib/ruhoh/resources/data/collection.rb +30 -9
  41. data/lib/ruhoh/resources/javascripts/collection_view.rb +5 -1
  42. data/lib/ruhoh/resources/javascripts/model_view.rb +15 -0
  43. data/lib/ruhoh/resources/layouts/client.rb +1 -1
  44. data/lib/ruhoh/resources/pages/client.rb +2 -2
  45. data/lib/ruhoh/resources/pages/collection.rb +2 -21
  46. data/lib/ruhoh/resources/theme/compiler.rb +2 -2
  47. data/lib/ruhoh/resources/widgets/collection.rb +2 -2
  48. data/lib/ruhoh/routes.rb +1 -1
  49. data/lib/ruhoh/summarizer.rb +2 -2
  50. data/lib/ruhoh/ui/dashboard.rb +13 -0
  51. data/lib/ruhoh/ui/page_not_found.rb +3 -2
  52. data/lib/ruhoh/url_slug.rb +23 -9
  53. data/lib/ruhoh/version.rb +1 -1
  54. data/lib/ruhoh/views/master_view.rb +1 -1
  55. data/spec/lib/ruhoh/plugins/initializer_spec.rb +43 -0
  56. data/spec/lib/ruhoh/plugins/plugin_spec.rb +40 -0
  57. data/spec/spec_helper.rb +1 -0
  58. data/system/config.json +21 -0
  59. data/system/{dash/index.html → dashboard.html} +1 -1
  60. data/{lib/ruhoh/ui → system}/page_not_found.html +0 -0
  61. data/system/plugins/sprockets/compiler.rb +1 -0
  62. data/system/widgets/comments/disqus.html +1 -1
  63. metadata +34 -15
  64. data/lib/ruhoh/base/collection.rb +0 -284
  65. data/lib/ruhoh/base/compiler.rb +0 -67
  66. data/lib/ruhoh/base/model.rb +0 -161
  67. data/lib/ruhoh/base/model_view.rb +0 -129
  68. data/lib/ruhoh/base/watcher.rb +0 -25
  69. data/lib/ruhoh/resources/dash/collection.rb +0 -10
  70. data/lib/ruhoh/resources/dash/model.rb +0 -5
  71. data/lib/ruhoh/resources/dash/model_view.rb +0 -5
  72. data/lib/ruhoh/resources/dash/previewer.rb +0 -13
@@ -2,17 +2,15 @@
2
2
  SampleSitePath = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '__tmp'))
3
3
 
4
4
  def start
5
- @ruhoh = Ruhoh.new
6
- @ruhoh.setup(:source => SampleSitePath)
5
+ @ruhoh = Ruhoh.new(:source => SampleSitePath)
7
6
  @ruhoh.env = :test
8
- @ruhoh.setup_paths
9
7
  @ruhoh.setup_plugins
10
8
  end
11
9
 
12
10
  def compile
13
11
  start
14
12
  @ruhoh.env = 'production'
15
- @ruhoh.paths.compiled = File.join(SampleSitePath, 'compiled')
13
+ @ruhoh.config['compiled_path'] = File.join(SampleSitePath, 'compiled')
16
14
  @ruhoh.compile
17
15
  end
18
16
 
@@ -55,7 +53,7 @@ TEXT
55
53
  end
56
54
 
57
55
  def get_compiled_file(path)
58
- FileUtils.cd(@ruhoh.paths.compiled) {
56
+ FileUtils.cd(@ruhoh.config['compiled_path']) {
59
57
  File.open(path, 'r:UTF-8') { |f|
60
58
  return f.read }
61
59
  }
@@ -1,4 +1,25 @@
1
1
  [
2
+ {
3
+ "version" : "2.6",
4
+ "date" : "13.12.2013",
5
+ "changes" : [
6
+ "config['compiled'] is now config['compiled_path'] and compiled folder is collection ignored.",
7
+ "Dash is no longer a collection, it is tracked on the root blog level and may be overloaded as normal."
8
+ ],
9
+ "features" : [
10
+ "config file now deep merges itself down the cascade.",
11
+ "data file now deep merges itself down the cascade.",
12
+ "page_not_found UI can now be overloaded via the cascade.",
13
+ "Any page metatdata attribute can be used in custom permalink",
14
+ "@nicolaracco adds ability to load plugins from gems."
15
+ ],
16
+ "bugs" : [
17
+ "@mudasobwa fix for non-ASCII summaries",
18
+ "custo data collections now work as expected as per the collection API.",
19
+ "@richtera enables ?to_javascripts to work with needed fingerpinting inclusion."
20
+ ]
21
+ }
22
+ ,
2
23
  {
3
24
  "version" : "2.5",
4
25
  "date" : "22.09.2013",
@@ -18,6 +18,8 @@ require 'ruhoh/utils'
18
18
  require 'ruhoh/friend'
19
19
  require 'ruhoh/parse'
20
20
 
21
+ require 'ruhoh/config'
22
+ require 'ruhoh/cascade'
21
23
  require 'ruhoh/converter'
22
24
  require 'ruhoh/views/master_view'
23
25
  require 'ruhoh/collections'
@@ -26,21 +28,24 @@ require 'ruhoh/routes'
26
28
  require 'ruhoh/string_format'
27
29
  require 'ruhoh/url_slug'
28
30
  require 'ruhoh/programs/preview'
31
+ require 'ruhoh/plugins/plugin'
29
32
 
30
33
  class Ruhoh
31
34
  class << self
32
35
  attr_accessor :log
33
- attr_reader :names, :root
36
+ attr_reader :root
34
37
  end
35
38
 
36
39
  attr_accessor :log, :env
37
- attr_reader :config, :paths, :root, :base, :cache, :collections, :routes
40
+ attr_reader :root, :cache, :collections, :routes
38
41
 
39
42
  Root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
40
43
  @log = Ruhoh::Logger.new
41
44
  @root = Root
42
45
 
43
- def initialize
46
+ def initialize(opts={})
47
+ self.class.log.log_file = opts[:log_file] if opts[:log_file] #todo
48
+ @base = opts[:source] ? opts[:source] : Dir.getwd
44
49
  @collections = Ruhoh::Collections.new(self)
45
50
  @cache = Ruhoh::Cache.new(self)
46
51
  @routes = Ruhoh::Routes.new(self)
@@ -50,119 +55,55 @@ class Ruhoh
50
55
  Ruhoh::Views::MasterView.new(self, pointer)
51
56
  end
52
57
 
53
- # Public: Setup Ruhoh utilities relative to the current application directory.
54
- # Returns boolean on success/failure
55
- def setup(opts={})
56
- self.class.log.log_file = opts[:log_file] if opts[:log_file] #todo
57
- @base = opts[:source] ? opts[:source] : Dir.getwd
58
- !!config
59
- end
60
-
61
58
  def collection(resource)
62
59
  @collections.load(resource)
63
60
  end
64
61
 
65
- def config(reload=false)
66
- return @config unless (reload or @config.nil?)
67
-
68
- config = Ruhoh::Parse.data_file(@base, "config") || {}
69
- config['compiled'] = config['compiled'] ? File.expand_path(config['compiled']) : "compiled"
70
-
71
- config['_root'] ||= {}
72
- config['_root']['permalink'] ||= "/:relative_path/:filename"
73
- config['_root']['paginator'] ||= {}
74
- config['_root']['paginator']['url'] ||= "/index/"
75
- config['_root']['rss'] ||= {}
76
- config['_root']['rss']['url'] ||= "/"
77
-
78
- config['base_path'] = config['base_path'].to_s.strip
79
- if config['base_path'].empty?
80
- config['base_path'] = '/'
81
- else
82
- config['base_path'] += "/" unless config['base_path'][-1] == '/'
83
- end
84
-
85
- Time.default_format = config['date_format'] || "%Y-%m-%d"
86
-
87
- @config = config
88
- end
89
-
90
- Paths = Struct.new(:base, :theme, :system, :compiled)
91
- def setup_paths
92
- @paths = Paths.new
93
- @paths.base = @base
94
- @paths.system = File.join(Ruhoh::Root, "system")
95
- @paths.compiled = @config["compiled"]
96
-
97
- theme = @config.find { |resource, data| data.is_a?(Hash) && data['use'] == "theme" }
98
- if theme
99
- Ruhoh::Friend.say { plain "Using theme: \"#{theme[0]}\""}
100
- @paths.theme = File.join(@base, theme[0])
101
- end
102
-
103
- @paths
62
+ def config
63
+ return @config if @config
64
+ @config = Ruhoh::Config.new(self)
65
+ @config.touch
104
66
  end
105
67
 
106
- # Default paths to the 3 levels of the cascade.
107
68
  def cascade
108
- a = [
109
- {
110
- "name" => "system",
111
- "path" => paths.system
112
- },
113
- {
114
- "name" => "base",
115
- "path" => paths.base
116
- }
117
- ]
118
- a << {
119
- "name" => "theme",
120
- "path" => paths.theme
121
- } if paths.theme
69
+ return @cascade if @cascade
122
70
 
123
- a
71
+ @cascade = Ruhoh::Cascade.new(config)
72
+ @cascade.base = @base
73
+ config.touch
74
+
75
+ @cascade
124
76
  end
125
77
 
126
78
  def setup_plugins
127
- ensure_paths
128
-
129
- enable_sprockets = @config['asset_pipeline']['enable'] rescue false
79
+ enable_sprockets = config['asset_pipeline']['enable'] rescue false
130
80
  if enable_sprockets
131
81
  Ruhoh::Friend.say { green "=> Oh boy! Asset pipeline enabled by way of sprockets =D" }
132
- sprockets = Dir[File.join(@paths.system, "plugins", "sprockets", "**/*.rb")]
82
+ sprockets = Dir[File.join(cascade.system, "plugins", "sprockets", "**/*.rb")]
133
83
  sprockets.each {|f| require f }
134
84
  end
85
+ require 'ruhoh/plugins/local_plugins_plugin'
135
86
 
136
- plugins = Dir[File.join(@base, "plugins", "**/*.rb")]
137
- plugins.each {|f| require f } unless plugins.empty?
87
+ Ruhoh::Plugins::Plugin.run_all self
138
88
  end
139
89
 
140
90
  def env
141
91
  @env || 'development'
142
92
  end
143
93
 
144
- def base_path
145
- return '/' unless (env == 'production')
146
-
147
- string = config['base_path'].chomp('/').reverse.chomp('/').reverse
148
- return '/' if string.empty? || string == '/'
149
- "/#{ string }/"
150
- end
151
-
152
94
  def compiled_path(url)
153
95
  if config['compile_as_root']
154
- url = url.gsub(/^#{ base_path.chomp('/') }\/?/, '')
96
+ url = url.gsub(/^#{ config.base_path.chomp('/') }\/?/, '')
155
97
  end
156
98
 
157
- path = File.expand_path(File.join(paths.compiled, url)).gsub(/\/{2,}/, '/')
99
+ path = File.expand_path(File.join(config['compiled_path'], url)).gsub(/\/{2,}/, '/')
158
100
  CGI.unescape(path)
159
101
  end
160
102
 
161
- # @config['base_path'] is assumed to be well-formed.
162
103
  # Always remove trailing slash.
163
104
  # Returns String - normalized url with prepended base_path
164
105
  def to_url(*args)
165
- url = base_path + args.join('/')
106
+ url = config.base_path + args.join('/')
166
107
  url = url.gsub(/\/{2,}/, '/')
167
108
  (url == "/") ? url : url.chomp('/')
168
109
  end
@@ -196,10 +137,9 @@ class Ruhoh
196
137
  # end
197
138
  # end
198
139
  def compile
199
- ensure_paths
200
140
  Ruhoh::Friend.say { plain "Compiling for environment: '#{@env}'" }
201
- FileUtils.rm_r @paths.compiled if File.exist?(@paths.compiled)
202
- FileUtils.mkdir_p @paths.compiled
141
+ FileUtils.rm_r config['compiled_path'] if File.exist?(config['compiled_path'])
142
+ FileUtils.mkdir_p config['compiled_path']
203
143
 
204
144
  # Run the resource compilers
205
145
  compilers = @collections.all
@@ -209,6 +149,7 @@ class Ruhoh
209
149
  compilers.delete('javascripts')
210
150
  compilers.unshift('javascripts')
211
151
 
152
+
212
153
  compilers.each do |name|
213
154
  collection = collection(name)
214
155
  next unless collection.compiler?
@@ -229,42 +170,6 @@ class Ruhoh
229
170
  true
230
171
  end
231
172
 
232
- # Find a file in the base cascade directories
233
- # @return[Hash, nil] a single file pointer
234
- def find_file(key)
235
- dict = _all_files
236
- dict[key] || dict.values.find{ |a| key == a['id'].gsub(/.[^.]+$/, '') }
237
- end
238
-
239
- # Collect all files from the base cascade directories.
240
- # @return[Hash] dictionary of file pointers
241
- def _all_files
242
- dict = {}
243
- cascade.map{ |a| a['path'] }.each do |path|
244
- FileUtils.cd(path) {
245
- Dir["*"].each { |id|
246
- next unless File.exist?(id) && FileTest.file?(id)
247
- dict[id] = {
248
- "id" => id,
249
- "realpath" => File.realpath(id),
250
- }
251
- }
252
- }
253
- end
254
-
255
- dict
256
- end
257
-
258
- def ensure_setup
259
- return if @config && @paths
260
- raise 'Ruhoh has not been fully setup. Please call: Ruhoh.setup'
261
- end
262
-
263
- def ensure_paths
264
- return if @config && @paths
265
- raise 'Ruhoh has not setup paths. Please call: Ruhoh.setup'
266
- end
267
-
268
173
  def self.collection(resource)
269
174
  Collections.load(resource)
270
175
  end
@@ -0,0 +1,273 @@
1
+ module Ruhoh::Base::Collectable
2
+ def self.included(klass)
3
+ klass.__send__(:attr_accessor, :resource_name, :master)
4
+ klass.__send__(:attr_reader, :ruhoh)
5
+ end
6
+
7
+ def initialize(ruhoh)
8
+ @ruhoh = ruhoh
9
+ end
10
+
11
+ # Public API for finding a resource from this collection
12
+ # @param name_or_pointer [String, Hash]
13
+ # Hash - File pointer
14
+ # String - id (filename) with full extension, e.g: about-me.md
15
+ # String - name (filename) without the extension e.g: about-me
16
+ # Returns the first matched filename.
17
+ # See implementation for how match is determined.
18
+ # @param opts [Hash] Optional options
19
+ # opts[:all] - true to search all files as some may be invalid as resources
20
+ #
21
+ # @return[model, nil] the model is always wrapped in its view.
22
+ def find(name_or_pointer, opts={})
23
+ pointer = find_file(name_or_pointer, opts)
24
+ return nil unless pointer
25
+
26
+ @ruhoh.cache.get(pointer['realpath']) ||
27
+ @ruhoh.cache.set(pointer['realpath'], load_model_view(pointer))
28
+ end
29
+
30
+ # Public API
31
+ # @return[Hash] dictionary of models { "id" => Model }
32
+ def dictionary
33
+ dict = {}
34
+ files.values.each { |pointer|
35
+ dict.merge!({
36
+ pointer['id'] => find(pointer)
37
+ })
38
+ }
39
+ dict
40
+ end
41
+
42
+ def resource_name
43
+ @resource_name ||= self.class.name.split("::").pop
44
+ end
45
+
46
+ # Implemented via Observable module
47
+ # See http://ruby-doc.org/stdlib-1.9.3/libdoc/observer/rdoc/Observable.html
48
+ # Collection subscribes to its child models.
49
+ # #update is called on model #process.
50
+ # noop
51
+ def update(model_data)
52
+ end
53
+
54
+ # The default glob for finding files.
55
+ # Every file in all child directories.
56
+ def glob
57
+ "**/*"
58
+ end
59
+
60
+ # Default paths to the 3 levels of the cascade.
61
+ def paths
62
+ Array(@ruhoh.cascade.paths.map{|h| h["path"]}).map { |path|
63
+ collection_path = File.join(path, resource_name)
64
+ next unless File.directory?(collection_path)
65
+
66
+ collection_path
67
+ }.compact
68
+ end
69
+
70
+ # Does this resource have any valid paths to process?
71
+ # A valid path may exist on any of the cascade levels.
72
+ # False means there are no directories on any cascade level.
73
+ # @returns[Boolean]
74
+ def paths?
75
+ !paths.empty?
76
+ end
77
+
78
+ def config
79
+ config = @ruhoh.config[resource_name] || {}
80
+ unless config.is_a?(Hash)
81
+ Ruhoh.log.error("'#{resource_name}' config key in config" +
82
+ " is a #{config.class}; it needs to be a Hash (object).")
83
+ end
84
+ config
85
+ end
86
+
87
+ # NOOP
88
+ # touch a model.
89
+ # Used to perform custom regeneration logic against a model.
90
+ def touch(name_or_pointer)
91
+ end
92
+
93
+ # @param key [String, Hash]
94
+ # String - id (filename) with full extension, e.g: about-me.md
95
+ # String - name (filename) without the extension e.g: about-me
96
+ # Returns the first matched filename.
97
+ # See implementation for how match is determined.
98
+ # Hash - File pointer
99
+ #
100
+ # @param opts [Hash] Optional options
101
+ # opts[:all] - true to search all files as some may be invalid as resources
102
+ #
103
+ # @return [pointer, nil]
104
+ def find_file(key, opts={})
105
+ return key if key.is_a?(Hash) # assume valid pointer
106
+
107
+ dict = opts[:all] ? _all_files : files
108
+
109
+ dict[key] || dict.values.find{ |a| key == a['id'].gsub(/.[^.]+$/, '') }
110
+ end
111
+
112
+ # Collect all files (as mapped by data resources) for this data endpoint.
113
+ # Each resource can have 3 file references, one per each cascade level.
114
+ # The file hashes are collected in order
115
+ # so they will overwrite eachother if found.
116
+
117
+ # @param id [String, Array] Optional.
118
+ # Collect all files for a single data resource.
119
+ # Can be many files due to the cascade.
120
+ # @param [block] Optional.
121
+ # Implement custom validation logic by passing in a block.
122
+ # The block is given (id, self) as args.
123
+ # Return true/false for whether the file is valid/invalid.
124
+ #
125
+ # @return[Hash] dictionary of pointers.
126
+ def files(id=nil, &block)
127
+ return @ruhoh.cache.get(files_cache_key) if @ruhoh.cache.get(files_cache_key)
128
+
129
+ dict = _all_files
130
+ dict.keep_if do |id, pointer|
131
+ block_given? ? yield(id, self) : valid_file?(id)
132
+ end
133
+
134
+ @ruhoh.cache.set(files_cache_key, dict)
135
+ dict
136
+ end
137
+
138
+ # Collect all files within this collection, valid or otherwise.
139
+ # Each resource can have 3 file references, one per each cascade level.
140
+ # The file hashes are collected in order and overwrite eachother if found.
141
+ # This is a low-level method, see #files for the public interface.
142
+ #
143
+ # @return[Hash] dictionary of pointers.
144
+ def _all_files
145
+ dict = {}
146
+ paths.each do |path|
147
+ FileUtils.cd(path) {
148
+ Dir[glob].each { |id|
149
+ next unless File.exist?(id) && FileTest.file?(id)
150
+ dict[id] = {
151
+ "id" => id,
152
+ "realpath" => File.realpath(id),
153
+ "resource" => resource_name,
154
+ }
155
+ }
156
+ }
157
+ end
158
+
159
+ dict
160
+ end
161
+
162
+ def valid_file?(filepath)
163
+ return false if filepath.start_with?('.')
164
+ return false if filepath.start_with?('_')
165
+ return false if %w{ config.json config.yaml config.yml }.include?(filepath)
166
+ excludes = Array(config['exclude']).map { |node| Regexp.new(node) }
167
+ excludes.each { |regex| return false if filepath =~ regex }
168
+ true
169
+ end
170
+
171
+ %w{
172
+ collection_view
173
+ model
174
+ model_view
175
+ client
176
+ compiler
177
+ watcher
178
+ previewer
179
+ }.each do |method_name|
180
+ define_method(method_name) do
181
+ get_module_namespace.const_get(camelize(method_name).to_sym)
182
+ end
183
+
184
+ define_method("#{method_name}?") do
185
+ get_module_namespace.const_defined?(camelize(method_name).to_sym)
186
+ end
187
+ end
188
+
189
+ def load_collection_view
190
+ @_collection_view ||= collection_view? ?
191
+ collection_view.new(self) :
192
+ self
193
+ end
194
+
195
+ def load_model(pointer)
196
+ _model = model? ?
197
+ model.new(@ruhoh, pointer) :
198
+ Ruhoh::Base::Model.new(@ruhoh, pointer)
199
+ _model.add_observer(self)
200
+ _model
201
+ end
202
+
203
+ def load_model_view(pointer)
204
+ model_view? ?
205
+ model_view.new(load_model(pointer)) :
206
+ Ruhoh::Base::ModelView.new(load_model(pointer))
207
+ end
208
+
209
+ def load_client(opts)
210
+ @_client ||= client.new(load_collection_view, opts)
211
+ end
212
+
213
+ def load_compiler
214
+ @_compiler ||= compiler.new(load_collection_view)
215
+ end
216
+
217
+ def load_watcher(*args)
218
+ @_watcher ||= watcher? ?
219
+ watcher.new(load_collection_view) :
220
+ Ruhoh::Base::Watcher.new(load_collection_view)
221
+ end
222
+
223
+ def load_previewer(*args)
224
+ @_previewer ||= previewer.new(@ruhoh)
225
+ end
226
+
227
+ def files_cache_key
228
+ "#{ resource_name }-files"
229
+ end
230
+
231
+ def scaffold
232
+ pointer = find_file('_scaffold', all: true) || @ruhoh.cascade.find_file('_scaffold')
233
+ return '' unless pointer
234
+
235
+ File.open(pointer['realpath'], 'r:UTF-8') { |f| f.read }
236
+ end
237
+
238
+ def compiled_path
239
+ @compiled_path ||= @ruhoh.compiled_path(@ruhoh.to_url(url_endpoint))
240
+ end
241
+
242
+ protected
243
+
244
+ # Load the registered resource else default to Pages if not configured.
245
+ # @returns[Constant] the resource's module namespace
246
+ def get_module_namespace
247
+ type = @ruhoh.config[resource_name]["use"] rescue nil
248
+ if type
249
+ if @ruhoh.collections.registered.include?(type)
250
+ Ruhoh::Resources.const_get(camelize(type))
251
+ elsif @ruhoh.collections.base.include?(type)
252
+ Ruhoh::Base.const_get(camelize(type))
253
+ else
254
+ klass = camelize(type)
255
+ Friend.say {
256
+ red "#{resource_name} resource set to use:'#{type}' in config" +
257
+ " but Ruhoh::Resources::#{klass} does not exist."
258
+ }
259
+ abort
260
+ end
261
+ else
262
+ if @ruhoh.collections.registered.include?(resource_name)
263
+ Ruhoh::Resources.const_get(camelize(resource_name))
264
+ else
265
+ Ruhoh::Resources.const_get(:Pages)
266
+ end
267
+ end
268
+ end
269
+
270
+ def camelize(name)
271
+ name.to_s.split('_').map { |a| a.capitalize }.join
272
+ end
273
+ end