PhoneFormatter.cfc 1.0

I typically store phone numbers in one field (instead of using a separate field for each part of a phone number). While this usually works quite well, I have discovered that it can cause issues when I want a phone number to display in the same format regardless of how it was originally entered.

This is relatively easy to do if you handle it as the data comes in, but if you don't (either as oversight or because the data comes from outside the system) then it is a more difficult task.

I created PhoneFormatter to handle this task. Actually, it can handle formatting the data on an individual string or on a field across a whole table.

PhoneFormatter does require DataMgr. It also requires you to pass in the format you want to use for the phone number (using zeros as place-holders for digits). You should also pass in a default area code for numbers that don't have one. So the arguments for the init() method are:

  • DataMgr: An instantiated DataMgr component
  • Format: The desired format for phone number (using zeros as place holders for digits)
  • DefaultAreaCode: (optional) The area code you want PhoneFormatter to assign to phone numbers that don't have one.

To format a single phone number, pass it to the fixPhoneNumber() function (optionally passing in an area code as a separate argument).

To format every row for one field in a table, use the fixPhoneNumbers() method.

  • table: The name of the table in which you have the phone number.
  • idfield: The primary key field for the table.
  • phonefield: The field in the table in which you have the phone number.

PhoneFormatter may not solve a problem that you have, but if it does it can certainly be useful.

It is open source and free for any use. Feel free to download PhoneFormatter and try it out. 

 

Capitalizer.cfc 1.0

Recently, a client of mine started working on printing up badges for users on their system. As soon as we started testing the system, they complained that the badges looked amateurish.

The problem was that the badges were using information originally entered by the users themselves. Sometimes these users enter their information with caps-lock on. So, "Joe Smith" could come out "JOE SMITH" or even "jOE sMITH". Naturally, both of these look pretty unprofessional on a printed badge.

With more than three thousand users already on the system (and more signing up all the time), it wasn't really practical to fix each entry by hand.

At the same time, these seemed like a problem that I was likely to run into again, so I wanted a general solution that I could use again in the future.

The result is Capitalizer.cfc, the heart of which is Adrian Lynch's TitleCaseList() UDF. The component does require DataMgr, but only to keep the code brief.

The main method of Capitalizer is fixFieldCase(). This method can correct the capitalization for a selected field in a table, using the following arguments:

  • table: The name of the table in which you want to fix the capitalization.
  • field: The field in the table in which you want to fix the capitalization.
  • pkfields: A comma delimited list of the primary key fields in the table.

You can also use Capitalizer to correct the case for a single string. You can pass in any string to the fixCase() method and it will return the string with the capitalization fixed.

Capitalizer watches for words that shouldn't be capitalized (like "and,or,the") and makes sure that they aren't. It also makes sure that directions (NE,SW) are capitalized. It also make sure that "mc" names (like "McWilliams") are capitalized correctly.

Capitalizer.cfc is open source and free for any use. Feel free to try it out. 

Scheduler.cfc 1.0 Beta

Using service components, one of the challenges that I have run into (and I think others have as well) is that I need to schedule a task from a component, but it doesn't make sense to do so.

So, I have a Scheduler.cfc to handle scheduling a task from a component. It should be loaded into a persistent scope (Application scope preferably) and does require that the runTasks() method should be run from a ColdFusion template that is called every hour (probably by scheduled task).

I typically pass Scheduler into a component that needs to schedule a task. From there I can call the setTask() method of Scheduler.cfc with the following arguments:

  • Name: A unique name for the scheduled task.
  • ComponentPath: A path to the calling component (just used as a unique indicator for the component).
  • Component: The calling component, on which Scheduler will call a method (usually This).
  • MethodName: The name of the method in your component that Scheduler should call when it fires the task.
  • Interval: The interval Scheduler should use for calling the method with the following options.
    • once: Scheduler will call the task immediately, but only one time.
    • hourly: Scheduler will call the task every hour.
    • daily: Scheduler will call the task every 24 hours.
    • weekly: Scheduler will call the task once every 7days.
    • monthy: Scheduler will call the task once a month.
    • A number of seconds between each call.
  • Args: A structure of arguments that Scheduler should pass to the method that it is calling for this task.
  • Hours: A comma-delimited list of the hours during which the task can be called (on a 24 hours clock). So, if the value is "2,3" then Scheduler will only call the task during the hours of 2:00AM-2:59AM or 3:00AM-3:59AM.
Scheduler does require (the free) DataMgr component set in order to work. It will record the tasks that it is to run in a table called "schTasks" and record each time it calls a task in a table called "schActions". It will use DataMgr to create these table and can use any database that DataMgr support.

Scheduler.cfc is open source and free for any use. Feel free to download it and try it out.

Database Synchronization

In order to test some code for a recent project, I needed to have the data from the live site on my local computer. Of course, the live site is running MySQL which I don't have on my local computer.

By happenstance, I had just read a blog entry on transfering data from an Access to a MySQL database. It looked like a good solution (it uses DataMgr, it must be good!). Unfortunately, the solution listed only works if both databases have datasources on the same computer - not the case for me (though in retrospect I may have been able to set up a datasource on my local computer that pointed to the remote MySQL database).

In any event, I ended up building a tool to handle database synchronization. It will copy a database structure (and data unless you opt not to copy that) from one datasource to another.

This can be done one of two ways.

One: 

  1. Load the DataSynch.cfc and pass in the DataMgr for the source database.
  2. run the getXml() method of DataSynch on the desired tables.
  3. Take the resulting XML and pass it into the loadXML() of another DataMgr (this can be on another server running another database)

Two:

  1.  Load the DataSynch.cfc and pass in the DataMgr for the source database.
  2. Call the addDataMgr() to pass in a DataMgrto which structure (and data) should be copied (this can be done multiple times, creating multiple recievers for structure anddata)
  3. Call the synchTables() method of DataSynch on the desired tables to synchronize the database structure and data with the datasources of each DataMgr pass in via addDataMgr()

Note that this approach won't update any existing data. The synchronization is one-way only (from the source datasource outward).

One other advantage to this approach is that DataSynch will do its best to figure out foreign keys. Instead of copying foreign keys by value, it will copy them by look-up (making sure that the value matches the primary key of the related record with the same data).

So, if you have a "categories" table with a catid field as an identity primary key field, the values created in the new table may not match the value in the old table. DataSynch will create the table so that it uses the new value for the catid field of your products table (assuming both are being synchronized) instead of the old value.

To borrow Michael's example. Here is how it could be implemented usign DataSynch:

<!--- Create datamgr objects for each datasource --->
<cfset dmaccess = createobject("component","datamgr.DataMgr_Access").init("mydb_access")>
<cfset dmmysql = createobject("component","datamgr.DataMgr_MYSQL").init("mydb_mysql")>
<!--- Create the Synchronizer --->
<cfset synch = createobject("component","datamgr.DataSynch").init(dmaccess)>
<!--- Add the receiving datamgr --->
<cfset synch.addDataMgr(dmmysql)>
<!--- Synchronize the tables --->
<cfset synch.synchTables("contact,address,country,order,orderline,product,price")>

Because of the nature of DataMgr, any new tables or columns will automatically be created in receiving datasources. 

DataSynch is free and open-source. It requires DataMgr , which can be downloaded from the same page.

Switch between Client and Session Variables

Many developers often ask whether client variables or session variables are better. The answer to this question (as with many others) is "It depends". A common suggestion is to create some kind of wrapper for these scopes to allow easy switching.

The SessionMgr component provides this functionality. It will allow you to specify Client or Session scope when you intialize it. After that, you can have SessionMgr handle all of your Client/Session data. If you ever need to change which scope you use, just change the scope passed in and re-initialize SessionMgr - no need to change any other code.

SessionMgr will ensure proper locking and handle complex variables in Client scope, so you don't have to worry about those issues in your code.

[More]

BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.