Class: Og::Relation
Overview
A collection of helper methods and resolvers for relations.
Instance Attribute Summary collapse
-
#options ⇒ Object
The parameters of this relation.
Class Method Summary collapse
-
.enchant(klass) ⇒ Object
Perform relation enchanting on this class.
-
.resolve(klass, action = :resolve_polymorphic) ⇒ Object
General resolve method.
-
.resolve_names(klass) ⇒ Object
Resolve the names of the relations.
-
.resolve_polymorphic_markers(klass) ⇒ Object
If the target class is just an Object mark this class (self) as a polymorphic parent class.
-
.resolve_polymorphic_relations(klass) ⇒ Object
Resolve polymorphic relations.
- .resolve_targets(klass) ⇒ Object
-
.symbol_to_class(sym, owner_class) ⇒ Object
(also: resolve_symbol)
To avoid forward declarations, references to undefined (at the time of the creation of the relation) classes are stored as symbols.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Get an option.
-
#[]=(key, val) ⇒ Object
Set an option.
-
#enchant ⇒ Object
This method is implemented in subclasses.
-
#initialize(args, options = {}) ⇒ Relation
constructor
A generalized initialize method for all relations.
-
#method_missing(sym, *args) ⇒ Object
Access the hash values as methods.
-
#polymorphic? ⇒ Boolean
Is this a polymorphic relation ?.
-
#polymorphic_marker? ⇒ Boolean
Is this a polymorphic marker?.
-
#resolve_polymorphic ⇒ Object
Resolve a polymorphic target class.
Constructor Details
#initialize(args, options = {}) ⇒ Relation
A generalized initialize method for all relations. Contains common setup code.
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 |
# File 'lib/og/relation.rb', line 24 def initialize(args, = {}) @options = @options.update(args.pop) if args.last.is_a?(Hash) target_name = if collection :target_plural_name else :target_singular_name end # Check that all needed options are provided. if args.empty? or (not (args.last.is_a?(Class) or args.last.is_a?(Symbol))) raise 'Class of target not defined' end # Try to set the target class. Checks for class and # class symbol. if args.last.to_s.capitalized? @options[:target_class] = args.pop end # Try to set the target name. if args.last.is_a? Symbol @options[target_name] = args.pop end # Inflect target_class if not provided. @options[:target_class] ||= @options[target_name].to_s.singular.camelize.intern # FIXME: this is a hack! # setup() rescue nil end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(sym, *args) ⇒ Object
Access the hash values as methods.
98 99 100 |
# File 'lib/og/relation.rb', line 98 def method_missing(sym, *args) return @options[sym] end |
Instance Attribute Details
#options ⇒ Object
The parameters of this relation.
19 20 21 |
# File 'lib/og/relation.rb', line 19 def @options end |
Class Method Details
.enchant(klass) ⇒ Object
Perform relation enchanting on this class.
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/og/relation.rb', line 227 def enchant(klass) # update inherited relations. for r in klass.relations r[:owner_class] = klass end # enchant. for r in klass.relations # p "=== #{klass} : #{r.class} : #{r.name}" r.enchant() unless r.polymorphic_marker? end end |
.resolve(klass, action = :resolve_polymorphic) ⇒ Object
General resolve method.
219 220 221 222 223 |
# File 'lib/og/relation.rb', line 219 def resolve(klass, action = :resolve_polymorphic) for r in klass.relations r.send(action) end end |
.resolve_names(klass) ⇒ Object
Resolve the names of the relations.
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/og/relation.rb', line 195 def resolve_names(klass) for r in klass.relations target_name = if r.collection :target_plural_name else :target_singular_name end # Inflect the relation name. unless r[target_name] r[target_name] = if r.collection r.target_class.to_s.demodulize.underscore.downcase.plural.intern else r.target_class.to_s.demodulize.underscore.downcase.intern end end r[:name] = r[target_name] end end |
.resolve_polymorphic_markers(klass) ⇒ Object
If the target class is just an Object mark this class (self) as a polymorphic parent class. This class acts as template to generate customized versions of this class.
For example:
class Comment
belongs_to :parent, Object # <= polymorphic
...
end
154 155 156 157 158 159 160 |
# File 'lib/og/relation.rb', line 154 def resolve_polymorphic_markers(klass) for r in klass.relations if r.polymorphic_marker? r.owner_class.ann :self, :polymorphic => r.owner_class end end end |
.resolve_polymorphic_relations(klass) ⇒ Object
Resolve polymorphic relations. If the target class is polymorphic, create a specialized version of that class (the target) enclosed in the owner namespace.
For example:
class Article
has_many Comment
...
end
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/og/relation.rb', line 174 def resolve_polymorphic_relations(klass) for r in klass.relations if r.polymorphic? target_dm = r.target_class.to_s.demodulize r.owner_class.module_eval %{ class #{r.owner_class}::#{target_dm} < #{r.target_class} end } # Replace the target class. r[:target_class] = eval("#{r.owner_class}::#{target_dm}") end r.resolve_polymorphic end end |
.resolve_targets(klass) ⇒ Object
134 135 136 137 138 139 140 141 |
# File 'lib/og/relation.rb', line 134 def resolve_targets(klass) for r in klass.relations if r.target_class.is_a? Symbol klass = symbol_to_class(r.target_class, r.owner_class) r.[:target_class] = klass end end end |
.symbol_to_class(sym, owner_class) ⇒ Object Also known as: resolve_symbol
To avoid forward declarations, references to undefined (at the time of the creation of the relation) classes are stored as symbols. These symbols are resolved by this method. – FIXME: do something more elegant here. ++
118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/og/relation.rb', line 118 def symbol_to_class(sym, owner_class) c = owner_class.name.dup c = "::" + c unless c =~ /::/ c.gsub!(/::.*$/, '::') c << sym.to_s begin return constant(c) rescue unless c == sym c = sym retry end end end |
Instance Method Details
#[](key) ⇒ Object
Get an option.
63 64 65 |
# File 'lib/og/relation.rb', line 63 def [](key) @options[key] end |
#[]=(key, val) ⇒ Object
Set an option.
69 70 71 |
# File 'lib/og/relation.rb', line 69 def []=(key, val) @options[key] = val end |
#enchant ⇒ Object
This method is implemented in subclasses.
93 94 |
# File 'lib/og/relation.rb', line 93 def enchant end |
#polymorphic? ⇒ Boolean
Is this a polymorphic relation ?
81 82 83 |
# File 'lib/og/relation.rb', line 81 def polymorphic? target_class.ann.self[:polymorphic] end |
#polymorphic_marker? ⇒ Boolean
Is this a polymorphic marker?
75 76 77 |
# File 'lib/og/relation.rb', line 75 def polymorphic_marker? target_class == Object end |
#resolve_polymorphic ⇒ Object
Resolve a polymorphic target class. Overrided in subclasses.
88 89 |
# File 'lib/og/relation.rb', line 88 def resolve_polymorphic end |