cortex-reaver 0.0.9 → 0.1.0

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 (77) hide show
  1. data/bin/cortex_reaver +7 -2
  2. data/lib/cortex_reaver.rb +51 -71
  3. data/lib/cortex_reaver/config.rb +23 -7
  4. data/lib/cortex_reaver/controller/admin.rb +6 -8
  5. data/lib/cortex_reaver/controller/comment.rb +17 -17
  6. data/lib/cortex_reaver/controller/config.rb +3 -2
  7. data/lib/cortex_reaver/controller/controller.rb +22 -0
  8. data/lib/cortex_reaver/controller/documentation.rb +1 -3
  9. data/lib/cortex_reaver/controller/journal.rb +13 -12
  10. data/lib/cortex_reaver/controller/main.rb +36 -29
  11. data/lib/cortex_reaver/controller/page.rb +15 -11
  12. data/lib/cortex_reaver/controller/photograph.rb +21 -15
  13. data/lib/cortex_reaver/controller/project.rb +16 -13
  14. data/lib/cortex_reaver/controller/tag.rb +16 -14
  15. data/lib/cortex_reaver/controller/user.rb +11 -13
  16. data/lib/cortex_reaver/helper/attachments.rb +18 -12
  17. data/lib/cortex_reaver/helper/auth.rb +2 -2
  18. data/lib/cortex_reaver/helper/canonical.rb +2 -2
  19. data/lib/cortex_reaver/helper/crud.rb +78 -38
  20. data/lib/cortex_reaver/helper/feeds.rb +2 -5
  21. data/lib/cortex_reaver/helper/form.rb +1 -1
  22. data/lib/cortex_reaver/helper/navigation.rb +1 -1
  23. data/lib/cortex_reaver/helper/photographs.rb +12 -3
  24. data/lib/cortex_reaver/helper/template.rb +37 -0
  25. data/lib/cortex_reaver/{view/blank_layout.rhtml → layout/blank.rhtml} +1 -1
  26. data/lib/cortex_reaver/{view/text_layout.rhtml → layout/text.rhtml} +1 -1
  27. data/lib/cortex_reaver/migrations/013_draft.rb +17 -0
  28. data/lib/cortex_reaver/model/comment.rb +64 -53
  29. data/lib/cortex_reaver/model/journal.rb +23 -21
  30. data/lib/cortex_reaver/model/model.rb +9 -0
  31. data/lib/cortex_reaver/model/page.rb +24 -42
  32. data/lib/cortex_reaver/model/photograph.rb +17 -17
  33. data/lib/cortex_reaver/model/project.rb +21 -18
  34. data/lib/cortex_reaver/model/tag.rb +12 -8
  35. data/lib/cortex_reaver/model/user.rb +79 -41
  36. data/lib/cortex_reaver/public/css/main.css +4 -0
  37. data/lib/cortex_reaver/snippets/numeric.rb +15 -0
  38. data/lib/cortex_reaver/snippets/ramaze/cache/memcached.rb +14 -0
  39. data/lib/cortex_reaver/support/attachments.rb +113 -105
  40. data/lib/cortex_reaver/support/cached_rendering.rb +65 -62
  41. data/lib/cortex_reaver/support/canonical.rb +82 -85
  42. data/lib/cortex_reaver/support/comments.rb +57 -51
  43. data/lib/cortex_reaver/support/cortex_reaver_validation_helpers.rb +13 -0
  44. data/lib/cortex_reaver/support/sequenceable.rb +202 -203
  45. data/lib/cortex_reaver/support/tags.rb +103 -94
  46. data/lib/cortex_reaver/support/timestamps.rb +27 -21
  47. data/lib/cortex_reaver/support/viewable.rb +17 -0
  48. data/lib/cortex_reaver/version.rb +3 -3
  49. data/lib/cortex_reaver/view/admin/index.rhtml +2 -2
  50. data/lib/cortex_reaver/view/comments/comment.rhtml +4 -1
  51. data/lib/cortex_reaver/view/comments/list.rhtml +1 -1
  52. data/lib/cortex_reaver/view/comments/post_form.rhtml +1 -1
  53. data/lib/cortex_reaver/view/journals/form.rhtml +3 -1
  54. data/lib/cortex_reaver/view/journals/journal.rhtml +6 -4
  55. data/lib/cortex_reaver/view/journals/list.rhtml +2 -2
  56. data/lib/cortex_reaver/view/journals/show.rhtml +1 -1
  57. data/lib/cortex_reaver/view/pages/form.rhtml +2 -1
  58. data/lib/cortex_reaver/view/pages/list.rhtml +2 -2
  59. data/lib/cortex_reaver/view/pages/show.rhtml +1 -1
  60. data/lib/cortex_reaver/view/photographs/form.rhtml +7 -3
  61. data/lib/cortex_reaver/view/photographs/list.rhtml +1 -1
  62. data/lib/cortex_reaver/view/photographs/show.rhtml +7 -7
  63. data/lib/cortex_reaver/view/projects/form.rhtml +1 -0
  64. data/lib/cortex_reaver/view/projects/list.rhtml +3 -3
  65. data/lib/cortex_reaver/view/projects/show.rhtml +5 -2
  66. data/lib/cortex_reaver/view/tags/list.rhtml +6 -2
  67. data/lib/cortex_reaver/view/tags/show.rhtml +10 -5
  68. data/lib/cortex_reaver/view/users/form.rhtml +1 -1
  69. data/lib/cortex_reaver/view/users/list.rhtml +5 -2
  70. data/lib/cortex_reaver/view/users/login.rhtml +1 -1
  71. data/lib/cortex_reaver/view/users/show.rhtml +5 -1
  72. metadata +159 -149
  73. data/lib/cortex_reaver/public/dispatch.fcgi +0 -11
  74. data/lib/cortex_reaver/snippets/ramaze/dispatcher/file.rb +0 -37
  75. data/lib/cortex_reaver/support/pagination.rb +0 -38
  76. data/lib/cortex_reaver/view/error.rhtml +0 -72
  77. data/lib/cortex_reaver/view/photographs/short.rhtml +0 -3
@@ -4,6 +4,24 @@ module Ramaze
4
4
  module Attachments
5
5
  Helper::LOOKUP << self
6
6
 
7
+ def self.included(base)
8
+ base.instance_eval do
9
+ # Saves all attachments from a request which match form to model.
10
+ # Returns true if all were successful. Returns an array of
11
+ # attachments which were added.
12
+ def self.add_attachments(model, attachments)
13
+ return unless attachments.respond_to? :each
14
+
15
+ attachments.each do |key, file|
16
+ if tempfile = file[:tempfile] and filename = file[:filename] and not filename.blank?
17
+ model.attachment(filename).file = tempfile
18
+ end
19
+ end
20
+ attachments
21
+ end
22
+ end
23
+ end
24
+
7
25
  # Deletes an attachment on a model identified by id.
8
26
  def delete_attachment(id, name)
9
27
  unless @model = model_class.get(id)
@@ -33,18 +51,6 @@ module Ramaze
33
51
 
34
52
  private
35
53
 
36
- # Saves all attachments from a request which match form to model. Returns true if
37
- # all were successful. Returns an array of attachments which were added.
38
- def add_attachments(model, attachments)
39
- attachments.each do |key, file|
40
- puts "adding #{key}: #{file.inspect}"
41
- if tempfile = file[:tempfile] and filename = file[:filename] and not filename.blank?
42
- model.attachment(filename).file = tempfile
43
- end
44
- end
45
- attachments
46
- end
47
-
48
54
  # Renders an attachments form for a model. Shows current attachments,
49
55
  # provides links to edit/delete, and a multiple-upload box. Doesn't
50
56
  # include form tags.
@@ -12,11 +12,11 @@ module Ramaze
12
12
  # Failed block
13
13
  if session[:user]
14
14
  flash[:error] = "You don't have permission to do this."
15
- redirect :/
15
+ redirect CortexReaver::MainController.r
16
16
  else
17
17
  flash[:notice] = "Please log in first."
18
18
  session[:target_uri] = request.request_uri
19
- redirect R('/users', :login)
19
+ redirect CortexReaver::UserController.r(:login)
20
20
  end
21
21
  end
22
22
  end
@@ -28,7 +28,7 @@ module Ramaze
28
28
 
29
29
  // Updates the "name" field as the watched field changes.
30
30
  $('##{watch}').change(function () {
31
- $.get('#{Rs('canonicalize')}', {
31
+ $.get('#{rs('canonicalize')}', {
32
32
  new: $('##{watch}').val(),
33
33
  id: '#{model.id}'
34
34
  }, function(response) {
@@ -38,7 +38,7 @@ $('##{watch}').change(function () {
38
38
 
39
39
  // Canonicalizes the name when we're done, just to make sure.
40
40
  $('##{name}').blur(function() {
41
- $.get('#{Rs('canonicalize')}', {
41
+ $.get('#{rs('canonicalize')}', {
42
42
  new: $('##{name}').val(),
43
43
  id: '#{model.id}'
44
44
  }, function(response) {
@@ -24,6 +24,11 @@ module Ramaze
24
24
  # journal.title = request[:title]
25
25
  # journal.body = request[:body].downcase
26
26
  # end
27
+ #
28
+ # You can also define on_save, on_second_save, and on_update methods
29
+ # which will be called after the blocks. The difference is that the
30
+ # block forms are evaluated in the class, and the method forms are
31
+ # evaluated in the context of the instance.
27
32
 
28
33
  def self.on_create(&block)
29
34
  unless block_given? and block.arity == 2
@@ -84,14 +89,6 @@ module Ramaze
84
89
  const_set('PLURAL_MODEL_VAR', const_get('SINGULAR_MODEL_VAR').pluralize)
85
90
  end
86
91
 
87
- # Prevent conflicts with our 0-ary action methods. Not needed if
88
- # we're using controller/show/name instead of controller/name
89
- #
90
- #begin
91
- # const_get('MODEL').reserved_canonical_names += ['index', 'new']
92
- #rescue
93
- #end
94
-
95
92
  # This action can't be in the normal module body, or it breaks things.
96
93
  def new
97
94
  # You need to be able to create one of these.
@@ -112,9 +109,15 @@ module Ramaze
112
109
  if block = self.class.on_save_block
113
110
  block.call(@model, request)
114
111
  end
112
+ if respond_to? :on_save
113
+ on_save(@model, request)
114
+ end
115
115
  if block = self.class.on_create_block
116
116
  block.call(@model, request)
117
117
  end
118
+ if respond_to? :on_create
119
+ on_create(@model, request)
120
+ end
118
121
 
119
122
  # Save for the first time
120
123
  raise unless @model.save
@@ -122,6 +125,11 @@ module Ramaze
122
125
  # Second save callback, if applicable
123
126
  if block = self.class.on_second_save_block
124
127
  block.call(@model, request)
128
+ end
129
+ if respond_to? :on_second_save
130
+ on_second_save @model, request
131
+ end
132
+ if block or respond_to? :on_second_save
125
133
  raise unless @model.save
126
134
  end
127
135
 
@@ -131,7 +139,13 @@ module Ramaze
131
139
  rescue => e
132
140
  # An error occurred
133
141
  Ramaze::Log.error e.inspect + e.backtrace.join("\n")
134
- flash[:error] = "Couldn't create #{model_class.to_s.demodulize.downcase} #{h request[:title]}: #{h e}."
142
+
143
+ if e.is_a? Sequel::ValidationFailed
144
+ flash[:error] = "Couldn't update #{model_class.to_s.demodulize.downcase} #{h @model.to_s}, because there were errors in the form."
145
+ else
146
+ flash[:error] = "Couldn't create #{model_class.to_s.demodulize.downcase} #{h request[:title]}: #{h e}."
147
+ end
148
+
135
149
  set_singular_model_var @model
136
150
  end
137
151
  else
@@ -166,10 +180,10 @@ module Ramaze
166
180
  if id
167
181
  # Redirect to show
168
182
  #
169
- # This way, you can (assuming your name doesn't conflict with an existing
170
- # action) tell people to visit /journals/my-cool-event, and it will go to
171
- # /journals/show/my-cool-event.
172
- raw_redirect Rs(:show, id), :status => 301
183
+ # This way, you can (assuming your name doesn't conflict with an
184
+ # existing action) tell people to visit /journals/my-cool-event, and
185
+ # it will go to /journals/show/my-cool-event.
186
+ raw_redirect rs(:show, id), :status => 301
173
187
  else
174
188
  # Display index
175
189
  page :last
@@ -182,16 +196,22 @@ module Ramaze
182
196
  u.can_edit? @model
183
197
  end
184
198
 
185
- if @model.destroy
199
+ begin
200
+ raise unless @model.destroy
186
201
  flash[:notice] = "#{model_class.to_s.demodulize.downcase} #{h @model.to_s} deleted."
187
- redirect Rs()
188
- else
202
+ redirect rs()
203
+ rescue => e
189
204
  flash[:notice] = "Couldn't delete #{model_class.to_s.demodulize.downcase} #{h @model.to_s}."
205
+ if @model.errors.size > 0
206
+ flash[:notice] << ' ' + @model.errors.to_s
207
+ else
208
+ flash[:notice] << ' ' + e.message
209
+ end
190
210
  redirect @model.url
191
211
  end
192
212
  else
193
213
  flash[:error] = "No such #{model_class.to_s.demodulize.downcase} (#{h id}) exists."
194
- redirect Rs()
214
+ redirect rs()
195
215
  end
196
216
  end
197
217
 
@@ -214,9 +234,15 @@ module Ramaze
214
234
  if block = self.class.on_save_block
215
235
  block.call(@model, request)
216
236
  end
237
+ if respond_to? :on_save
238
+ on_save @model, request
239
+ end
217
240
  if block = self.class.on_update_block
218
241
  block.call(@model, request)
219
242
  end
243
+ if respond_to? :on_update
244
+ on_update @model, request
245
+ end
220
246
 
221
247
  # Save
222
248
  raise unless @model.save
@@ -224,13 +250,16 @@ module Ramaze
224
250
  # Second callbacks and save if applicable
225
251
  if block = self.class.on_second_save_block
226
252
  block.call(@model, request)
253
+ end
254
+ if respond_to? :on_second_save
255
+ on_second_save @model, request
256
+ end
257
+ if block or respond_to? :on_second_save
227
258
  raise unless @model.save
228
259
  end
229
260
 
230
261
  # Invalidate caches
231
- if respond_to? :action_cache
232
- action_cache.clear
233
- end
262
+ Ramaze::Cache.action.clear
234
263
 
235
264
  flash[:notice] = "Updated #{model_class.to_s.demodulize.downcase} #{h @model.to_s}."
236
265
  redirect @model.url
@@ -238,16 +267,21 @@ module Ramaze
238
267
  rescue => e
239
268
  # An error occurred
240
269
  Ramaze::Log.error e.inspect + e.backtrace.join("\n")
241
- flash[:error] = "Couldn't update #{model_class.to_s.demodulize.downcase} #{h @model.to_s}: #{h e}."
270
+
271
+ if e.is_a? Sequel::ValidationFailed
272
+ flash[:error] = "Couldn't update #{model_class.to_s.demodulize.downcase} #{h @model.to_s}, because there were errors in the form."
273
+ else
274
+ flash[:error] = "Couldn't update #{model_class.to_s.demodulize.downcase} #{h @model.to_s}: #{h e}."
275
+ end
242
276
  end
243
277
  end
244
278
  else
245
279
  flash[:error] = "No such #{model_class.to_s.demodulize.downcase} (#{id}) exists."
246
- redirect Rs()
280
+ redirect rs()
247
281
  end
248
282
  end
249
283
 
250
- def page(page)
284
+ def page(page = nil)
251
285
  page = case page
252
286
  when Symbol
253
287
  page
@@ -261,32 +295,40 @@ module Ramaze
261
295
  page.to_i
262
296
  end
263
297
 
298
+ if page.is_a? Integer and (page < 0 or page > model_class.window_count)
299
+ # This page isn't in the sequence!
300
+ error_404
301
+ end
302
+
264
303
  @title = "#{model_class.to_s.demodulize.pluralize.titleize}"
265
304
  if self.class.private_method_defined? :feed and model_class.respond_to? :atom_url
266
305
  feed @title, model_class.atom_url
267
306
  end
268
- @models = model_class.window(page)
269
- @page = page
270
307
 
271
- if model_class.count.zero?
272
- # There are NO models
273
- elsif @models.empty?
274
- # Empty page
275
- error_404
308
+ @models = model_class.window(page)
309
+ if @models.respond_to? :viewable_by
310
+ @models = @models.viewable_by(user)
276
311
  end
277
312
 
313
+ @page = page
314
+
278
315
  set_plural_model_var @models
279
316
 
280
317
  if user.can_create? model_class.new
281
- workflow "New #{model_class.to_s.demodulize}", Rs(:new)
318
+ workflow "New #{model_class.to_s.demodulize}", rs(:new)
282
319
  end
283
320
 
284
- render_template :list
321
+ render_view(:list)
285
322
  end
286
323
 
287
- def show(id)
324
+ def show(id = nil)
288
325
  if id and @model = model_class.get(id)
289
326
  # Found that model
327
+
328
+ unless user.can_view? @model
329
+ error_403
330
+ end
331
+
290
332
  # Redirect IDs to names
291
333
  raw_redirect(@model.url, :status => 301) if id =~ /^\d+$/
292
334
 
@@ -309,16 +351,14 @@ module Ramaze
309
351
  end
310
352
 
311
353
  if user.can_create? model_class.new
312
- workflow "New #{model_class.to_s.demodulize}", Rs(:new)
354
+ workflow "New #{model_class.to_s.demodulize}", rs(:new)
313
355
  end
314
356
  if user.can_edit? @model
315
- workflow "Edit this #{model_class.to_s.demodulize}", Rs(:edit, @model.id)
357
+ workflow "Edit this #{model_class.to_s.demodulize}", rs(:edit, @model.id)
316
358
  end
317
359
  if user.can_delete? @model
318
- workflow "Delete this #{model_class.to_s.demodulize}", Rs(:delete, @model.id)
360
+ workflow "Delete this #{model_class.to_s.demodulize}", rs(:delete, @model.id)
319
361
  end
320
-
321
- render_template :show
322
362
  elsif id
323
363
  # Didn't find that model
324
364
  error_404
@@ -21,12 +21,9 @@ module Ramaze
21
21
  end
22
22
 
23
23
  # Cache feeds
24
- if base.respond_to? :cache
25
- cache :atom, :ttl => 300
24
+ if base.respond_to? :cache_action
25
+ base.cache_action(:method => :atom, :ttl => 300)
26
26
  end
27
-
28
- # Don't use layout
29
- base.deny_layout :atom
30
27
  end
31
28
  end
32
29
 
@@ -89,7 +89,7 @@ module Ramaze
89
89
 
90
90
  case type
91
91
  when 'textarea'
92
- f << "<textarea name=\"#{id}\" id=\"#{id}\">#{default}</textarea>"
92
+ f << "<textarea name=\"#{id}\" id=\"#{id}\">#{Rack::Utils::escape_html default}</textarea>"
93
93
  when 'checkbox'
94
94
  f << "<input type=\"checkbox\" name=\"#{id}\" id=\"#{id}\" #{default ? 'checked="checked"' : ''} />"
95
95
  else
@@ -162,7 +162,7 @@ module Ramaze
162
162
  case x
163
163
  when CortexReaver::User
164
164
  name = x.name || x.login
165
- A(name, :href => x.url)
165
+ "<a href=\"#{attr_h x.url}\">#{h name}</a>"
166
166
  when CortexReaver::Comment
167
167
  if x.send(who)
168
168
  # Use attached creator/whoever
@@ -6,11 +6,11 @@ module Ramaze
6
6
  begin
7
7
  if exif = photo.exif
8
8
  description = ''
9
- description << photo.date.strftime('%m/%d/%Y') + ': '
10
- description << exif.make if exif.make
9
+ description << photo.date.strftime('%m/%d/%Y') + ' '
10
+ # description << exif.make if exif.make
11
11
  description << ' ' + exif.model + ', ' if exif.model
12
12
  description << ' ' + exif.focal_length_in_35mm_film.to_i.to_s + 'mm' if exif.focal_length_in_35mm_film
13
- description << ' at ' + exposure_time_to_s(exif.exposure_time) if exif.exposure_time
13
+ description << ' at ' + neat_time(exif.exposure_time) if exif.exposure_time
14
14
  description << ' F' + exif.f_number.to_f.to_s if exif.f_number
15
15
  else
16
16
  nil
@@ -20,6 +20,15 @@ module Ramaze
20
20
  return description
21
21
  end
22
22
  end
23
+
24
+ # 1/60 => '1/60th'
25
+ def neat_time(rational)
26
+ if rational.denominator == 1
27
+ rational.numerator.ordinal.to_s
28
+ else
29
+ "#{rational.numerator}/#{rational.denominator.ordinal.to_s}"
30
+ end
31
+ end
23
32
  end
24
33
  end
25
34
  end
@@ -0,0 +1,37 @@
1
+ module Ramaze
2
+ module Helper
3
+ # Simple render_template method
4
+ module Template
5
+ # # HACK: find the template to render
6
+ # def render_template(path)
7
+ # opts = Ramaze::App[:cortex_reaver].options
8
+ #
9
+ # # Construct possible directories
10
+ # roots = opts.roots.map do |root|
11
+ # opts.views.map do |view|
12
+ # root = File.join(root, view)
13
+ #
14
+ # if path[0..0] != '/'
15
+ # # Append controller map as well
16
+ # File.join(root, Ramaze::Current.action.node.mapping)
17
+ # else
18
+ # root
19
+ # end
20
+ # end
21
+ # end
22
+ # roots.flatten!
23
+ #
24
+ # # Try to find the path in each root
25
+ # roots.each do |root|
26
+ # file = File.join(root, path)
27
+ # if File.exists? file
28
+ # return render_file(file)
29
+ # end
30
+ # end
31
+ #
32
+ # # Lookup failed
33
+ # raise RuntimeError.new("No template #{path} in any of #{roots.inspect}")
34
+ # end
35
+ end
36
+ end
37
+ end
@@ -32,7 +32,7 @@
32
32
  <script type="text/javascript" defer="defer" src="/js/admin.js"></script>
33
33
  <script type="text/javascript" src="/js/photo.js"></script>
34
34
 
35
- <%= render_template 'adminbox.rhtml' %>
35
+ <%= CortexReaver::MainController.render_view('adminbox') %>
36
36
 
37
37
  <%= flashbox %>
38
38
 
@@ -59,7 +59,7 @@
59
59
  <tbody>
60
60
  <tr>
61
61
  <td id="main">
62
- <%= render_template "adminbox.rhtml" %>
62
+ <%= CortexReaver::MainController.render_view('adminbox') %>
63
63
 
64
64
  <%= flashbox %>
65
65
 
@@ -0,0 +1,17 @@
1
+ module CortexReaver
2
+ class DraftSchema < Sequel::Migration
3
+ def down
4
+ alter_table(:pages) { drop_column :draft }
5
+ alter_table(:projects) { drop_column :draft }
6
+ alter_table(:journals) { drop_column :draft }
7
+ alter_table(:photographs) { drop_column :draft }
8
+ end
9
+
10
+ def up
11
+ alter_table(:pages) { add_column :draft, :boolean, :default => false }
12
+ alter_table(:projects) { add_column :draft, :boolean, :default => false }
13
+ alter_table(:journals) { add_column :draft, :boolean, :default => false }
14
+ alter_table(:photographs) { add_column :draft, :boolean, :default => false }
15
+ end
16
+ end
17
+ end