sethyates-content_manager 0.4.0 → 1.0.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.
- data/README.rdoc +253 -1
- data/VERSION +1 -1
- data/content_manager.gemspec +38 -2
- data/doc/created.rid +1 -0
- data/doc/files/README_rdoc.html +487 -0
- data/doc/fr_class_index.html +26 -0
- data/doc/fr_file_index.html +27 -0
- data/doc/fr_method_index.html +26 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/generators/component_scaffold/USAGE +28 -0
- data/generators/component_scaffold/component_scaffold_generator.rb +84 -0
- data/generators/component_scaffold/templates/controller.rb +85 -0
- data/generators/component_scaffold/templates/model.rb +5 -0
- data/generators/component_scaffold/templates/style.css +1 -0
- data/generators/component_scaffold/templates/view_edit.html.erb +13 -0
- data/generators/component_scaffold/templates/view_index.html.erb +22 -0
- data/generators/component_scaffold/templates/view_new.html.erb +12 -0
- data/generators/component_scaffold/templates/view_show.html.erb +3 -0
- data/generators/content_scaffold/USAGE +28 -0
- data/generators/content_scaffold/content_scaffold_generator.rb +83 -0
- data/generators/content_scaffold/templates/controller.rb +85 -0
- data/generators/content_scaffold/templates/model.rb +8 -0
- data/generators/content_scaffold/templates/view_edit.html.erb +13 -0
- data/generators/content_scaffold/templates/view_index.html.erb +22 -0
- data/generators/content_scaffold/templates/view_new.html.erb +12 -0
- data/generators/content_scaffold/templates/view_show.html.erb +8 -0
- data/lib/component.rb +28 -0
- data/lib/content/adapters/base.rb +79 -0
- data/lib/content/adapters/cabinet_adapter.rb +62 -0
- data/lib/content/adapters/tyrant_adapter.rb +73 -0
- data/lib/content/item.rb +178 -0
- data/lib/content/item_association_class_methods.rb +148 -0
- data/lib/content/item_class_methods.rb +71 -0
- data/lib/content/item_dirty_methods.rb +171 -0
- data/lib/content/item_finder_class_methods.rb +203 -0
- data/lib/content/manager.rb +105 -0
- data/lib/content/sublayout.rb +44 -0
- data/lib/content/template.rb +24 -0
- metadata +38 -2
@@ -0,0 +1,71 @@
|
|
1
|
+
module Content
|
2
|
+
module ItemClassMethods
|
3
|
+
def establish_connection(options = {})
|
4
|
+
conn_options = ::YAML::load_file('config/content.yml')[::RAILS_ENV]
|
5
|
+
conn_options.merge!(options) unless options.nil?
|
6
|
+
conn_type = conn_options[:type] || conn_options["type"] || :cabinet
|
7
|
+
$adapter = "content/adapters/#{conn_type}_adapter".camelize.constantize.new(conn_options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def connection()
|
11
|
+
$adapter ||= establish_connection
|
12
|
+
end
|
13
|
+
|
14
|
+
def self_and_descendants_from_active_record#nodoc:
|
15
|
+
klass = self
|
16
|
+
classes = [klass]
|
17
|
+
while klass != klass.base_class
|
18
|
+
classes << klass = klass.superclass
|
19
|
+
end
|
20
|
+
classes
|
21
|
+
rescue
|
22
|
+
[self]
|
23
|
+
end
|
24
|
+
|
25
|
+
def human_name(options = {})
|
26
|
+
defaults = self_and_descendants_from_active_record.map do |klass|
|
27
|
+
:"#{klass.name.underscore}"
|
28
|
+
end
|
29
|
+
defaults << name
|
30
|
+
defaults.shift.to_s.humanize
|
31
|
+
end
|
32
|
+
|
33
|
+
def human_attribute_name(attr_name)
|
34
|
+
attr_name.to_s.humanize
|
35
|
+
end
|
36
|
+
|
37
|
+
def create(attributes = nil, &block)
|
38
|
+
if attributes.is_a?(Array)
|
39
|
+
attributes.collect { |attr| create(attr, &block) }
|
40
|
+
else
|
41
|
+
object = new(attributes)
|
42
|
+
yield(object) if block_given?
|
43
|
+
object.save
|
44
|
+
object
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def update(id, attributes)
|
49
|
+
if id.is_a?(Array)
|
50
|
+
idx = -1
|
51
|
+
id.collect { |one_id| idx += 1; update(one_id, attributes[idx]) }
|
52
|
+
else
|
53
|
+
object = find(id)
|
54
|
+
object.update_attributes(attributes)
|
55
|
+
object
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def destroy(id)
|
60
|
+
if id.is_a?(Array)
|
61
|
+
id.map { |one_id| destroy(one_id) }
|
62
|
+
else
|
63
|
+
find(id).destroy
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete(id)
|
68
|
+
destroy id
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module Content
|
2
|
+
# Track unsaved attribute changes.
|
3
|
+
#
|
4
|
+
# A newly instantiated object is unchanged:
|
5
|
+
# person = Person.find_by_name('uncle bob')
|
6
|
+
# person.changed? # => false
|
7
|
+
#
|
8
|
+
# Change the name:
|
9
|
+
# person.name = 'Bob'
|
10
|
+
# person.changed? # => true
|
11
|
+
# person.name_changed? # => true
|
12
|
+
# person.name_was # => 'uncle bob'
|
13
|
+
# person.name_change # => ['uncle bob', 'Bob']
|
14
|
+
# person.name = 'Bill'
|
15
|
+
# person.name_change # => ['uncle bob', 'Bill']
|
16
|
+
#
|
17
|
+
# Save the changes:
|
18
|
+
# person.save
|
19
|
+
# person.changed? # => false
|
20
|
+
# person.name_changed? # => false
|
21
|
+
#
|
22
|
+
# Assigning the same value leaves the attribute unchanged:
|
23
|
+
# person.name = 'Bill'
|
24
|
+
# person.name_changed? # => false
|
25
|
+
# person.name_change # => nil
|
26
|
+
#
|
27
|
+
# Which attributes have changed?
|
28
|
+
# person.name = 'bob'
|
29
|
+
# person.changed # => ['name']
|
30
|
+
# person.changes # => { 'name' => ['Bill', 'bob'] }
|
31
|
+
#
|
32
|
+
# Before modifying an attribute in-place:
|
33
|
+
# person.name_will_change!
|
34
|
+
# person.name << 'by'
|
35
|
+
# person.name_change # => ['uncle bob', 'uncle bobby']
|
36
|
+
module ItemDirtyMethods
|
37
|
+
DIRTY_SUFFIXES = ['_changed?', '_change', '_will_change!', '_was']
|
38
|
+
|
39
|
+
def self.included(base)
|
40
|
+
# base.attribute_method_suffix *DIRTY_SUFFIXES
|
41
|
+
base.alias_method_chain :write_attribute, :dirty
|
42
|
+
base.alias_method_chain :save, :dirty
|
43
|
+
base.alias_method_chain :save!, :dirty
|
44
|
+
base.alias_method_chain :update, :dirty
|
45
|
+
# base.alias_method_chain :reload, :dirty
|
46
|
+
|
47
|
+
base.send(:extend, ClassMethods)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Do any attributes have unsaved changes?
|
51
|
+
# person.changed? # => false
|
52
|
+
# person.name = 'bob'
|
53
|
+
# person.changed? # => true
|
54
|
+
def changed?
|
55
|
+
!changed_attributes.empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
# List of attributes with unsaved changes.
|
59
|
+
# person.changed # => []
|
60
|
+
# person.name = 'bob'
|
61
|
+
# person.changed # => ['name']
|
62
|
+
def changed
|
63
|
+
changed_attributes.keys
|
64
|
+
end
|
65
|
+
|
66
|
+
# Map of changed attrs => [original value, new value].
|
67
|
+
# person.changes # => {}
|
68
|
+
# person.name = 'bob'
|
69
|
+
# person.changes # => { 'name' => ['bill', 'bob'] }
|
70
|
+
def changes
|
71
|
+
changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h }
|
72
|
+
end
|
73
|
+
|
74
|
+
# Attempts to +save+ the record and clears changed attributes if successful.
|
75
|
+
def save_with_dirty(*args) #:nodoc:
|
76
|
+
if status = save_without_dirty(*args)
|
77
|
+
changed_attributes.clear
|
78
|
+
end
|
79
|
+
status
|
80
|
+
end
|
81
|
+
|
82
|
+
# Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
|
83
|
+
def save_with_dirty!(*args) #:nodoc:
|
84
|
+
status = save_without_dirty!(*args)
|
85
|
+
changed_attributes.clear
|
86
|
+
status
|
87
|
+
end
|
88
|
+
|
89
|
+
# <tt>reload</tt> the record and clears changed attributes.
|
90
|
+
def reload_with_dirty(*args) #:nodoc:
|
91
|
+
record = reload_without_dirty(*args)
|
92
|
+
changed_attributes.clear
|
93
|
+
record
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
# Map of change <tt>attr => original value</tt>.
|
98
|
+
def changed_attributes
|
99
|
+
@changed_attributes ||= {}
|
100
|
+
end
|
101
|
+
|
102
|
+
# Handle <tt>*_changed?</tt> for +method_missing+.
|
103
|
+
def attribute_changed?(attr)
|
104
|
+
changed_attributes.include?(attr)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Handle <tt>*_change</tt> for +method_missing+.
|
108
|
+
def attribute_change(attr)
|
109
|
+
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Handle <tt>*_was</tt> for +method_missing+.
|
113
|
+
def attribute_was(attr)
|
114
|
+
attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Handle <tt>*_will_change!</tt> for +method_missing+.
|
118
|
+
def attribute_will_change!(attr)
|
119
|
+
changed_attributes[attr] = clone_attribute_value(:read_attribute, attr)
|
120
|
+
end
|
121
|
+
|
122
|
+
def clone_attribute_value(method, attr)
|
123
|
+
val = __send__(method, attr)
|
124
|
+
val.dup unless val.nil?
|
125
|
+
end
|
126
|
+
|
127
|
+
# Wrap write_attribute to remember original attribute value.
|
128
|
+
def write_attribute_with_dirty(attr, value)
|
129
|
+
# The attribute already has an unsaved change.
|
130
|
+
if changed_attributes.include?(attr)
|
131
|
+
old = changed_attributes[attr]
|
132
|
+
changed_attributes.delete(attr) unless field_changed?(attr, old, value)
|
133
|
+
else
|
134
|
+
old = clone_attribute_value(:read_attribute, attr)
|
135
|
+
changed_attributes[attr] = old if field_changed?(attr, old, value)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Carry on.
|
139
|
+
write_attribute_without_dirty(attr, value)
|
140
|
+
end
|
141
|
+
|
142
|
+
def update_with_dirty
|
143
|
+
if partial_updates?
|
144
|
+
# Serialized attributes should always be written in case they've been
|
145
|
+
# changed in place.
|
146
|
+
update_without_dirty(changed | self.class.serialized_attributes.keys)
|
147
|
+
else
|
148
|
+
update_without_dirty
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def field_changed?(attr, old, value)
|
153
|
+
old != value
|
154
|
+
end
|
155
|
+
|
156
|
+
module ClassMethods
|
157
|
+
def self.extended(base)
|
158
|
+
base.metaclass.alias_method_chain(:alias_attribute, :dirty)
|
159
|
+
end
|
160
|
+
|
161
|
+
def alias_attribute_with_dirty(new_name, old_name)
|
162
|
+
alias_attribute_without_dirty(new_name, old_name)
|
163
|
+
DIRTY_SUFFIXES.each do |suffix|
|
164
|
+
module_eval <<-STR, __FILE__, __LINE__+1
|
165
|
+
def #{new_name}#{suffix}; self.#{old_name}#{suffix}; end # def subject_changed?; self.title_changed?; end
|
166
|
+
STR
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module Content
|
2
|
+
module ItemFinderClassMethods
|
3
|
+
# Find operates with four different retrieval approaches:
|
4
|
+
#
|
5
|
+
# * Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]).
|
6
|
+
# If no record can be found for all of the listed ids, then RecordNotFound will be raised.
|
7
|
+
# * Find first - This will return the first record matched by the options used. These options can either be specific
|
8
|
+
# conditions or merely an order. If no record can be matched, +nil+ is returned. Use
|
9
|
+
# <tt>Model.find(:first, *args)</tt> or its shortcut <tt>Model.first(*args)</tt>.
|
10
|
+
# * Find last - This will return the last record matched by the options used. These options can either be specific
|
11
|
+
# conditions or merely an order. If no record can be matched, +nil+ is returned. Use
|
12
|
+
# <tt>Model.find(:last, *args)</tt> or its shortcut <tt>Model.last(*args)</tt>.
|
13
|
+
# * Find all - This will return all the records matched by the options used.
|
14
|
+
# If no records are found, an empty array is returned. Use
|
15
|
+
# <tt>Model.find(:all, *args)</tt> or its shortcut <tt>Model.all(*args)</tt>.
|
16
|
+
#
|
17
|
+
# All approaches accept an options hash as their last parameter.
|
18
|
+
#
|
19
|
+
# ==== Parameters
|
20
|
+
#
|
21
|
+
# * <tt>:conditions</tt> - An SQL fragment like "administrator = 1", <tt>[ "user_name = ?", username ]</tt>, or <tt>["user_name = :user_name", { :user_name => user_name }]</tt>. See conditions in the intro.
|
22
|
+
# * <tt>:order</tt> - An SQL fragment like "created_at DESC, name".
|
23
|
+
# * <tt>:limit</tt> - An integer determining the limit on the number of rows that should be returned.
|
24
|
+
# * <tt>:offset</tt> - An integer determining the offset from where the rows should be fetched. So at 5, it would skip rows 0 through 4.
|
25
|
+
# * <tt>:select</tt> - By default, this is "*" as in "SELECT * FROM", but can be changed if you, for example, want to do a join but not
|
26
|
+
# include the joined columns. Takes a string with the SELECT SQL fragment (e.g. "id, name").
|
27
|
+
#
|
28
|
+
# ==== Examples
|
29
|
+
#
|
30
|
+
# # find by id
|
31
|
+
# Person.find(1) # returns the object for ID = 1
|
32
|
+
# Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6)
|
33
|
+
# Person.find([7, 17]) # returns an array for objects with IDs in (7, 17)
|
34
|
+
# Person.find([1]) # returns an array for the object with ID = 1
|
35
|
+
# Person.find(1, :conditions => "administrator = 1", :order => "created_on DESC")
|
36
|
+
#
|
37
|
+
# Note that returned records may not be in the same order as the ids you
|
38
|
+
# provide since database rows are unordered. Give an explicit <tt>:order</tt>
|
39
|
+
# to ensure the results are sorted.
|
40
|
+
#
|
41
|
+
# ==== Examples
|
42
|
+
#
|
43
|
+
# # find first
|
44
|
+
# Person.find(:first) # returns the first object fetched by SELECT * FROM people
|
45
|
+
# Person.find(:first, :conditions => [ "user_name = ?", user_name])
|
46
|
+
# Person.find(:first, :conditions => [ "user_name = :u", { :u => user_name }])
|
47
|
+
# Person.find(:first, :order => "created_on DESC", :offset => 5)
|
48
|
+
#
|
49
|
+
# # find last
|
50
|
+
# Person.find(:last) # returns the last object fetched by SELECT * FROM people
|
51
|
+
# Person.find(:last, :conditions => [ "user_name = ?", user_name])
|
52
|
+
# Person.find(:last, :order => "created_on DESC", :offset => 5)
|
53
|
+
#
|
54
|
+
# # find all
|
55
|
+
# Person.find(:all) # returns an array of objects for all the rows fetched by SELECT * FROM people
|
56
|
+
# Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50)
|
57
|
+
# Person.find(:all, :conditions => { :friends => ["Bob", "Steve", "Fred"] }
|
58
|
+
# Person.find(:all, :offset => 10, :limit => 10)
|
59
|
+
# Person.find(:all, :include => [ :account, :friends ])
|
60
|
+
# Person.find(:all, :group => "category")
|
61
|
+
#
|
62
|
+
def find(*args)
|
63
|
+
options = {}
|
64
|
+
which = args.shift
|
65
|
+
if which.is_a? Symbol
|
66
|
+
given_options = args.shift
|
67
|
+
options.merge!(given_options) unless given_options.nil?
|
68
|
+
else
|
69
|
+
id = which
|
70
|
+
which = :first
|
71
|
+
given_options = args.shift
|
72
|
+
options.merge!(given_options) unless given_options.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
options[:limit] = 1 if which == :first
|
76
|
+
|
77
|
+
if id.nil?
|
78
|
+
wrap_result which, connection.run_query(self, options)
|
79
|
+
elsif id.is_a? Array
|
80
|
+
id.collect {|one_id| find_by_id one_id}.compact
|
81
|
+
elsif options.keys.length == 0
|
82
|
+
find_by_id id
|
83
|
+
else
|
84
|
+
if options.has_key? :conditions
|
85
|
+
options[:conditions].merge!(:__id => id)
|
86
|
+
else
|
87
|
+
options[:conditions] = {:__id => id}
|
88
|
+
end
|
89
|
+
wrap_result which, connection.run_query(self, options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def count(options)
|
94
|
+
connection.count(self, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
def paginate(*args)
|
98
|
+
options = args.first.dup
|
99
|
+
options[:conditions] = (options[:conditions] || {}).merge(:content_type => name)
|
100
|
+
options[:limit] = (options[:per_page] || 25)
|
101
|
+
options[:offset] = ((options[:page] || 1) - 1) * options[:limit]
|
102
|
+
options.delete :page
|
103
|
+
options.delete :per_page
|
104
|
+
find(:all, options)
|
105
|
+
end
|
106
|
+
|
107
|
+
def find_by_id(id)
|
108
|
+
wrap_result :first, connection.get_record_by_id(self, id.to_i)
|
109
|
+
end
|
110
|
+
|
111
|
+
def find_each(options)
|
112
|
+
#TODO - run the query
|
113
|
+
if block_given?
|
114
|
+
#each ... yield(row)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def all
|
119
|
+
if name == "Content::Item"
|
120
|
+
find :all
|
121
|
+
else
|
122
|
+
find_all_by_content_type name
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def first
|
127
|
+
if name == "Content::Item"
|
128
|
+
find :first
|
129
|
+
else
|
130
|
+
find_by_content_type name
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def last
|
135
|
+
all.last
|
136
|
+
end
|
137
|
+
|
138
|
+
def method_missing(name, *arguments, &block)
|
139
|
+
name_s = name.to_s
|
140
|
+
if name_s =~ /^find_all(_by)?_(.+)$/
|
141
|
+
obj = polymorphic_finder :all, $2, arguments
|
142
|
+
elsif name_s =~ /^find_by_(.+)$/
|
143
|
+
obj = polymorphic_finder :first, $1, arguments
|
144
|
+
elsif name_s =~ /^find_last(_by)?_(.+)$/
|
145
|
+
obj = polymorphic_finder :last, $2, arguments
|
146
|
+
elsif name_s =~ /^find_or_create_by_(.+)$/
|
147
|
+
obj = polymorphic_finder :first, $1, arguments
|
148
|
+
if obj.nil?
|
149
|
+
self.create(arguments, &block)
|
150
|
+
end
|
151
|
+
elsif name_s =~ /^paginate_by_(.+)$/
|
152
|
+
obj = polymorphic_pager $1, arguments
|
153
|
+
else
|
154
|
+
obj = super
|
155
|
+
end
|
156
|
+
yield(obj) if !obj.nil? and block_given?
|
157
|
+
obj
|
158
|
+
end
|
159
|
+
|
160
|
+
protected
|
161
|
+
def hash_zip(keys, values, default=nil, &block)
|
162
|
+
hash = block_given? ? Hash.new(&block) : Hash.new(default)
|
163
|
+
keys.zip(values) { |k,v| hash[k]=v }
|
164
|
+
hash
|
165
|
+
end
|
166
|
+
|
167
|
+
def polymorphic_finder(which, name, arguments)
|
168
|
+
find which, :conditions => hash_zip(name.split(/_and_/), arguments)
|
169
|
+
end
|
170
|
+
|
171
|
+
def polymorphic_pager(name, arguments)
|
172
|
+
names = name.split(/_and_/)
|
173
|
+
options = arguments.length > names.length ? arguments.last : {}
|
174
|
+
if options.has_key? :conditions
|
175
|
+
options[:conditions].merge! hash_zip(names, arguments)
|
176
|
+
else
|
177
|
+
options.merge!({:conditions => hash_zip(names, arguments)})
|
178
|
+
end
|
179
|
+
paginate options
|
180
|
+
end
|
181
|
+
|
182
|
+
def create_item(attrs)
|
183
|
+
if attrs.nil?
|
184
|
+
nil
|
185
|
+
elsif !attrs[:content_type].nil?
|
186
|
+
attrs[:content_type].to_s.camelize.constantize.new(attrs)
|
187
|
+
elsif self == Content::Item
|
188
|
+
Content::Item.new(attrs)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def wrap_result(which, attrs)
|
193
|
+
unless attrs.nil?
|
194
|
+
attrs = [attrs] unless attrs.is_a?(Array)
|
195
|
+
case which
|
196
|
+
when :first then create_item attrs.first
|
197
|
+
when :last then create_item attrs.last
|
198
|
+
else attrs.collect { |item| create_item(item) }.compact
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Content
|
2
|
+
module Manager
|
3
|
+
def self.load_content_item(params)
|
4
|
+
url = params["content_item_url"]
|
5
|
+
unless url.nil?
|
6
|
+
if url.is_a? Array
|
7
|
+
url = "/#{url.join('/')}"
|
8
|
+
end
|
9
|
+
if url.match(/^(.+)\.([a-z]+)$/i)
|
10
|
+
params[:format] = $2
|
11
|
+
url = $1
|
12
|
+
end
|
13
|
+
params["content_item_url"] = url
|
14
|
+
Content::Item.find_by_url(url)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def show
|
19
|
+
render404 and return if current_content_item.nil? or current_content_item.template.nil? or current_content_item.template.sublayout.nil?
|
20
|
+
respond_to do |format|
|
21
|
+
format.html { prerender_containers and render :template => "sublayouts/#{current_content_item.template.sublayout}", :layout => false }
|
22
|
+
format.xml { render :xml => current_content_item }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
def prerender_containers
|
28
|
+
begin
|
29
|
+
sublayout = Content::Sublayout.find_by_path(current_content_item.template.sublayout)
|
30
|
+
sublayout.containers.each {|name| content_for name, render_container(name) }
|
31
|
+
rescue RuntimeError => err
|
32
|
+
render500(err) and return false
|
33
|
+
end
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def content_for(name, content)
|
38
|
+
name = "layout" if name.to_s == "contents"
|
39
|
+
ivar = "@content_for_#{name}"
|
40
|
+
instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}")
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Renders the given component
|
45
|
+
#
|
46
|
+
# url_options the options that would be passed to url_for
|
47
|
+
#
|
48
|
+
def render_component(url_options)
|
49
|
+
url = url_for(url_options)
|
50
|
+
querystring = URI.parse(url).query
|
51
|
+
|
52
|
+
env = {
|
53
|
+
"rack.version" => [0, 1],
|
54
|
+
"rack.input" => StringIO.new(""),
|
55
|
+
"rack.errors" => $stderr,
|
56
|
+
"rack.url_scheme" => "http",
|
57
|
+
"rack.run_once" => false,
|
58
|
+
"rack.multithread" => false,
|
59
|
+
"rack.multiprocess" => false,
|
60
|
+
"QUERY_STRING" => querystring,
|
61
|
+
"REQUEST_METHOD" => "GET",
|
62
|
+
"PATH_INFO" => url,
|
63
|
+
"REQUEST_PATH" => url,
|
64
|
+
"REQUEST_URI" => url
|
65
|
+
}
|
66
|
+
|
67
|
+
%w(SERVER_SOFTWARE HTTP_USER_AGENT HTTP_ACCEPT_ENCODING HTTP_ACCEPT_CHARSET
|
68
|
+
HTTP_ACCEPT_LANGUAGE HTTP_KEEP_ALIVE HTTP_COOKIE HTTP_VERSION SERVER_PROTOCOL HTTP_HOST
|
69
|
+
SERVER_NAME SERVER_PORT REMOTE_ADDR SCRIPT_NAME).each { |key| env[key] = request.env[key] }
|
70
|
+
|
71
|
+
resp = ActionController::Routing::Routes.call(env)
|
72
|
+
raise resp[2].body unless resp[0] == 200
|
73
|
+
resp[2].body
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Renders a container
|
78
|
+
#
|
79
|
+
# name the name of the container to render
|
80
|
+
#
|
81
|
+
def render_container(name)
|
82
|
+
unless current_content_item.nil? or current_content_item.template.nil? or current_content_item.template[name].nil?
|
83
|
+
current_content_item.template.get_container(name).collect {|component|
|
84
|
+
render_component(:controller => "components/#{component.keys.first.to_s.pluralize}", :action => "show", :id => component.values.first)
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def render404
|
90
|
+
respond_to do |format|
|
91
|
+
format.html { render :template => "errors/error_404", :status => 404 }
|
92
|
+
format.all { render :nothing => true, :status => 404 }
|
93
|
+
end
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
def render500(err)
|
98
|
+
respond_to do |format|
|
99
|
+
format.html { render :text => err, :layout => false, :status => 500 }
|
100
|
+
format.all { render :nothing => true, :status => 500 }
|
101
|
+
end
|
102
|
+
true
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|