-
Notifications
You must be signed in to change notification settings - Fork 41
/
content_node_extension.rb
148 lines (118 loc) · 5 KB
/
content_node_extension.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Copyright (C) 2009 Pascal Rettig.
module ModelExtension::ContentNodeExtension
module ClassMethods
# See ContentNode for an overview of the content node system
# and how to use this method
#
# Options:
#
# [:skip_has_one]
# Skips the polymorphic has_one relationship with content_node
# [:except]
# symbol or proc the is resolved to determine whether or not to create a content node
# [:container_type]
# string representing the class that is the ContentType container for this class
# [:container_field]
# symbol with the name of the attribute that is the belong_to foreign key for the container
# [:push_value]
# set to true to immediately push the content node value - should only be done for admin only content models
def content_node(options = {})
attr_accessor :content_node_skip
after_save :content_node_save
if !options[:skip_has_one]
has_one :content_node, :as => :node, :dependent => :destroy
end
self.send(:include, ModelExtension::ContentNodeExtension::InstanceMethods)
define_method(:content_node_options) do
options
end
end
# See ContentType for an overview of content types.
#
# content_node_type will add any entry to the ContentType table every time
# a new object of this class is created.
#
# content_type is a string representing the class to create content nodes
# e.g. you could call content_type on a BookBook with a content_type of BookPage
#
# Options:
#
# [:except]
# symbol or proc that is resolved to determine whether or not to create a content type
# [:title_field]
# field that represents the title of the content node (deafults to name)
# [:url_field]
# field that represents the url of the content node (deafults to id)
# [:content_name]
# name of the content type
def content_node_type(component,content_type,options = {})
after_create :content_node_type_create
after_update :content_node_type_update
has_one :content_type, :as => 'Container', :dependent => :destroy
options = options.clone
options[:component] = component.to_s
options[:content_type] = content_type
options.symbolize_keys!
self.send(:include, ModelExtension::ContentNodeExtension::NodeTypeInstanceMethods)
define_method(:content_node_type_options) do
options
end
end
end
def self.append_features(mod) #:nodoc:
super
mod.extend ModelExtension::ContentNodeExtension::ClassMethods
end
module InstanceMethods
def content_node_save #:nodoc:
# Only save if we aren't already inside of save_content
save_content(nil,{},true) if(!content_node_skip)
end
# This is added to all content nodes, and should ideally be used
# to save the object as it will record the last author into the content node
# table (otherwise it is called automatically after save)
def save_content(user,atr={},skip_save = false)
self.attributes = atr
self.content_node_skip = true
if skip_save || (saved_content = self.save)
if !self.content_node_options[:except] || !resolve_argument(self.content_node_options[:except],nil)
cn = self.content_node || self.build_content_node
cn.update_node_content(user,self,self.content_node_options)
end
end
self.content_node_skip = false
return skip_save || saved_content
end
end
module NodeTypeInstanceMethods #:nodoc:all
def content_node_type_create #:nodoc:
if !self.content_node_type_options[:except] || !resolve_argument(self.content_node_type_options[:except],nil)
opts = self.content_node_type_options
title_field = (opts[:title_field] || 'name')
url_field = (opts[:url_field] || 'id')
title_field = title_field.call(self) if title_field.is_a?(Proc)
url_field = url_field.call(self) if url_field.is_a?(Proc)
# Get the name of the content
content_name = self.resolve_argument(opts[:content_name],:name)
content_type = resolve_argument(opts[:content_type])
ContentType.create(:component => opts[:component],
:container => self,
:content_name => content_name,
:content_type => content_type,
:title_field => title_field.to_s,
:url_field => url_field.to_s,
:search_results => opts[:search] )
end
end
def content_node_type_update #:nodoc:
opts = self.content_node_type_options
# Get the name of the content
content_name = self.resolve_argument(opts[:content_name],:name)
if !self.content_type
self.content_node_type_create
elsif content_name != self.content_type.content_name
self.content_type.update_attributes(:content_name => content_name)
end
end
end
end