This is cool. I think your TimeClock example is essentially the pattern used 
for the web2py Mail, Auth, and Crud classes. It might be useful to include a 
section in the book about this pattern (or at least a web2py slice).
 
Anthony

On Monday, February 28, 2011 11:14:04 AM UTC-5, Ross Peoples wrote:

> I've always read that if you needed to centralize your logic, that you 
> should use modules instead of trying to do it in a model or trying to wire 
> up one controller to another. I used global settings as an example, as you 
> might need access to these settings in every controller, and duplicating the 
> code in every controller goes against the Python and we2py's DRY 
> (don't repeat yourself) principal. So this is why modules were created. 
>
> Granted, the GlobalSettings object I demonstrated is a very basic object 
> that doesn't require you to instantiate it because it's all static. However, 
> if you want to use more sophisticated objects, then the static class method 
> may not work well. So there's another way to do this that I've been playing 
> with.
>
> I am replacing a legacy application that is sort of like an ERP. The 
> application keeps track of when employees clock in and clock out. Then, at 
> the end of the week they print out their time cards. So, I wrote a TimeClock 
> class in the same 'core.py' file described above. The big difference here is 
> that the TimeClock object will have several functions, and I don't want to 
> have to pass db, cache, and everything else for every function call, so I 
> wrote it like this:
>
> class TimeClock:
>     def __init__(self, environment, db):
>         self.env = Storage(environment)
>         self.request = self.env.request
>         self.response = self.env.response
>         self.cache = self.env.cache
>         self.db = db
>
>     def is_employee_clocked_in(self, employee):
>         db = self.db
>         timeclock_entry = db((db.timeclock.employee==employee) & 
> (db.timeclock.endtime==None)).select().first()
>         if timeclock_entry is None:
>             return False
>         else:
>             return True
>
> Now, in my 'z_import_modules.py', I would add this (assuming I already did 
> a local_import on core.py):
>
> timeclock = core.TimeClock(globals(), db)
>
> Then in any controller, if I want to check if an employee is clocked in:
>
> employee = auth.user
> if timeclock.is_employee_clocked_in(employee):
>     print '%s is clocked in' % (employee.first_name)
> else:
>     print '%s is not clocked in' % (employee.first_name)
>
> So with modules, you can make static classes for simple objects, like 
> global settings that just load and save settings, or you can make complex 
> objects that you instantiate in either the 'z_import_modules.py' file, or if 
> you don't plan on using the module in every controller, then you could just 
> remove the line we added in 'z_import_modules.py' to instantiate the 
> 'timeclock' object, and use that line in whatever controller action we want.
>
> Hope this helps. So far this method seems to work really well. Oh, and to 
> help you avoid some frustration in developing your modules, when you call 
> local_import, you may also want to add reload=True to it. Without this, you 
> would have to restart the web2py server every time you made a change to the 
> module. Once you put your app into production, you would want to remove 
> reload=True, as you don't want web2py to reload the module for every page 
> load on a production server. So for testing, use this line:
>
> core = local_import('core', reload=True)
>
> And when you go into production, just remove 'reload=True'.
>

Reply via email to