cortex-reaver 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cortex_reaver +7 -2
- data/lib/cortex_reaver.rb +51 -71
- data/lib/cortex_reaver/config.rb +23 -7
- data/lib/cortex_reaver/controller/admin.rb +6 -8
- data/lib/cortex_reaver/controller/comment.rb +17 -17
- data/lib/cortex_reaver/controller/config.rb +3 -2
- data/lib/cortex_reaver/controller/controller.rb +22 -0
- data/lib/cortex_reaver/controller/documentation.rb +1 -3
- data/lib/cortex_reaver/controller/journal.rb +13 -12
- data/lib/cortex_reaver/controller/main.rb +36 -29
- data/lib/cortex_reaver/controller/page.rb +15 -11
- data/lib/cortex_reaver/controller/photograph.rb +21 -15
- data/lib/cortex_reaver/controller/project.rb +16 -13
- data/lib/cortex_reaver/controller/tag.rb +16 -14
- data/lib/cortex_reaver/controller/user.rb +11 -13
- data/lib/cortex_reaver/helper/attachments.rb +18 -12
- data/lib/cortex_reaver/helper/auth.rb +2 -2
- data/lib/cortex_reaver/helper/canonical.rb +2 -2
- data/lib/cortex_reaver/helper/crud.rb +78 -38
- data/lib/cortex_reaver/helper/feeds.rb +2 -5
- data/lib/cortex_reaver/helper/form.rb +1 -1
- data/lib/cortex_reaver/helper/navigation.rb +1 -1
- data/lib/cortex_reaver/helper/photographs.rb +12 -3
- data/lib/cortex_reaver/helper/template.rb +37 -0
- data/lib/cortex_reaver/{view/blank_layout.rhtml → layout/blank.rhtml} +1 -1
- data/lib/cortex_reaver/{view/text_layout.rhtml → layout/text.rhtml} +1 -1
- data/lib/cortex_reaver/migrations/013_draft.rb +17 -0
- data/lib/cortex_reaver/model/comment.rb +64 -53
- data/lib/cortex_reaver/model/journal.rb +23 -21
- data/lib/cortex_reaver/model/model.rb +9 -0
- data/lib/cortex_reaver/model/page.rb +24 -42
- data/lib/cortex_reaver/model/photograph.rb +17 -17
- data/lib/cortex_reaver/model/project.rb +21 -18
- data/lib/cortex_reaver/model/tag.rb +12 -8
- data/lib/cortex_reaver/model/user.rb +79 -41
- data/lib/cortex_reaver/public/css/main.css +4 -0
- data/lib/cortex_reaver/snippets/numeric.rb +15 -0
- data/lib/cortex_reaver/snippets/ramaze/cache/memcached.rb +14 -0
- data/lib/cortex_reaver/support/attachments.rb +113 -105
- data/lib/cortex_reaver/support/cached_rendering.rb +65 -62
- data/lib/cortex_reaver/support/canonical.rb +82 -85
- data/lib/cortex_reaver/support/comments.rb +57 -51
- data/lib/cortex_reaver/support/cortex_reaver_validation_helpers.rb +13 -0
- data/lib/cortex_reaver/support/sequenceable.rb +202 -203
- data/lib/cortex_reaver/support/tags.rb +103 -94
- data/lib/cortex_reaver/support/timestamps.rb +27 -21
- data/lib/cortex_reaver/support/viewable.rb +17 -0
- data/lib/cortex_reaver/version.rb +3 -3
- data/lib/cortex_reaver/view/admin/index.rhtml +2 -2
- data/lib/cortex_reaver/view/comments/comment.rhtml +4 -1
- data/lib/cortex_reaver/view/comments/list.rhtml +1 -1
- data/lib/cortex_reaver/view/comments/post_form.rhtml +1 -1
- data/lib/cortex_reaver/view/journals/form.rhtml +3 -1
- data/lib/cortex_reaver/view/journals/journal.rhtml +6 -4
- data/lib/cortex_reaver/view/journals/list.rhtml +2 -2
- data/lib/cortex_reaver/view/journals/show.rhtml +1 -1
- data/lib/cortex_reaver/view/pages/form.rhtml +2 -1
- data/lib/cortex_reaver/view/pages/list.rhtml +2 -2
- data/lib/cortex_reaver/view/pages/show.rhtml +1 -1
- data/lib/cortex_reaver/view/photographs/form.rhtml +7 -3
- data/lib/cortex_reaver/view/photographs/list.rhtml +1 -1
- data/lib/cortex_reaver/view/photographs/show.rhtml +7 -7
- data/lib/cortex_reaver/view/projects/form.rhtml +1 -0
- data/lib/cortex_reaver/view/projects/list.rhtml +3 -3
- data/lib/cortex_reaver/view/projects/show.rhtml +5 -2
- data/lib/cortex_reaver/view/tags/list.rhtml +6 -2
- data/lib/cortex_reaver/view/tags/show.rhtml +10 -5
- data/lib/cortex_reaver/view/users/form.rhtml +1 -1
- data/lib/cortex_reaver/view/users/list.rhtml +5 -2
- data/lib/cortex_reaver/view/users/login.rhtml +1 -1
- data/lib/cortex_reaver/view/users/show.rhtml +5 -1
- metadata +159 -149
- data/lib/cortex_reaver/public/dispatch.fcgi +0 -11
- data/lib/cortex_reaver/snippets/ramaze/dispatcher/file.rb +0 -37
- data/lib/cortex_reaver/support/pagination.rb +0 -38
- data/lib/cortex_reaver/view/error.rhtml +0 -72
- data/lib/cortex_reaver/view/photographs/short.rhtml +0 -3
@@ -1,78 +1,81 @@
|
|
1
|
-
|
2
|
-
module Model
|
1
|
+
require 'ostruct'
|
3
2
|
|
3
|
+
module Sequel
|
4
|
+
module Plugins
|
4
5
|
# On save, calls a special rendering method on configured attributes, and
|
5
6
|
# saves the results to their cache.
|
6
7
|
module CachedRendering
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
fields = render_fields.select do |k, v|
|
20
|
-
changed.include? k.to_sym
|
21
|
-
end
|
22
|
-
|
23
|
-
fields.each do |name, field|
|
24
|
-
# Render and cache
|
25
|
-
self[field.to] = self.send(field.with, self[name])
|
8
|
+
module ClassMethods
|
9
|
+
# Refreshes all records with cached fields.
|
10
|
+
def refresh_render_caches
|
11
|
+
# TODO: inefficient, but Model.each breaks Sequel in validation
|
12
|
+
# "commands out of sync"
|
13
|
+
all.each do |record|
|
14
|
+
# Mark all caching columns as changed, so the before_save hook
|
15
|
+
# processes them.
|
16
|
+
record.skip_timestamp_update = true
|
17
|
+
render_fields.keys.each do |column|
|
18
|
+
record.changed_columns << column
|
26
19
|
end
|
20
|
+
record.save
|
27
21
|
end
|
22
|
+
nil
|
23
|
+
end
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
25
|
+
# Assigns a field to cache
|
26
|
+
#
|
27
|
+
# render :body, :with => 'wikify', :to => 'cached_body'
|
28
|
+
#
|
29
|
+
# ... calls #wikify on the value of self.body, and stores the result
|
30
|
+
# in self.cached_body. :to defaults to the field name with _cache
|
31
|
+
# appended. :with defaults to :render.
|
32
|
+
def render(field, params = {})
|
33
|
+
# Assign parameters
|
34
|
+
params = {
|
35
|
+
:to => (field.to_s + '_cache').to_sym,
|
36
|
+
:with => :render
|
37
|
+
}.merge!(params)
|
38
|
+
|
39
|
+
# Store field
|
40
|
+
render_fields[field] = OpenStruct.new(params)
|
41
|
+
end
|
44
42
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
params = {
|
55
|
-
:to => (field.to_s + '_cache').to_sym,
|
56
|
-
:with => :render
|
57
|
-
}.merge!(params)
|
58
|
-
|
59
|
-
# Store field
|
60
|
-
render_fields[field] = OpenStruct.new(params)
|
61
|
-
end
|
43
|
+
def render_fields
|
44
|
+
@render_fields ||= {}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module InstanceMethods
|
49
|
+
# Before save, render all changed caching fields
|
50
|
+
def before_save
|
51
|
+
return false if super == false
|
62
52
|
|
63
|
-
|
64
|
-
|
53
|
+
# Get changed fields to render
|
54
|
+
if new?
|
55
|
+
changed = columns.map { |c| c.to_sym }
|
56
|
+
else
|
57
|
+
changed = changed_columns.map { |c| c.to_sym }
|
58
|
+
end
|
59
|
+
fields = render_fields.select do |k, v|
|
60
|
+
changed.include? k.to_sym
|
65
61
|
end
|
62
|
+
|
63
|
+
fields.each do |name, field|
|
64
|
+
# Render and cache
|
65
|
+
self[field.to] = self.send(field.with, self[name])
|
66
|
+
end
|
67
|
+
|
68
|
+
true
|
66
69
|
end
|
67
|
-
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
# Default renderer
|
72
|
+
def render(value)
|
73
|
+
value
|
74
|
+
end
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
+
def render_fields
|
77
|
+
self.class.render_fields
|
78
|
+
end
|
76
79
|
end
|
77
80
|
end
|
78
81
|
end
|
@@ -1,110 +1,107 @@
|
|
1
|
-
module
|
2
|
-
module
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
3
|
# Supports canonical, url-safe identifiers for records, inferred from other
|
4
4
|
# fields.
|
5
5
|
module Canonical
|
6
|
+
module ClassMethods
|
7
|
+
# The canonical name attribute
|
8
|
+
CANONICAL_NAME_ATTR = :name
|
9
|
+
# The attribute we infer the canonical name from, if not set.
|
10
|
+
CANONICAL_INFERENCE_ATTR = :title
|
6
11
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
12
|
+
# Canonical names which cannot be reserved.
|
13
|
+
def reserved_canonical_names
|
14
|
+
@reserved_canonical_names ||= []
|
15
|
+
end
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
17
|
+
def reserved_canonical_names=(names)
|
18
|
+
@reserved_canonical_names = names
|
19
|
+
end
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
21
|
+
# Canonicalize a string. Optionally, ignore conflicts with the record
|
22
|
+
# with opts[:id]
|
23
|
+
def canonicalize(string, opts={})
|
24
|
+
# Lower case, remove special chars, and replace with hyphens.
|
25
|
+
proper = formalize string
|
23
26
|
|
24
|
-
|
25
|
-
|
27
|
+
# If proper is blank, just return it at this point.
|
28
|
+
if proper.blank?
|
29
|
+
return proper
|
26
30
|
end
|
27
31
|
|
28
|
-
#
|
29
|
-
|
30
|
-
def self.canonicalize(string, opts={})
|
31
|
-
# Lower case, remove special chars, and replace with hyphens.
|
32
|
-
proper = Canonical.formalize string
|
33
|
-
|
34
|
-
# If proper is blank, just return it at this point.
|
35
|
-
if proper.blank?
|
36
|
-
return proper
|
37
|
-
end
|
38
|
-
|
39
|
-
# Numeric suffix to append
|
40
|
-
suffix = nil
|
32
|
+
# Numeric suffix to append
|
33
|
+
suffix = nil
|
41
34
|
|
42
|
-
|
43
|
-
|
35
|
+
# Get similar names from the class
|
36
|
+
similar = similar_canonical_names(proper, opts)
|
44
37
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
38
|
+
# Get reserved names from the class
|
39
|
+
reserved_canonical_names.each do |name|
|
40
|
+
if name =~ /^#{proper}(-\d+)?$/
|
41
|
+
similar << name
|
50
42
|
end
|
43
|
+
end
|
51
44
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
# Extract numeric suffices
|
46
|
+
suffices = {}
|
47
|
+
similar.each do |name|
|
48
|
+
suffices[name[/\d$/].to_i] = true
|
49
|
+
end
|
57
50
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
suffix = i
|
65
|
-
end
|
66
|
-
|
67
|
-
# Apply suffix
|
68
|
-
if suffix
|
69
|
-
proper + '-' + suffix.to_s
|
70
|
-
else
|
71
|
-
proper
|
51
|
+
# Compute suffix
|
52
|
+
unless suffices.empty?
|
53
|
+
i = 1
|
54
|
+
while suffices.include? i
|
55
|
+
i += 1
|
72
56
|
end
|
57
|
+
suffix = i
|
58
|
+
end
|
59
|
+
|
60
|
+
# Apply suffix
|
61
|
+
if suffix
|
62
|
+
proper + '-' + suffix.to_s
|
63
|
+
else
|
64
|
+
proper
|
73
65
|
end
|
66
|
+
end
|
74
67
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
68
|
+
# Sets the attribute we infer the canonical name from to attr, or
|
69
|
+
# gets that attr if nil.
|
70
|
+
def canonical_inference_attr(attr = nil)
|
71
|
+
if attr
|
72
|
+
@canonical_inference_attr = attr.to_sym
|
73
|
+
else
|
74
|
+
@canonical_inference_attr || CANONICAL_INFERENCE_ATTR
|
83
75
|
end
|
76
|
+
end
|
84
77
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
78
|
+
# Sets the canonical name attribute to attr. Returns it if nil.
|
79
|
+
def canonical_name_attr(attr = nil)
|
80
|
+
if attr
|
81
|
+
@canonical_name_attr = attr.to_sym
|
82
|
+
else
|
83
|
+
@canonical_name_attr || CANONICAL_NAME_ATTR
|
92
84
|
end
|
85
|
+
end
|
93
86
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
def self.similar_canonical_names(proper, opts={})
|
98
|
-
id = opts[:id]
|
99
|
-
similar = []
|
100
|
-
if filter(canonical_name_attr => proper).exclude(:id => id).limit(1).count > 0
|
101
|
-
# This name already exists, and it's not ours.
|
102
|
-
similar << proper
|
103
|
-
similar += filter(canonical_name_attr.like(/^#{proper}\-[0-9]+$/)).map(canonical_name_attr)
|
104
|
-
end
|
105
|
-
similar
|
106
|
-
end
|
87
|
+
# Lower case, remove special chars, and replace with hyphens.
|
88
|
+
def formalize(string)
|
89
|
+
string.downcase.gsub(/'"/, '').gsub(/[^a-z0-9_]/, '-').squeeze('-')[0..250].sub(/-$/, '')
|
107
90
|
end
|
91
|
+
|
92
|
+
# Canonicalize only in the context of our parent's namespace. Takes a
|
93
|
+
# proper canonical name to check for conflicts with, and an optional id
|
94
|
+
# to ignore conflicts with
|
95
|
+
def similar_canonical_names(proper, opts={})
|
96
|
+
id = opts[:id]
|
97
|
+
similar = []
|
98
|
+
if filter(canonical_name_attr => proper).exclude(:id => id).limit(1).count > 0
|
99
|
+
# This name already exists, and it's not ours.
|
100
|
+
similar << proper
|
101
|
+
similar += filter(canonical_name_attr.like(/^#{proper}\-[0-9]+$/)).map(canonical_name_attr)
|
102
|
+
end
|
103
|
+
similar
|
104
|
+
end
|
108
105
|
end
|
109
106
|
end
|
110
107
|
end
|
@@ -1,67 +1,73 @@
|
|
1
|
-
module
|
2
|
-
module
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
3
|
# Support methods for comments on models
|
4
4
|
module Comments
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
remove_all_comments
|
11
|
-
comments.each do |comment|
|
12
|
-
comment.destroy
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Refresh all comment counts
|
17
|
-
def self.refresh_comment_counts
|
18
|
-
all.each do |model|
|
19
|
-
model.refresh_comment_count
|
20
|
-
end
|
5
|
+
module ClassMethods
|
6
|
+
# Refresh all comment counts
|
7
|
+
def refresh_comment_counts
|
8
|
+
all.each do |model|
|
9
|
+
model.refresh_comment_count
|
21
10
|
end
|
22
11
|
end
|
23
12
|
end
|
24
13
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
14
|
+
module InstanceMethods
|
15
|
+
# When we delete a model that has comments, remove the comments too.
|
16
|
+
def before_destroy
|
17
|
+
Ramaze::Log.debug 'remove_comments'
|
18
|
+
return false if super == false
|
19
|
+
Ramaze::Log.debug 'removing comments'
|
20
|
+
|
21
|
+
comments = self.comments
|
22
|
+
remove_all_comments
|
23
|
+
comments.each do |comment|
|
24
|
+
comment.destroy
|
25
|
+
end
|
26
|
+
|
27
|
+
true
|
33
28
|
end
|
34
|
-
self[:comment_count] = count
|
35
|
-
self.skip_timestamp_update = true
|
36
29
|
|
37
|
-
#
|
38
|
-
|
39
|
-
|
40
|
-
|
30
|
+
# Recalculates the number of comments on this record (and all comments
|
31
|
+
# below it, recursively) and saves those values. Returns the comment
|
32
|
+
# count on this record.
|
33
|
+
def refresh_comment_count
|
34
|
+
count = 0
|
35
|
+
comments.each do |comment|
|
36
|
+
# Recalculate for sub-comments and sum.
|
37
|
+
count += comment.refresh_comment_count + 1
|
38
|
+
end
|
39
|
+
self[:comment_count] = count
|
40
|
+
self.skip_timestamp_update = true
|
41
|
+
|
42
|
+
# Save and return
|
43
|
+
self.save
|
44
|
+
self[:comment_count]
|
45
|
+
end
|
41
46
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
# Returns the parent of a given comment. Caches, pass true to refresh.
|
48
|
+
def parent(refresh = false)
|
49
|
+
if refresh or @parent_cache.nil?
|
50
|
+
[:comment, :journal, :photograph, :project, :page].each do |p|
|
51
|
+
if self.respond_to?(p) and parent = self.send(p)
|
52
|
+
# We found an applicable parent.
|
53
|
+
@parent_cache = parent
|
54
|
+
return parent
|
55
|
+
end
|
50
56
|
end
|
57
|
+
# We didn't find any parent
|
58
|
+
nil
|
59
|
+
else
|
60
|
+
@parent_cache
|
51
61
|
end
|
52
|
-
# We didn't find any parent
|
53
|
-
nil
|
54
|
-
else
|
55
|
-
@parent_cache
|
56
62
|
end
|
57
|
-
end
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
# Returns the top-level parent of a given comment.
|
65
|
+
def root_parent
|
66
|
+
if parent
|
67
|
+
parent.root_parent
|
68
|
+
else
|
69
|
+
self
|
70
|
+
end
|
65
71
|
end
|
66
72
|
end
|
67
73
|
end
|