Commits

Mike Bayer committed eb98ffa

some updates to UOW, fixes to all those relation() calls

Comments (0)

Files changed (3)

doc/build/content/adv_datamapping.myt

 <&|formatting.myt:code&>
     # order address objects by address id
     mapper = mapper(User, users, properties = {
-        'addresses' : relation(Address, addresses, order_by=addresses.c.address_id)
+        'addresses' : relation(mapper(Address, addresses), order_by=addresses.c.address_id)
     })
     
     # eager load with ordering - the ORDER BY clauses of parent/child will be organized properly
     mapper = mapper(User, users, properties = {
-        'addresses' : relation(Address, addresses, order_by=desc(addresses.c.email_address), eager=True)
+        'addresses' : relation(mapper(Address, addresses), order_by=desc(addresses.c.email_address), eager=True)
     }, order_by=users.c.user_id)
     
 </&>
         class Address(object):
             pass
         m = mapper(User, users, properties={
-            'addresses' : relation(Address, addresses, lazy=False)
+            'addresses' : relation(mapper(Address, addresses), lazy=False)
         })
         r = m.select(User.c.user_name.like('F%'), limit=20, offset=10)
 <&|formatting.myt:poppedcode, link="sql" &>
         
         # a 'lazy' relationship
         User.mapper = mapper(User, users, properties = {
-            'addreses':relation(Address, addresses, lazy=True)
+            'addreses':relation(mapper(Address, addresses), lazy=True)
         })
     
         # copy the mapper and convert 'addresses' to be eager
         
         # mapper two - this one will also eager-load address objects in
         m2 = mapper(User, users, properties={
-                'addresses' : relation(Address, addresses, lazy=False)
+                'addresses' : relation(mapper(Address, addresses), lazy=False)
             })
         
         # get a user.  this user will not have an 'addreses' property

doc/build/content/datamapping.myt

                     self.state = state
                     self.zip = zip
         </&>
-<p>And then a Mapper that will define a relationship of the User and the Address classes to each other as well as their table metadata.  We will add an additional mapper keyword argument <span class="codeline">properties</span> which is a dictionary relating the name of an object property to a database relationship, in this case a <span class="codeline">relation</span> object which will define a new mapper for the Address class:</p>
+<p>And then a Mapper that will define a relationship of the User and the Address classes to each other as well as their table metadata.  We will add an additional mapper keyword argument <span class="codeline">properties</span> which is a dictionary relating the name of an object property to a database relationship, in this case a <span class="codeline">relation</span> object against a newly defined  mapper for the Address class:</p>
         <&|formatting.myt:code&>
             User.mapper = mapper(User, users, properties = {
-                                'addresses' : relation(Address, addresses)
+                                'addresses' : relation(mapper(Address, addresses))
                             }
                           )
         </&>
-<p>Alternatively, the Address mapper can be defined separately.  This allows the mappers of various objects to be combined in any number of ways at runtime:
-        <&|formatting.myt:code&>
-            Address.mapper = mapper(Address, addresses)
-            User.mapper = mapper(User, users, properties = {
-                                'addresses' : relation(Address.mapper)
-                            }
-                          )
-        </&>
-
-</p>
 <p>Lets do some operations with these classes and see what happens:</p>
 
         <&|formatting.myt:code&>
 
         <&|formatting.myt:code&>
             User.mapper = mapper(User, users, properties = {
-                                'addresses' : relation(Address, addresses, private=True)
+                                'addresses' : relation(mapper(Address, addresses), private=True)
                             }
                           )
             del u.addresses[1]
 <&|doclib.myt:item, name="backreferences", description="Useful Feature: Backreferences" &>
 <p>By creating relations with the <span class="codeline">backref</span> keyword, a bi-directional relationship can be created which will keep both ends of the relationship updated automatically, even without any database queries being executed.  Below, the User mapper is created with an "addresses" property, and the corresponding Address mapper receives a "backreference" to the User object via the property name "user":
         <&|formatting.myt:code&>
+            Address.mapper = mapper(Address, addresses)
             User.mapper = mapper(User, users, properties = {
-                                'addresses' : relation(Address, addresses, backref='user')
+                                'addresses' : relation(Address.mapper, backref='user')
                             }
                           )
 
         <&|formatting.myt:code&>
             # define a mapper
             User.mapper = mapper(User, users, properties = {
-                              'addresses' : relation(Address, addresses, private=True)
+                              'addresses' : relation(mapper(Address, addresses), private=True)
                             })
         
             # select users where username is 'jane', get the first element of the list
         <p>With just a single parameter "lazy=False" specified to the relation object, the parent and child SQL queries can be joined together.
 
         <&|formatting.myt:code&>
+    Address.mapper = mapper(Address, addresses)
     User.mapper = mapper(User, users, properties = {
-                        'addresses' : relation(Address, addresses, lazy=False)
+                        'addresses' : relation(Address.mapper, lazy=False)
                     }
                   )
 
         <&|formatting.myt:code&>
           # user mapper with lazy addresses
           User.mapper = mapper(User, users, properties = {
-                                 'addresses' : relation(Address, addresses)
+                                 'addresses' : relation(mapper(Address, addresses))
                              }
                     )
                     
         class UserPrefs(object):
             pass
         UserPrefs.mapper = mapper(UserPrefs, prefs)
-    
+        
+        # address mapper
+        Address.mapper = mapper(Address, addresses)
+        
         # make a new mapper referencing everything.
         m = mapper(User, users, properties = dict(
-            addresses = relation(Address, addresses, lazy=True, private=True),
+            addresses = relation(Address.mapper, lazy=True, private=True),
             preferences = relation(UserPrefs.mapper, lazy=False, private=True),
         ))
         
             class KeywordAssociation(object):
                 pass
 
+            # mapper for KeywordAssociation
+            KeywordAssociation.mapper = mapper(KeywordAssociation, itemkeywords)
+            
             # mappers for Users, Keywords
             User.mapper = mapper(User, users)
             Keyword.mapper = mapper(Keyword, keywords)
             # eager loading.  but the user who added each keyword, we usually dont need so specify 
             # lazy loading for that.
             m = mapper(Article, articles, properties=dict(
-                keywords = relation(KeywordAssociation, itemkeywords, lazy=False, association=Keyword, 
+                keywords = relation(KeywordAssociation.mapper, lazy=False, association=Keyword, 
                     primary_key = [itemkeywords.c.article_id, itemkeywords.c.keyword_id],
                     properties={
-                        'keyword' : relation(Keyword, lazy = False),
-                        'user' : relation(User, lazy = True)
+                        'keyword' : relation(Keyword, lazy = False), # uses primary Keyword mapper
+                        'user' : relation(User, lazy = True) # uses primary User mapper
                     }
                 )
                 )

doc/build/content/unitofwork.myt

     </ul></p>
     </&>
     <&|doclib.myt:item, name="getting", description="Accessing UnitOfWork Instances" &>
-    <p>The current unit of work is a thread-local instance maintained within an object called a Session.  These objects are accessed as follows:</p>
+    <p>The current unit of work is accessed via the Session interface.  The Session is available in a thread-local context from the objectstore module as follows:</p>
         <&|formatting.myt:code&>
-            # get the current session - there is by default one per application
-            s = objectstore.session()
-            
-            # get the thread local unit of work from the session
-            u = s.uow
+            # get the current thread's session
+            s = objectstore.get_session()
         </&>
-    <p>The Session object acts as a proxy to all attributes on the current thread's unit of work and also includes the common methods begin(), commit(), etc.  Also, most methods are available as functions on the objectstore package itself so common operations need not explicitly reference the current Session or UnitOfWork instance.
+    <p>The Session object acts as a proxy to an underlying UnitOfWork object.  Common methods include commit(), begin(), clear(), and delete().  Most of these methods are available at the module level in the objectstore module, which operate upon the Session returned by the get_session() function.
     </p>
     <p>To clear out the current thread's UnitOfWork, which has the effect of discarding the Identity Map and the lists of all objects that have been modified, just issue a clear:
     </p>
     <&|formatting.myt:code&>
+        # via module
         objectstore.clear()
+        
+        # or via Session
+        objectstore.get_session().clear()
     </&>
     <p>This is the easiest way to "start fresh", as in a web application that wants to have a newly loaded graph of objects on each request.  Any object instances before the clear operation should be discarded.</p>
     </&>
     <p>The current thread's UnitOfWork object keeps track of objects that are modified.  It maintains the following lists:</p>
     <&|formatting.myt:code&>
         # new objects that were just constructed
-        objectstore.session().new
+        objectstore.get_session().new
         
         # objects that exist in the database, that were modified
-        objectstore.session().dirty
+        objectstore.get_session().dirty
         
         # objects that have been marked as deleted via objectstore.delete()
-        objectstore.session().deleted
+        objectstore.get_session().deleted
     </&>
     <p>To commit the changes stored in those lists, just issue a commit.  This can be called via <span class="codeline">objectstore.session().commit()</span>, or through the module-level convenience method in the objectstore module:</p>
     <&|formatting.myt:code&>
         myobj1.foo = "something new"
         
         # begin an objectstore scope
-        # this is equivalent to objectstore.uow().begin()
+        # this is equivalent to objectstore.get_session().begin()
         objectstore.begin()
         
         # modify another object
         r = MyObj.mapper.using(s).select_by(id=12)
             
         # get the session that corresponds to an instance
-        s = objectstore.session(x)
+        s = objectstore.get_session(x)
         
         # commit 
         s.commit()