Module: Og::MetaLanguage
- Included in:
- Module
- Defined in:
- lib/og/meta.rb
Overview
Implements a meta-language for manipulating og-managed objects and defining their relationships. The original idea comes from the excellent ActiveRecord library.
Many more useful relations will be available soon.
Instance Method Summary collapse
-
#belongs_to(name, klass, options = {}) ⇒ Object
Implements a ‘belongs_to’ relation.
-
#has_many(name, klass, options = {}) ⇒ Object
Implements a ‘has_many’ relation.
-
#has_one(name, klass = nil, options = {}) ⇒ Object
Implements a ‘has_one’ relation.
-
#joins(klass, options = {}) ⇒ Object
Declares that this class can join with another class.
-
#many_to_many(name, klass, options = {}) ⇒ Object
(also: #has_and_belongs_to_many)
Implements a ‘many_to_many’ relation.
-
#refers_to(name, klass, options = {}) ⇒ Object
Implements a ‘refers_to’ relation.
-
#sql_index(index, options = {}) ⇒ Object
Defines an SQL index.
Instance Method Details
#belongs_to(name, klass, options = {}) ⇒ Object
Implements a ‘belongs_to’ relation. Automatically enchants the calling class with helper methods.
Example:
class MyObject belongs_to AnotherObject, :prop => :parent end
creates the code:
prop_accessor Fixnum, :parent_oid def parent; … end def parent=(obj_or_oid); … end
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/og/meta.rb', line 84 def belongs_to(name, klass, = {}) prop_eval = "prop_accessor Fixnum, :#{name}_oid" prop_eval << ", :sql => '#{[:sql]}'" if [:sql] prop_eval << ", :extra_sql => '#{[:extra_sql]}'" if [:extra_sql] :belongs_to, klass module_eval %{ #{prop_eval} def #{name} Og.db.load_by_oid(@#{name}_oid, #{klass}) end def #{name}=(obj_or_oid) @#{name}_oid = obj_or_oid.to_i end } end |
#has_many(name, klass, options = {}) ⇒ Object
Implements a ‘has_many’ relation. Automatically enchants the calling class with helper methods.
Example:
class MyObject has_many :children, AnotherObject end
creates the code:
def children; … end
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/og/meta.rb', line 151 def has_many(name, klass, = {}) name_s = N::Inflector.singularize(name.to_s) # linkback is the property of the child object that 'links back' # to this object. linkback = [:linkback] || "#{MetaUtils.(self)}_oid" # keep belongs to metadata, useful for # reflection/scaffolding. :has, [klass, linkback] module_eval %{ def #{name}(extrasql = nil) Og.db.select("SELECT * FROM #{Og::Adapter.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}", #{klass}) end def #{name}_count(extrasql = nil) Og.db.count("SELECT COUNT(*) FROM #{Og::Adapter.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}") end def add_#{name_s}(obj, extra = nil) obj.#{linkback} = @oid obj.save! end def delete_all_#{name}(extrasql = nil) Og.db.exec("DELETE FROM #{Og::Adapter.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}") end } end |
#has_one(name, klass = nil, options = {}) ⇒ Object
Implements a ‘has_one’ relation. Automatically enchants the calling class with helper methods.
Example:
class MyObject has_one :child, TheClass has_one :article end
creates the code:
…
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/og/meta.rb', line 118 def has_one(name, klass = nil, = {}) # linkback is the property of the child object that 'links back' # to this object. linkback = [:linkback] || "#{MetaUtils.(self)}_oid" :has, [klass, linkback] module_eval %{ def #{name}(extrasql = nil) Og.db.select_one("SELECT * FROM #{Og::Adapter.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}", #{klass}) end def delete_#{name}(extrasql = nil) Og.db.exec("DELETE FROM #{Og::Adapter.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}") end } end |
#joins(klass, options = {}) ⇒ Object
Declares that this class can join with another class. The join parameters are given so the join-compatible methods are generated.
323 324 325 |
# File 'lib/og/meta.rb', line 323 def joins(klass, = {}) :joins, [klass, ] end |
#many_to_many(name, klass, options = {}) ⇒ Object Also known as: has_and_belongs_to_many
Implements a ‘many_to_many’ relation. Two objects are associated using an intermediate join table. Automatically enchants the calling class with helper methods.
Options:
Example:
class Article many_to_many :categories, Category, :linkback => articles end
article.categories article.del_category article.add_category article.clear_categories
category.articles … – FIXME: make more compatible with other enchant methods. ++
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/og/meta.rb', line 207 def many_to_many(name, klass, = {}) list_o = name.to_s prop_o = N::Inflector.singularize(list_o) list_m = [:linkback] || N::Inflector.plural_name(self) prop_m = N::Inflector.singularize(list_m) # exit if the class is allready indirectly 'enchanted' from the # other class of the many_to_many relation. return if self.respond_to?(prop_m) # Add some metadata to the class to allow for automatic join table # calculation. :sql_join, [klass, ] :many_to_many, klass klass. :many_to_many, self # enchant this class module_eval %{ def #{list_o}(extrasql = nil) Og.db.select("SELECT d.* FROM #{Og::Adapter.table(klass)} AS d, #{Og::Adapter.join_table(self, klass)} AS j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass}) end def #{list_o}_count(extrasql = nil) Og.db.select("SELECT COUNT(*) FROM #{Og::Adapter.table(klass)} AS d, #{Og::Adapter.join_table(self, klass)} AS j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass}) end def add_#{prop_o}(obj, extra = nil) Og.db.exec("INSERT INTO #{Og::Adapter.join_table(self, klass)} (key1, key2) VALUES (\#\@oid, \#\{obj.oid\})") end def delete_#{prop_o}(obj_or_oid, extra = nil) Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass)} WHERE key2=\#\{obj_or_oid.to_i\}") end def clear_#{list_o} Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass)} WHERE key1=\#\@oid") end } # indirectly enchant the other class of the relation. klass.module_eval %{ def #{list_m}(extrasql = nil) Og.db.select("SELECT s.* FROM #{Og::Adapter.table(self)} AS s, #{Og::Adapter.join_table(self, klass)} AS j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self}) end def #{list_m}_count(extrasql = nil) Og.db.select("SELECT COUNT(*) FROM #{Og::Adapter.table(self)} AS s, #{Og::Adapter.join_table(self, klass)} AS j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self}) end def add_#{prop_m}(obj, extra = nil) Og.db.exec("INSERT INTO #{Og::Adapter.join_table(self, klass)} (key1, key2) VALUES (\#\{obj.oid\}, \#\@oid)") end def delete_#{prop_m}(obj_or_oid, extra = nil) Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass)} WHERE key1=\#\{obj_or_oid.to_i\}") end def clear_#{list_m} Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass)} WHERE key2=\#\@oid") end } end |
#refers_to(name, klass, options = {}) ⇒ Object
Implements a ‘refers_to’ relation. This is a one-way version of the ‘has_one’/‘belongs_to’ relations. The target object cannot link back to the source object. This is in fact EXACTLY the same as belongs_to with a different name (!!!!)
Automatically enchants the calling class with helper methods.
Example:
class MyObject refers_to article, Article end
creates the code:
prop_accessor Fixnum, :article_oid def article; … end def article=(obj_or_oid); … end
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
# File 'lib/og/meta.rb', line 298 def refers_to(name, klass, = {}) prop_eval = "prop_accessor Fixnum, :#{name}_oid" prop_eval << ", :sql => '#{[:sql]}'" if [:sql] prop_eval << ", :extra_sql => '#{[:extra_sql]}'" if [:extra_sql] :refers_to, klass klass. :has, [self, "#{name}_oid"] module_eval %{ #{prop_eval} def #{name} Og.db.load_by_oid(@#{name}_oid, #{klass}) end def #{name}=(obj_or_oid) @#{name}_oid = obj_or_oid.to_i end } end |
#sql_index(index, options = {}) ⇒ Object
Defines an SQL index. Useful for defining indiced over multiple columns.
65 66 67 |
# File 'lib/og/meta.rb', line 65 def sql_index(index, = {}) :sql_index, [index, ] end |