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.
102 103 104 |
# File 'lib/og/relation.rb', line 102 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.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/og/relation.rb', line 231 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.
223 224 225 226 227 |
# File 'lib/og/relation.rb', line 223 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.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/og/relation.rb', line 199 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
158 159 160 161 162 163 164 |
# File 'lib/og/relation.rb', line 158 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
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/og/relation.rb', line 178 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
138 139 140 141 142 143 144 145 |
# File 'lib/og/relation.rb', line 138 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. ++
122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/og/relation.rb', line 122 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 |
# File 'lib/og/relation.rb', line 96 def to_s @options[:target_name] end |