ruhoh 2.5 → 2.6

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 (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