Class: Og::Relation
- Inherits:
-
Object
- Object
- Og::Relation
- Defined in:
- lib/og/relation.rb,
lib/og/relation.rb
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.
- #to_s ⇒ Object
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.
103 104 105 |
# File 'lib/og/relation.rb', line 103 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.
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/og/relation.rb', line 236 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.
228 229 230 231 232 |
# File 'lib/og/relation.rb', line 228 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.
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/og/relation.rb', line 204 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.to_sym else r.target_class.to_s.demodulize.underscore.downcase.to_sym 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
162 163 164 165 166 167 168 |
# File 'lib/og/relation.rb', line 162 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
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/og/relation.rb', line 182 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
139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/og/relation.rb', line 139 def resolve_targets(klass) for r in klass.relations if r.target_class.is_a? Symbol if klass = symbol_to_class(r.target_class, r.owner_class) r.[:target_class] = klass else Logger.error "Cannot resolve target class '#{r.target_class}' for relation '#{r}' of class '#{r.owner_class}'!" end 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. ++
123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/og/relation.rb', line 123 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 |
#to_s ⇒ Object
96 97 98 99 |
# File 'lib/og/relation.rb', line 96 def to_s self.class.to_s.underscore # @options[:target_name] end |