spontaneous 0.2.0.beta4 → 0.2.0.beta5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/Gemfile +11 -6
  4. data/Readme.markdown +136 -69
  5. data/application/css/core.css.scss +27 -7
  6. data/application/css/editing.css.scss +4 -26
  7. data/application/css/schema_error.css.scss +22 -0
  8. data/application/js/content.js +11 -3
  9. data/application/js/edit_panel.js +1 -4
  10. data/application/js/field/file.js +17 -0
  11. data/application/js/field/image.js +30 -21
  12. data/application/js/field/string.js +4 -1
  13. data/application/js/field_preview.js +21 -16
  14. data/application/js/publish.js +6 -6
  15. data/application/js/types.js +5 -13
  16. data/application/js/views.js +2 -2
  17. data/application/js/views/box_view.js +3 -2
  18. data/application/js/views/page_piece_view.js +1 -1
  19. data/application/js/views/piece_view.js +1 -1
  20. data/application/views/schema_modification_error.html.erb +13 -3
  21. data/db/migrations/20131104101935_site_must_publish_all.rb +14 -0
  22. data/lib/spontaneous.rb +0 -1
  23. data/lib/spontaneous/box_style.rb +15 -9
  24. data/lib/spontaneous/capistrano/deploy.rb +13 -1
  25. data/lib/spontaneous/change.rb +11 -13
  26. data/lib/spontaneous/cli.rb +5 -2
  27. data/lib/spontaneous/cli/assets.rb +7 -1
  28. data/lib/spontaneous/cli/console.rb +7 -1
  29. data/lib/spontaneous/cli/content.rb +35 -0
  30. data/lib/spontaneous/cli/fields.rb +3 -2
  31. data/lib/spontaneous/cli/generate.rb +5 -2
  32. data/lib/spontaneous/cli/server.rb +12 -8
  33. data/lib/spontaneous/cli/site.rb +12 -12
  34. data/lib/spontaneous/cli/user.rb +28 -14
  35. data/lib/spontaneous/collections/box_set.rb +4 -4
  36. data/lib/spontaneous/collections/field_set.rb +4 -4
  37. data/lib/spontaneous/collections/prototype_set.rb +12 -4
  38. data/lib/spontaneous/data_mapper.rb +11 -7
  39. data/lib/spontaneous/data_mapper/content_model.rb +8 -0
  40. data/lib/spontaneous/data_mapper/content_model/associations.rb +1 -1
  41. data/lib/spontaneous/data_mapper/dataset.rb +14 -2
  42. data/lib/spontaneous/data_mapper/scope.rb +33 -13
  43. data/lib/spontaneous/facet.rb +4 -0
  44. data/lib/spontaneous/field.rb +12 -12
  45. data/lib/spontaneous/field/base.rb +27 -22
  46. data/lib/spontaneous/field/boolean.rb +4 -4
  47. data/lib/spontaneous/field/date.rb +2 -2
  48. data/lib/spontaneous/field/file.rb +24 -18
  49. data/lib/spontaneous/field/html.rb +1 -1
  50. data/lib/spontaneous/field/image.rb +6 -19
  51. data/lib/spontaneous/field/location.rb +1 -1
  52. data/lib/spontaneous/field/long_string.rb +3 -3
  53. data/lib/spontaneous/field/markdown.rb +3 -3
  54. data/lib/spontaneous/field/select.rb +2 -2
  55. data/lib/spontaneous/field/string.rb +2 -2
  56. data/lib/spontaneous/field/tags.rb +2 -2
  57. data/lib/spontaneous/field/update.rb +21 -20
  58. data/lib/spontaneous/field/webvideo.rb +6 -6
  59. data/lib/spontaneous/field/webvideo/fallback.rb +2 -2
  60. data/lib/spontaneous/field/webvideo/vimeo.rb +7 -7
  61. data/lib/spontaneous/generators/site.rb +2 -2
  62. data/lib/spontaneous/generators/site/Gemfile.tt +5 -1
  63. data/lib/spontaneous/layout.rb +2 -2
  64. data/lib/spontaneous/media.rb +1 -0
  65. data/lib/spontaneous/media/file.rb +6 -5
  66. data/lib/spontaneous/media/image/attributes.rb +4 -0
  67. data/lib/spontaneous/media/image/renderable.rb +4 -4
  68. data/lib/spontaneous/media/store.rb +22 -0
  69. data/lib/spontaneous/{storage → media/store}/backend.rb +1 -1
  70. data/lib/spontaneous/{storage → media/store}/cloud.rb +1 -1
  71. data/lib/spontaneous/{storage → media/store}/local.rb +1 -1
  72. data/lib/spontaneous/media/temp_file.rb +1 -1
  73. data/lib/spontaneous/model.rb +10 -7
  74. data/lib/spontaneous/model/action.rb +7 -0
  75. data/lib/spontaneous/model/action/clean.rb +87 -0
  76. data/lib/spontaneous/model/box/allowed_types.rb +15 -1
  77. data/lib/spontaneous/model/core.rb +10 -0
  78. data/lib/spontaneous/model/core/aliases.rb +1 -1
  79. data/lib/spontaneous/model/core/content_groups.rb +1 -1
  80. data/lib/spontaneous/model/core/fields.rb +1 -1
  81. data/lib/spontaneous/model/core/modifications.rb +2 -2
  82. data/lib/spontaneous/model/core/page_search.rb +4 -0
  83. data/lib/spontaneous/model/core/publishing.rb +4 -17
  84. data/lib/spontaneous/model/core/render.rb +4 -4
  85. data/lib/spontaneous/model/core/styles.rb +2 -2
  86. data/lib/spontaneous/model/core/visibility.rb +6 -2
  87. data/lib/spontaneous/model/page.rb +6 -2
  88. data/lib/spontaneous/model/page/controllers.rb +55 -17
  89. data/lib/spontaneous/model/page/formats.rb +12 -7
  90. data/lib/spontaneous/model/page/layouts.rb +2 -2
  91. data/lib/spontaneous/model/page/locks.rb +4 -1
  92. data/lib/spontaneous/model/page/page_tree.rb +40 -6
  93. data/lib/spontaneous/output.rb +14 -52
  94. data/lib/spontaneous/output/context.rb +11 -39
  95. data/lib/spontaneous/output/context/navigation.rb +31 -0
  96. data/lib/spontaneous/output/format.rb +15 -19
  97. data/lib/spontaneous/output/renderable.rb +99 -0
  98. data/lib/spontaneous/output/store.rb +24 -0
  99. data/lib/spontaneous/output/store/backend.rb +52 -0
  100. data/lib/spontaneous/output/store/file.rb +77 -0
  101. data/lib/spontaneous/output/store/moneta.rb +117 -0
  102. data/lib/spontaneous/output/store/revision.rb +34 -0
  103. data/lib/spontaneous/output/store/store.rb +15 -0
  104. data/lib/spontaneous/output/store/transaction.rb +44 -0
  105. data/lib/spontaneous/output/template/engine.rb +17 -7
  106. data/lib/spontaneous/output/template/renderer.rb +66 -40
  107. data/lib/spontaneous/page_lock.rb +5 -7
  108. data/lib/spontaneous/page_piece.rb +2 -2
  109. data/lib/spontaneous/permissions/user.rb +14 -7
  110. data/lib/spontaneous/plugins/application/features.rb +8 -4
  111. data/lib/spontaneous/plugins/application/state.rb +12 -6
  112. data/lib/spontaneous/prototypes/box_prototype.rb +9 -10
  113. data/lib/spontaneous/prototypes/field_prototype.rb +66 -15
  114. data/lib/spontaneous/publishing/immediate.rb +30 -26
  115. data/lib/spontaneous/rack.rb +12 -7
  116. data/lib/spontaneous/rack/back.rb +43 -37
  117. data/lib/spontaneous/rack/back/base.rb +4 -4
  118. data/lib/spontaneous/rack/back/changes.rb +2 -2
  119. data/lib/spontaneous/rack/back/file.rb +16 -24
  120. data/lib/spontaneous/rack/back/map.rb +5 -5
  121. data/lib/spontaneous/rack/back/preview.rb +3 -4
  122. data/lib/spontaneous/rack/back/schema.rb +1 -1
  123. data/lib/spontaneous/rack/back/site.rb +6 -7
  124. data/lib/spontaneous/rack/front.rb +19 -16
  125. data/lib/spontaneous/rack/middleware/authenticate.rb +3 -3
  126. data/lib/spontaneous/rack/middleware/reloader.rb +3 -2
  127. data/lib/spontaneous/rack/middleware/scope.rb +25 -19
  128. data/lib/spontaneous/rack/page_controller.rb +164 -13
  129. data/lib/spontaneous/rack/public.rb +23 -62
  130. data/lib/spontaneous/rack/static.rb +2 -3
  131. data/lib/spontaneous/schema.rb +27 -8
  132. data/lib/spontaneous/schema/schema_modification.rb +9 -1
  133. data/lib/spontaneous/schema/uid.rb +2 -2
  134. data/lib/spontaneous/schema/uid_map.rb +3 -2
  135. data/lib/spontaneous/search/database.rb +2 -2
  136. data/lib/spontaneous/search/field.rb +5 -3
  137. data/lib/spontaneous/search/index.rb +12 -7
  138. data/lib/spontaneous/search/results.rb +5 -3
  139. data/lib/spontaneous/server.rb +2 -2
  140. data/lib/spontaneous/site.rb +10 -3
  141. data/lib/spontaneous/site/features.rb +26 -6
  142. data/lib/spontaneous/site/helpers.rb +9 -12
  143. data/lib/spontaneous/site/level.rb +7 -9
  144. data/lib/spontaneous/site/map.rb +9 -11
  145. data/lib/spontaneous/site/paths.rb +5 -5
  146. data/lib/spontaneous/site/publishing.rb +83 -80
  147. data/lib/spontaneous/site/schema.rb +1 -7
  148. data/lib/spontaneous/site/search.rb +8 -18
  149. data/lib/spontaneous/site/selectors.rb +60 -54
  150. data/lib/spontaneous/site/state.rb +36 -30
  151. data/lib/spontaneous/site/storage.rb +10 -16
  152. data/lib/spontaneous/state.rb +8 -0
  153. data/lib/spontaneous/style.rb +32 -33
  154. data/lib/spontaneous/version.rb +1 -1
  155. data/spontaneous.gemspec +22 -21
  156. data/test/fixtures/public/templates/layouts/default.html.cut +1 -1
  157. data/test/fixtures/public/templates/layouts/default.pdf.cut +1 -1
  158. data/test/fixtures/public/templates/layouts/default.rss.cut +1 -1
  159. data/test/fixtures/search/config/indexes.rb +1 -1
  160. data/test/fixtures/serialisation/class_hash.yaml.erb +13 -1
  161. data/test/fixtures/serialisation/root_hash.yaml.erb +10 -0
  162. data/test/functional/test_application.rb +20 -24
  163. data/test/functional/test_back.rb +26 -27
  164. data/test/functional/test_cli.rb +146 -0
  165. data/test/functional/test_front.rb +287 -216
  166. data/test/functional/test_user_manager.rb +1 -1
  167. data/test/test_helper.rb +15 -11
  168. data/test/unit/test_alias.rb +32 -25
  169. data/test/unit/test_asset_bundler.rb +1 -1
  170. data/test/unit/test_assets.rb +34 -33
  171. data/test/unit/test_authentication.rb +1 -1
  172. data/test/unit/test_boxes.rb +16 -2
  173. data/test/unit/test_changesets.rb +23 -11
  174. data/test/unit/test_content.rb +15 -0
  175. data/test/unit/test_context.rb +139 -0
  176. data/test/unit/test_controllers.rb +374 -0
  177. data/test/{experimental → unit}/test_crypt.rb +0 -0
  178. data/test/unit/test_datamapper.rb +260 -237
  179. data/test/unit/test_datamapper_content.rb +42 -12
  180. data/test/{experimental → unit}/test_features.rb +85 -3
  181. data/test/unit/test_fields.rb +117 -42
  182. data/test/unit/test_formats.rb +11 -1
  183. data/test/unit/test_generators.rb +2 -2
  184. data/test/unit/test_helpers.rb +7 -8
  185. data/test/unit/test_images.rb +39 -2
  186. data/test/unit/test_layouts.rb +14 -12
  187. data/test/unit/test_media.rb +32 -23
  188. data/test/unit/test_output_store.rb +342 -0
  189. data/test/unit/test_page.rb +8 -1
  190. data/test/unit/test_permissions.rb +11 -7
  191. data/test/unit/test_plugins.rb +3 -3
  192. data/test/unit/test_prototype_set.rb +8 -1
  193. data/test/unit/test_publishing.rb +67 -54
  194. data/test/unit/test_render.rb +91 -38
  195. data/test/unit/test_revisions.rb +4 -4
  196. data/test/unit/test_schema.rb +109 -84
  197. data/test/unit/test_search.rb +42 -42
  198. data/test/unit/test_serialisation.rb +3 -2
  199. data/test/unit/test_site.rb +39 -27
  200. data/test/unit/test_storage.rb +9 -6
  201. data/test/unit/test_styles.rb +25 -32
  202. data/test/unit/test_templates.rb +8 -4
  203. metadata +89 -54
  204. data/lib/spontaneous/model/page/request.rb +0 -105
  205. data/lib/spontaneous/storage.rb +0 -22
@@ -7,9 +7,8 @@ module Spontaneous
7
7
  def initialize(app, options)
8
8
  @app = app
9
9
  @try = ['', *options.delete(:try)].compact
10
- @static = ::Rack::Static.new(
11
- lambda { |env| [404, {}, []] },
12
- options)
10
+ fallback_app = lambda { |env| [404, {}, []] }
11
+ @static = ::Rack::Static.new(fallback_app, options)
13
12
  end
14
13
 
15
14
  def call(env)
@@ -99,16 +99,16 @@ module Spontaneous
99
99
  end
100
100
  end
101
101
 
102
- def self.new(root, schema_loader_class = Spontaneous::Schema::PersistentMap)
103
- Schema.new(root, schema_loader_class)
102
+ def self.new(site, root, schema_loader_class = Spontaneous::Schema::PersistentMap)
103
+ Schema.new(site, root, schema_loader_class)
104
104
  end
105
105
 
106
106
  class Schema
107
107
  attr_accessor :schema_loader_class
108
108
  attr_reader :uids
109
109
 
110
- def initialize(root, schema_loader_class = Spontaneous::Schema::PersistentMap)
111
- @root = root
110
+ def initialize(site, root, schema_loader_class = Spontaneous::Schema::PersistentMap)
111
+ @site, @root = site, root
112
112
  @schema_loader_class = schema_loader_class
113
113
  @subclass_map = Hash.new { |h, k| h[k] = [] }
114
114
  initialize_uid_map
@@ -163,6 +163,7 @@ module Spontaneous
163
163
  case action
164
164
  when :delete
165
165
  uids.destroy(uid)
166
+ after_delete(uid)
166
167
  when :rename
167
168
  uid.rewrite!(dest)
168
169
  end
@@ -172,6 +173,17 @@ module Spontaneous
172
173
  logger.info("✓ Schema updated successfully")
173
174
  end
174
175
 
176
+ # now I want to clean up the content, removing any types associated with UIDs
177
+ # that no longer exist and then cleaning up after that by looking for any
178
+ # instances with an invalid content path. This can happen because when a
179
+ # type is removed it becomes difficult to instantiate any entries that remain
180
+ # in the db
181
+ def after_delete(uid)
182
+ result = Spontaneous::Model::Action::Clean.run(@site)
183
+ logger.warn("Deleted #{result[:invalid]} invalid and #{result[:orphans]} orphaned content instances.")
184
+ logger.warn("Site must_publish_all flag has been set") if result[:publish]
185
+ end
186
+
175
187
  def generate_new_schema
176
188
  logger.info("Generating new schema map at #{schema_map_file}")
177
189
  self.schema_loader_class = TransientMap
@@ -275,7 +287,8 @@ module Spontaneous
275
287
  end
276
288
 
277
289
  def excluded_types
278
- [Spontaneous::Content, Spontaneous::Content::Page, Spontaneous::Content::Piece]
290
+ model = @site.model
291
+ [model, model::Page, model::Piece]
279
292
  end
280
293
 
281
294
  def inheritance_map
@@ -302,7 +315,11 @@ module Spontaneous
302
315
  # TODO: Find a way to filter out the top-level classes without hard-coding
303
316
  # them here.
304
317
  def content_classes
305
- classes.reject { |k| k.is_box? }.uniq
318
+ classes.select { |k| k.is_a?(Spontaneous::DataMapper::ContentModel) }.uniq
319
+ end
320
+
321
+ def types
322
+ content_classes
306
323
  end
307
324
 
308
325
  def recurse_classes(root_class, list)
@@ -314,17 +331,18 @@ module Spontaneous
314
331
 
315
332
  def reset!
316
333
  @classes = []
334
+ @types = []
317
335
  @inheritance_map = nil
318
336
  reload!
319
337
  end
320
338
 
321
339
  def reload!
322
- @map = nil
340
+ @map = nil
323
341
  initialize_uid_map
324
342
  end
325
343
 
326
344
  def initialize_uid_map
327
- @uids = Spontaneous::Schema::UIDMap.new
345
+ @uids = Spontaneous::Schema::UIDMap.new(@site)
328
346
  end
329
347
 
330
348
  # It's obvious from this method that schema classes are
@@ -341,6 +359,7 @@ module Spontaneous
341
359
 
342
360
  def constants_of(klass)
343
361
  return [] unless klass.respond_to?(:constants)
362
+ return [] if klass == ::BasicObject
344
363
  klass.constants.
345
364
  select { |c| klass.const_defined?(c, false) }.
346
365
  map { |c| klass.const_get(c) }
@@ -67,7 +67,7 @@ module Spontaneous
67
67
  end
68
68
 
69
69
  def simple_change?
70
- only_removed_items? or only_added_items?
70
+ only_removed_fields? or only_added_items?
71
71
  end
72
72
 
73
73
  def only_added_items?
@@ -78,6 +78,14 @@ module Spontaneous
78
78
  end
79
79
  end
80
80
 
81
+ def only_removed_fields?
82
+ if removed_items.empty?
83
+ false
84
+ else
85
+ added_items.empty? && removed_items.all? { |uid| uid.category == :field }
86
+ end
87
+ end
88
+
81
89
  def only_removed_items?
82
90
  if removed_items.empty?
83
91
  false
@@ -26,10 +26,10 @@ module Spontaneous
26
26
  map.destroy(self)
27
27
  end
28
28
 
29
- def after_destroy
29
+ def after_destroy(site)
30
30
  case @category
31
31
  when :box
32
- Spontaneous::Content.filter(:box_sid => @id).delete
32
+ site.model.filter(:box_sid => @id).delete
33
33
  end
34
34
  end
35
35
 
@@ -25,7 +25,8 @@ module Spontaneous::Schema
25
25
 
26
26
  include Enumerable
27
27
 
28
- def initialize
28
+ def initialize(site)
29
+ @site = site
29
30
  @instance_lock = Mutex.new
30
31
  @instances = {}
31
32
  end
@@ -66,7 +67,7 @@ module Spontaneous::Schema
66
67
  def destroy(uid)
67
68
  @instance_lock.synchronize do
68
69
  @instances.delete(uid.to_s)
69
- uid.after_destroy
70
+ uid.after_destroy(@site)
70
71
  end
71
72
  end
72
73
 
@@ -79,13 +79,13 @@ module Spontaneous::Search
79
79
  if autocorrect and xapian_results.empty? and !corrected_query.blank?
80
80
  xapian_results = database.search(corrected_query, options)
81
81
  end
82
- Results.new(xapian_results, corrected_query)
82
+ Results.new(@index.model, xapian_results, corrected_query)
83
83
  end
84
84
 
85
85
  alias_method :<<, :add
86
86
 
87
87
  def directory
88
- S::Site.revision_dir(@revision) / "indexes" / @index.name
88
+ @index.site.revision_dir(@revision) / "indexes" / @index.name
89
89
  end
90
90
  end # Database
91
91
  end
@@ -4,7 +4,9 @@ module Spontaneous::Search
4
4
  class Field
5
5
  attr_reader :prototype, :options
6
6
 
7
- def initialize(prototype, options)
7
+ # TODO: options seems redundant as its available as prototype.options
8
+ def initialize(site, prototype, options)
9
+ @site = site
8
10
  @prototype = prototype
9
11
  @options = options
10
12
  end
@@ -58,7 +60,7 @@ module Spontaneous::Search
58
60
  # options. Each entry contains the index to which it pertains and then
59
61
  # the options that should be applied to this field within that index
60
62
  def parse_indexes(opts)
61
- all_indexes = S::Site.indexes.values
63
+ all_indexes = @site.indexes.values
62
64
  case opts
63
65
  when true
64
66
  all_indexes.map { |index| default_index_options(index) }
@@ -87,7 +89,7 @@ module Spontaneous::Search
87
89
  end
88
90
 
89
91
  def find_index(name)
90
- index = S::Site.indexes[name]
92
+ index = @site.indexes[name]
91
93
  logger.warn("Invalid index :#{name} for field #{@prototype.owner}.#{@prototype.name}") unless index
92
94
  index
93
95
  end
@@ -5,9 +5,10 @@ require 'xapian-fu'
5
5
  module Spontaneous::Search
6
6
  class Index
7
7
 
8
- attr_reader :name, :search_types
8
+ attr_reader :name, :search_types, :site
9
9
 
10
- def initialize(name, &definition)
10
+ def initialize(site, name, &definition)
11
+ @site = site
11
12
  @name = name
12
13
  @search_types = base_search_types
13
14
  @include_pages = nil
@@ -43,7 +44,7 @@ module Spontaneous::Search
43
44
  database.search(query, options)
44
45
  end
45
46
 
46
- def database(revision = Spontaneous::Site.published_revision)
47
+ def database(revision = @site.published_revision)
47
48
  Database.new(self, revision)
48
49
  end
49
50
 
@@ -156,6 +157,10 @@ module Spontaneous::Search
156
157
  include_type?(content.class) and include_page?(content.page)
157
158
  end
158
159
 
160
+ def model
161
+ @site.model
162
+ end
163
+
159
164
  protected
160
165
 
161
166
  def include_type?(type)
@@ -185,7 +190,7 @@ module Spontaneous::Search
185
190
  when /\A[\/#]/
186
191
  page.path == selector
187
192
  when /\A(>=?)\s+(.+)\z/
188
- rule, root = $1, S::Site[$2]
193
+ rule, root = $1, @site[$2]
189
194
  root.send(rule, page)
190
195
  else
191
196
  false
@@ -193,7 +198,7 @@ module Spontaneous::Search
193
198
  end
194
199
 
195
200
  def resolve_page_list(pages)
196
- pages.map { |p| S::Site[p] }
201
+ pages.map { |p| @site[p] }
197
202
  end
198
203
 
199
204
  def base_search_types
@@ -216,11 +221,11 @@ module Spontaneous::Search
216
221
  end
217
222
 
218
223
  def all_types
219
- S.schema.classes
224
+ @site.schema.classes
220
225
  end
221
226
 
222
227
  def all_page_types
223
- S.schema.classes.select { |klass| klass.page? }
228
+ @site.schema.classes.select { |klass| klass.page? }
224
229
  end
225
230
  end # Index
226
231
  end # Spontaneous
@@ -11,8 +11,10 @@ module Spontaneous::Search
11
11
 
12
12
  def_delegators :@results, :current_page, :per_page, :total_pages, :next_page, :offset, :previous_page, :total_entries
13
13
 
14
- def initialize(result_set, corrected_query = nil)
15
- @results, @corrected_query = result_set, corrected_query
14
+ def initialize(model, result_set, corrected_query = nil)
15
+ @model = model
16
+ @results = result_set
17
+ @corrected_query = corrected_query
16
18
  end
17
19
 
18
20
  def corrected_query
@@ -28,7 +30,7 @@ module Spontaneous::Search
28
30
  end
29
31
 
30
32
  def pages
31
- @page_list ||= Spontaneous::Content.get(@results.map { |doc| doc.id })
33
+ @page_list ||= @model.get(@results.map { |doc| doc.id })
32
34
  end
33
35
  end # Results
34
36
  end
@@ -12,7 +12,7 @@ module Spontaneous
12
12
  Handlers = %w[thin] unless const_defined?(:Handlers)
13
13
 
14
14
 
15
- def self.run!(options={})
15
+ def self.run!(site, options={})
16
16
  host = options["host"] || Spontaneous::Site.config.host || "0.0.0.0"
17
17
  port = options["port"] || Spontaneous::Site.config.port || 2012
18
18
  adapter = options["adapter"] || Spontaneous::Site.config.adapter
@@ -33,7 +33,7 @@ module Spontaneous
33
33
  end
34
34
  puts "=> Spontaneous:#{Spontaneous.mode.to_s.ljust(5, " ")} running on port #{host}:#{port} (PID #{$$})"
35
35
 
36
- handler.run Spontaneous::Rack.application.to_app, :Host => host, :Port => port do |server|
36
+ handler.run Spontaneous::Rack.application(site).to_app, :Host => host, :Port => port do |server|
37
37
  term = Proc.new do
38
38
  server.respond_to?(:stop!) ? server.stop! : server.stop
39
39
  puts "=> Spontaneous:#{Spontaneous.mode.to_s.ljust(5, " ")} exiting..."
@@ -35,13 +35,17 @@ module Spontaneous
35
35
  include URL
36
36
 
37
37
  attr_accessor :database
38
- attr_reader :environment, :mode
38
+ attr_reader :environment, :mode, :model
39
39
 
40
40
  def initialize(root, env, mode)
41
41
  super(root)
42
42
  @environment, @mode = env, mode
43
43
  end
44
44
 
45
+ def model=(content_model)
46
+ @model = content_model
47
+ end
48
+
45
49
  def initialize!
46
50
  load_config!
47
51
  connect_to_database!
@@ -79,8 +83,11 @@ module Spontaneous
79
83
 
80
84
 
81
85
  def connect_to_database!
82
- self.database = Sequel.connect(db_settings)
83
- self.database.logger = logger if config.log_queries
86
+ db = Sequel.connect(db_settings)
87
+ db.logger = logger if config.log_queries
88
+ # Improve performance for postgres
89
+ db.optimize_model_load = true if db.respond_to?(:optimize_model_load)
90
+ self.database = db
84
91
  end
85
92
 
86
93
  def db_settings
@@ -5,6 +5,16 @@ class Spontaneous::Site
5
5
  module Features
6
6
  extend Spontaneous::Concern
7
7
 
8
+ class Middleware
9
+ def use(*args, &block)
10
+ middleware << [args, block]
11
+ end
12
+
13
+ def middleware
14
+ @middleware ||= []
15
+ end
16
+ end
17
+
8
18
  # InstanceMethods
9
19
  def back_controllers
10
20
  @back_controllers ||= []
@@ -14,14 +24,24 @@ class Spontaneous::Site
14
24
  @front_controllers ||= []
15
25
  end
16
26
 
17
- def register_back_controller(namespace, controller_class)
18
- app = Spontaneous::Rack.make_back_controller(controller_class)
19
- back_controllers << [namespace_url(namespace), app]
27
+ # Mounts an app into the authenticated CMS application
28
+ # namespace: the namespace of the app. A namespace of `moderation` will be mounted
29
+ # inside the CMS as /@moderation
30
+ # app: A Rack compatible class or Proc
31
+ def register_back_controller(namespace, app, opts = {})
32
+ app = Spontaneous::Rack.make_back_controller(app, self)
33
+ path_prefix = opts.fetch(:path_prefix, namespace_url(namespace))
34
+ back_controllers << [path_prefix, app]
35
+ end
36
+
37
+ def register_front_controller(namespace, app, opts = {})
38
+ app = Spontaneous::Rack.make_front_controller(app, self)
39
+ path_prefix = opts.fetch(:path_prefix, namespace_url(namespace))
40
+ front_controllers << [path_prefix, app]
20
41
  end
21
42
 
22
- def register_front_controller(namespace, controller_class)
23
- app = Spontaneous::Rack.make_front_controller(controller_class)
24
- front_controllers << [namespace_url(namespace), app]
43
+ def front
44
+ @front_middleware ||= Middleware.new
25
45
  end
26
46
 
27
47
  def namespace_url(namespace)
@@ -4,7 +4,7 @@ class Spontaneous::Site
4
4
  module Helpers
5
5
  extend Spontaneous::Concern
6
6
 
7
- module ClassMethods
7
+ # module ClassMethods
8
8
  def helper(*formats, &block)
9
9
  helper_module = Module.new(&block)
10
10
  register_helper(helper_module, helper_module_name(caller), *formats.flatten)
@@ -12,7 +12,8 @@ class Spontaneous::Site
12
12
  end
13
13
 
14
14
  def helper_module_name(_caller)
15
- path = _caller.first.split(':').first.split('/')[-5..-1]
15
+ parts = _caller.first.split(':').first.split('/')
16
+ path = parts[-([5, parts.length].min)..-1]
16
17
  path.join('_').gsub(/[^A-Za-z_]/, '_').gsub(/_+/, '_').gsub(/^_+/, '').capitalize
17
18
  end
18
19
 
@@ -25,7 +26,7 @@ class Spontaneous::Site
25
26
  helper_module.send :include, mod
26
27
  helper_module.send :extend, mod
27
28
  end
28
- Spontaneous::Site.registered_helpers[format].each do |mod|
29
+ registered_helpers[format].each do |mod|
29
30
  helper_module.send :include, mod
30
31
  helper_module.send :extend, mod
31
32
  end
@@ -34,8 +35,8 @@ class Spontaneous::Site
34
35
  end
35
36
 
36
37
  def register_helper(helper_module, module_name, *formats)
37
- site = instance
38
- helpers = site.registered_helpers
38
+ site = self
39
+ helpers = registered_helpers
39
40
  if formats.empty?
40
41
  helpers[:*] << helper_module
41
42
  else
@@ -43,23 +44,19 @@ class Spontaneous::Site
43
44
  helpers[format.to_sym] << helper_module
44
45
  end
45
46
  end
46
- # Spontaneous::Site::Helpers.const_set(module_name, helper_module)
47
47
  def helper_module.__finalize
48
- Spontaneous::Site.unregister_helper(self)
48
+ site.unregister_helper(self)
49
49
  end
50
50
  end
51
51
 
52
52
  def unregister_helper(helper_module)
53
- helpers = instance.registered_helpers
53
+ helpers = registered_helpers
54
54
  helpers.each do |format, helpers|
55
55
  helpers.delete(helper_module)
56
56
  end
57
57
  end
58
58
 
59
- def registered_helpers
60
- instance.registered_helpers
61
- end
62
- end
59
+ # end
63
60
 
64
61
  def registered_helpers
65
62
  @registered_helpers ||= Hash.new { |hash, key| hash[key] = [] }