Changes between Version 3 and Version 4 of TestManagerForTracPluginGenericClass


Ignore:
Timestamp:
Jan 4, 2011, 6:41:50 PM (13 years ago)
Author:
Roberto Longobardi
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • TestManagerForTracPluginGenericClass

    v3 v4  
    118118
    119119 * Create an empty object, and also try to fetch it from the database, if an object with a matching key is found.
    120    To fetch an existing object from the database:
     120   To fetch an existing object from the database and modify or delete it:
    121121   1. specify a key at contruction time: the object will be filled with all of the values form the database,
    122122   2. modify any other property via the {{{obj['fieldname'] = value}}} syntax, including custom fields.
    123123      This syntax is the only one to keep track of the changes to any field.
    124    3. call the save_changes() method on the object.[[BR]]
     124   3. call the save_changes() or delete() method on the object.[[BR]]
    125125 * Create a new object to be later stored in the database. In this case, the steps required are the following:
    126126   1. specify a key at contruction time,
     
    358358
    359359[[BR]]
     360== A sample use ==
     361
     362Now that we have our new class and provider in place, '''let's see how to use them'''!
     363
     364=== Creating a new, non-existing object ===
     365
     366To create a new, non existing object of our new class, we follow the steps outlined above:
     367
     368   1. specify a key at contruction time,
     369   2. set any other property via the {{{obj['fieldname'] = value}}} syntax, including custom fields,
     370   3. call the insert() method on the object.
     371
     372See the following code.
     373
     374{{{
     375# Let's first import our new class definition.
     376# Note that you don't have to deal with the framework in any way, the class may be defined on its own.
     377from tracgenericworkflow.model import ResourceWorkflowState
     378}}}
     379
     380{{{
     381    # The following statement will create an empty object with a specific key, and suddenly
     382    # try to fetch an object with the same key from the database.
     383    # If it is found, then the object's properties will be filled with the corresponding values
     384    # from the database, and the internal field "exists" set to True.
     385    rws = ResourceWorkflowState(self.env, id, sometext)
     386   
     387    # We can here check whether the object was found in the database
     388    if rws.exists:
     389        # The object already exists! So we can get its property values
     390        print rws['state']
     391    else:
     392        # Here we decide to create the object. So we fill in some other properties and then call the "insert()" method.
     393        # The object will be stored into the database, and all registered listeners will be called.
     394        rws['state'] = 'new'
     395        rws.insert()
     396}}}
     397
     398=== Reading an existing object, and changing it ===
     399
     400Here we want to read an existing object of our new class, alter some of its properties and save it back.
     401
     402We follow the steps outlined above:
     403
     404   1. specify a key at contruction time: the object will be filled with all of the values form the database,
     405   2. modify any other property via the {{{obj['fieldname'] = value}}} syntax, including custom fields.
     406      This syntax is the only one to keep track of the changes to any field.
     407   3. call the save_changes() method on the object.[[BR]]
     408
     409See the code below.
     410
     411{{{
     412    rws = ResourceWorkflowState(self.env, id, sometext)
     413   
     414    if rws.exists:
     415        # The object already exists.
     416        # Now we also want to modify the object's 'state' property, and save the updated object.
     417        rws['state'] = 'ok'
     418
     419        # The following code will modify the object in the database and also call all
     420        # of the registered listeners.
     421        try:
     422            rws.save_changes(author, "State changed")
     423        except:
     424            self.log.info("Error saving the resource with id %s" % rws['id'])
     425}}}
     426
     427Saving changes will also keep track of the change history into a different table, named like the base table with an "_change" suffix.
     428Note: Currently there is no explicit programmatic API to access these change tables, you must access them directly with SQL if you need to.
     429
     430=== Delete an object ===
     431
     432Deleting an object is as simple as calling the {{{delete()}}} method on the object instance.
     433
     434See the following code.
     435
     436{{{
     437    rws = ResourceWorkflowState(self.env, id, sometext)
     438   
     439    if rws.exists:
     440        # The object already exists.
     441        # Now we want to delete the object from the database. The following code will delete the
     442        # object and also call all of the registered listeners.
     443        try:
     444            rws.delete()
     445        except:
     446            self.log.info("Error deleting the resource with id %s" % rws['id'])
     447}}}
     448
     449=== Use pattern-matching to find a particular set of objects ===
     450
     451You can get a list of objects matching a particular set of properties - i.e. pattern matching - very easily:
     452
     453 1. Create an empty, template object, without specifying a key,
     454 2. Give values to any properties you want the objects in the database to match,
     455 3. Call the list_matching_objects() method on the object.
     456
     457See the following code.
     458
     459{{{
     460    # We create a template object here, i.e. not providing a key.
     461    rws_search = ResourceWorkflowState(self.env)
     462
     463    # Let's say we want to list all the objects in the database having a 'state' of 'new'.
     464    # We set the desired property values in the template objects
     465    rws_search['state'] = 'new'
     466
     467    # We then start the search
     468    for rws in rws_search.list_matching_objects():
     469        # At every cycle, rws will hold another result matching the search pattern, in the
     470        # form of a full-fetched object of the ResourceWorkflowState type.
     471        print rws['id']
     472}}}
     473
     474[[BR]]
     475== Providing specific results to the Trac search engine ==
     476
     477Subclasses can participate in the Trac search engine, if they wish to. It is a matter of a few lines of code.
     478
     479First of all, the concrete class provider must explicitly state this support in the class metadata, just by setting the 'searchable' metadata property. For more details about class metadata, refer to the IConcreteClassProvider interface implementation.
     480
     481Then, the subclass must override the {{{get_search_results()}}} method.
     482
     483For details about how to implement this method, refer to the base Trac documentation about the {{{ISearchSource}}} interface in the {{{trac.search}}} package.
     484
     485[[BR]]
    360486== IGenericObjectChangeListener - Registering listeners to objects lifecycle events ==
    361487