Publishers of technology books, eBooks, and videos for creative people

Home > Articles

This chapter is from the book

Technical Fusebox Principles

If you are like us, you are probably thinking, "Okay, enough with the metaphors. Just what makes a Fusebox application in the real world?" Well, Fusebox has many technical aspects. Some people use all the ideas that have ever been labeled "Fusebox," whereas others only use some core components. For an application to be considered "Fusebox," it needs to exhibit all of the following characteristics:

  • Use the Fusebox method of file and directory organization.

  • Use the Fusebox core files.

  • Switch on a "fuseaction" to control the flow of the application.

  • Employ exit fuseactions (XFAs).

  • Have all fuses contain Fusedocs.

What happens if an application only uses some of the five characteristics? Usually we call it "my own version of Fusebox." It might work perfectly well for you, in your own development environment, for your own application, but what would happen if everyone wrote applications differently? You could not proclaim that you "knew Fusebox" because you write it differently from others. Shared applications could not be said to be "written in Fusebox." The power of a widely used framework and methodology is lost. Most industries standardize on a certain set of specifications. When that happens, the industry booms.

In Part 2, "Fusebox Coding," we will discuss these concepts in greater detail. Throughout the book, we will look at other ideas and practices that (although not all Fusebox developers use them) are considered Fusebox "best-practices." For the following sections, we will give you some background so that you understand how the whole picture fits together. Welcome to technical Fusebox. Put on your thinking caps!

File and Directory Organization

Any time you have more than a few files, it makes sense to reorganize them into a set of folders. Imagine you start a new school semester with a new laptop computer and you stick all your schoolwork in My Documents. After the first week, you have 10 files in there—a few Word documents, maybe an Excel spreadsheet of your class schedule, a Mind Map you created in Biology class (more on Mind Mapping in Chapter 14, "Construction and Coding"), and a handful of text files of notes. By next week, the number of files has doubled to 20. Sensing impending disaster by file overload, you wisely create folders for each of your classes and segregate your files. This works wonderfully through the end of the school year, but the next fall rolls around and you have all those folders from old classes—too many of them to quickly access folders for your current classes. You create a new folder called Freshman Year and move all your class folders from last year into that new folder. "Hey, I'm getting organized," you think. And you are right. Using folders to logically and physically separate files and subfolders is mandatory after you get a good number of them together.

What do we mean by "logically and physically"? Determining that you had too many files and putting them into separate folders is the physical separation. However, you didn't just create folders called folder1, folder2, and folder3 and randomly stick files in each one until they were equally full. You carefully named your folders Biology 101, Intro to Java, and Women's Studies and placed the files that you created for each of those classes into the corresponding folder. That is what is meant by "logically." Maybe your Intro to Java folder has twice as many files as Biology 101, but it makes sense to organize them according to class, not according to count.

The way we organize files and folders in Fusebox is nothing radical; it is just an extension of logical organization. Take, for instance, this site map of a couple HTML pages pictured in Figure 1.3.

Figure 1.3Figure 1.3 Simple HTML site map.

The site map in Figure 1.3 is an example of the directory structure shown in Figure 1.4.

Figure 1.4Figure 1.4 Simple HTML site directory structure.

If the web site shown in Figure 1.4 were a Fusebox application, then the subfolders customerservice, newsreleases, and catalog would be called circuits. On the most basic level, a Fusebox circuit is just a directory. In Windows terminology, there are folders and subfolders, but in Fusebox, there is only one name for any directory, regardless of how deeply nested it is. Frequently, Fusebox developers refer to a circuit as being a child circuit of another circuit. That just means that a circuit is nested inside another circuit.

Circuit Inheritance

Circuits are more than just a collection of files. When you (using your imagination) organized your freshman year class folders into one folder, what benefit did it bring? It reduced the number of folders in one location, but it also allowed you to apply security (if you had some important files in those folders) to one folder and have subfolders inherit the security settings from their parent folder. If you were to mark the folder Freshman Year as read-only, you would not be able to modify files in subfolders of Freshman Year. Imagine if this feature were not built into Windows; you would have to go through each file and modify its properties by hand, which would be quite time-consuming.

Fusebox has the same system of inheritance. In fact, it is even more powerful than Windows's version. Inside each circuit is a file called fbx_settings.cfm. Variables set in fbx_settings.cfm are available to the rest of the circuit, including any nested circuits. This means that you can apply security to check whether a user is logged into one circuit's fbx_settings.cfm file; then every file in that circuit can forego its own security validation. Because the files in the circuit that contain the secured fbx_settings.cfm inherit its settings, they cannot be accessed unless the user is logged in. We will further discuss the security of circuits and the fbx_settings.cfm file in later chapters.

Note

Inheritance is a term used in object-oriented programming, but in Fusebox, it basically means what it sounds like it means—a child circuit can use the variables from its parent circuit.

One good way to decide how to partition your application into circuits is to determine what parts of your application might be considered miniature applications. If we were building an e-commerce site (which we will do throughout Part 3, "Fusebox Lifecycle Process (FLiP)"), we would make the catalog/product viewer a circuit, as well as product reviews, checkout, customer service, search, and user management. Let's not forget about the home circuit, too. Every application needs a home circuit, which is used to tie all the circuits together into one application. Just as we applied a setting to fbx_settings.cfm and had all files in that circuit inherit those settings, we can apply settings to the home application, and every circuit in the entire application will inherit those settings.

File Organization

To review the terminology acquired thus far, a folder or directory in Fusebox is called a circuit. Any subfolders or subdirectories are said to be child circuits of the main circuit, which might be called the parent circuit. We would be remiss if we did not correct ourselves by replacing the term file with fuse. Often, ColdFusion files are called templates. Although the terms template, file, page, and fuse are relatively interchangeable, a file that is used in a Fusebox application carries two unique distinctions that any old ColdFusion template or file does not necessarily have: structured naming conventions and rules of use.

Fuses Versus Plain Templates

The first distinction is that Fusebox fuses follow a carefully defined yet extensible file-naming system. The content that can and should be contained in a fuse depends on its file prefix.

Table 1.1 File Prefixes for Fuses

Fuse Prefix

Fuse Type

Description

dsp_

Display

Only fuse type that can contain display, be it HTML, WML, or SOAP packets.

qry_

Query

Only fuse type that can perform database interactions, whether it be via <cfquery> or <cfstoredproc>. Always returns a recordset.

act_

Action

Any ColdFusion that does not fall into the previous two fuse types. Used primarily for data manipulation, form validation, and external systems interaction such as <cfmail>, <cfpop>, and so on.

lay_

Layout

These files assemble the page request for presentation to the user by handling headers, footers, and embedded fuseactions.

fbx_

Fusebox framework reserved fuse

The seven reserved Fusebox fuses use the fbx_ prefix. No user-defined files should use this prefix.


For the majority of files in your Fusebox application, exactly what code should get which of the preceding four fuse prefixes is a no-brainer. A fuse that runs a <cfquery> tag to get a recordset of all products in a database with prices over $30 would use the qry_ prefix (that is, qry_GetProducts.cfm). A fuse that loops over the recordset created by a qry_ fuse and displays each row formatted into a <table> would use the dsp_ prefix (that is, dsp_showProducts.cfm). A fuse that performs some complex validation based on the results of a user- submitted form would use the act_ fuse prefix (that is, act_validateProduct.cfm).

The fbx_ prefix is used for the reserved Fusebox framework files—those files that get the Fusebox job done by creating the inheritance structure, creating the central controller file, handling the layout and nesting of displays, and other tasks. For now, you should understand that nearly every fuse with an fbx_ prefix is not a file you create, although you do edit the contents of some of those files. We will talk more about fbx_ fuses starting in Chapter 3, "The Fusebox Framework."

The second distinction between a plain ColdFusion template and a Fusebox fuse is that each fuse should perform a discrete task. If a user is placing an order at the end of a checkout process, an example system has a number of tasks to perform, including checking the inventory, verifying and processing the credit card, updating the inventory, inserting the order into the database, sending an email to the shipping and accounting departments, sending an email to the customer, and finally displaying a "thank you" page to the customer. Each one of these steps would be a fuse. A good Fusebox developer would not combine these steps into one fuse, as tempting as it might be. A good rule of thumb is that most query and action fuses should fit on one screen in ColdFusion Studio.

Fuse Rules

A complete discussion of fuses and fuse content comes in Chapter 5, "The Fuses," but in the meantime, some hard and fast rules are available to keep in mind about what kind of code can and cannot be in certain fuse types.

For action fuses that use the act_ prefix, there can be no display. Whether the requesting client is a browser, a WAP phone, a web service, or a <cfmodule> tag, act_ fuses can only contain CFML logic and service calls. Use of <cfoutput> should be strictly limited to looping over query resultsets to perform manipulations of the data. In rare instances, an action fuse can perform database queries if, for example, you are trying to emulate the functionality of a stored procedure by running a query, looping through it, and performing subsequent queries based on the results of the first query. However, it would be wisest to <cfinclude> that nested query as a qry_ fuse. Here is an example of an action fuse that creates a name list:

<!--- act_nameBuild.cfm --->
<cfset nameList="">
<cfloop collection="#attributes.stName#" item="aName">
 <cfset nameList=ListAppend(nameList,aName,)>
</cfloop>

This code takes a structure of names (attributes.stName) and creates a list of the key values (nameList).

Like action fuses, query fuses that use the qry_ prefix cannot present display to the client. Query fuses should be as modular as possible to allow maximum reuse of the query. This means that the only code that should be contained in a qry_ fuse is the <cfquery> (or <cfstoredproc>) tag, a few <cfparam> tags to create defaults for the query, and maybe, just maybe, some looping afterward to rearrange the data output if it could not be accomplished in the query. Query fuses must always generate a recordset. It is also a good idea to name the recordset (via the name attribute in the <cfquery> tag) the same name as the fuse, minus the file extension and fuse prefix. For example, the fuse qry_customerDetails.cfm has a recordset called customerDetails:

<!--- qry_customerDetails.cfm --->
<cfparam name="attributes.customerID" default="0">
<cfquery name="customerDetails" datasource="#request.dsn#">
 SELECT * FROM customers
 WHERE customerID=#attributes.customerID#
</cfquery>

Unlike the previous two fuses, display fuses are the only type that can present output to the client. As a consequence, display fuses should contain a minimal amount of ColdFusion logic. Common ColdFusion tags that are used in display fuses include <cfoutput>, <cfloop>, <cfset>, <cfparam>, and <cfif>. Of course, you are free to use whatever tags are necessary to get the job done for a fuse, but if you find yourself writing blocks of ColdFusion code, it should probably be moved into an action fuse. Here is an example of a display fuse:

<!--- dsp_customerDetails.cfm --->
<table border="1">
<tr>
 <td>Name</td><td>Managers</td>
</tr>
<cfoutput>
<tr>
 <td>#customerDetails.name#</td><td>#nameList#</td>
</tr>
</cfoutput>
</table>

Because Fusebox encourages different kind of code to be created in different fuse types, the result is a complete separation of display from logic. Due to this separation, debugging is easier, development is faster, and the entire application has increased cohesion, bringing many benefits, discussed further in Chapter 2, "Is Fusebox Right for You?"

Note

Cohesion relates to how well a fuse, fuseaction, or circuit performs exactly one function or achieves a single goal.

The Fusebox Core Files

Applications that were developed in early versions of Fusebox consisted of a "federation" of circuits; in a metaphysical sense, each circuit lived in its own world, only vaguely aware of ties to other circuits. Circuits did not share the benefits of inheritance. To simulate inheritance, it was commonplace to tie circuits together, which reduced modularity. Extended Fusebox (XFB), created by Hal Helms, was developed to solve these problems. XFB gave circuits complete independence from each other but also created a true structure among the circuits, uniting them into one "wrapper" application. In the latest release (version 3), Fusebox builds on XFB by using a formalized set of core files that sets up a structure for the circuits, creates the system of inheritance and settings, provides for the switch-case that controls the application flow, and controls layouts and nested displays. Each core file uses the fbx_ prefix.

Table 1.2 The Core Files

Processing Order

Filename

Description

1

fbx_fusebox30_CFxx.cfm

Commonly referred to as "the core file," this file sets up the entire Fusebox framework that calls the other core files and fuses. The xx denotes ColdFusion version- specific files.

2

fbx_circuits.cfm

Establishes the relationship of circuits to each other by "registering" circuits with the application.

3

fbx_settings.cfm

One per circuit, this file allows circuit-wide (and child circuit) settings and inheritance.

4

fbx_switch.cfm

Little more than a <cfswitch>/<cfcase> statement, this file controls the application flow, based on the fuseaction.

5

fbx_layouts.cfm

One per circuit, this file controls which layout file to use for the request.

N/A

fbx_savecontent.cfm

Fusebox relies on <cfsaveco-tent>, introduced in CF5. This file emulates the native tag's functionality for people using versions of ColdFusion earlier than version 5.


All these files might sound confusing at this point, but fear not; they will be discussed fully in Part 2.

Controlling the Flow

Unfortunately, we both find ourselves flying more than we would like. Last year, we flew cross-country at least a half-dozen times and over the course of one two-month period, we flew nine times combined. But out of all those frequent-flyer miles accumulated, few were on delayed flights. We never got "bumped," and for the most part, the tickets were inexpensive and we were able to get on the flights we wanted, even on short notice.

But if this were 1950, it's unlikely we would have had such success. Back then, airlines were frequently late, ticket prices were higher, and direct flights were the only way you could fly. If you wanted to go from Los Angeles to New Orleans, you had to wait for a long time for a direct flight, or take any number of flights, each one quite expensive, and there was little guarantee that you would not miss a connecting flight. Airlines were operating on a point-to-point system but recognized that something needed to change to allow an increase in cities served, passenger volume, and profits realized. In the early 1960s, United Airlines created the world's first hub-and-spoke system of airports, linking western U.S. routes with eastern U.S. routes via major connecting hubs. At the time, the other major airlines nay-sayed this model, claiming it would destroy the industry. However, after a few short years, all the airlines had their own hub-and-spoke systems.

The system used by the airline industry these days is similar to the system used by Fusebox. In addition, the system used by the airline industry up until the early 1960s is similar to most non-Fusebox ColdFusion applications. Non-Fusebox ColdFusion applications tend to rely on page-to-page links. A form that is collecting information submits to a form-processing page. The form-processing page has a "thank you" section at the bottom. In Fusebox applications, every page links and submits to one controller file, which then processes the user's request. If you are on a page with a form, it submits to the Fusebox, which then passes control to the form-processing page. Because all links, form actions, JavaScript redirects, <cfmodule>, and <cflocation> tags go through the Fusebox, the hub-and-spoke system is duplicated in web applications.

Figure 1.5 shows a comparison of point-to-point versus hub-and-spoke systems in airlines and web applications. Point-to-point models can work well in small sizes, but they must be upgraded to hub-and-spoke systems to handle increases in traffic and complexity. This hub-and-spoke is most obvious in the "controller file," called fbx_switch.cfm.

Figure 1.5Figure 1.5 Point-to-point versus hub-and-spoke.

A Look at fbx_switch.cfm

So what makes a Fusebox application actually run? In ColdFusion, you point a browser to a .cfm template, and the web server picks up the request and passes it off to ColdFusion Server. From there, ColdFusion processes the Application.cfm file—including any files referenced—and then processes the page, again including any files needed. When ColdFusion is done, the page goes back to the web server and you get your page. But in Fusebox, instead of pointing to individual fuses, you always point to one file: the default web document, which is usually index.cfm.

This index.cfm file includes the core file (fbx_fusebox30_CFxx.cfm), which runs code to set up the Fusebox framework, including <cfinclude>ing the fbx_settings.cfm fuses from the circuits. Next, it includes the fbx_switch.cfm for the target circuit, and then finishes off by handling any layouts to be used. But again, where do you stick your code—the stuff that actually does something?

All the fuses—your code—gets <cfinclude>d from the fbx_switch.cfm file. Here is an example fbx_switch.cfm file:

<cfswitch expression = "#fusebox.fuseaction#">
 <cfcase value="main">
  <cfinclude template="act_ReadFiles.cfm">
  <cfinclude template="act_MakeFileIntoStruct.cfm">
  <cfinclude template="dsp_map.cfm">
 </cfcase>
 <cfcase value="admin">
  <cfinclude template="act_getAllDirs.cfm">
  <cfinclude template="dsp_admin.cfm">
 </cfcase>
 <!--- ... other <cfcase> tags here... --->
</cfswitch>

That is all there is to an fbx_switch.cfm file. We will do a little more explaining later, but for now, just think of the Fusebox as a big switchboard, running different code depending on a user-supplied variable.

Fuseactions Control Flow

If the user wants your application to run the "main" fuseaction, the request that follows will do it. The <cfswitch> statement switches on fusebox.fuseaction, which is passed on the URL string like this:

<a href="index.cfm?fuseaction=home.main">

or in a hidden form field like this:

<input type="Hidden" name="fuseaction" value="home.main">

or in a <cflocation> tag like this:

<cflocation url="index.cfm?fuseaction=home.main">

Being an astute reader, you are probably wondering where fusebox.fuseaction comes from if we are only passing around url.fuseaction and form.fuseaction. Remember how we mentioned that the core file sets up the Fusebox framework? One job that the core file has is to take any incoming Fuseaction variable, no matter what the scope is, and copy the second part of it (after the dot) into a variable called fusebox.fuseaction. Referencing fusebox.fuseaction is similar to referencing ListLast(url.fuseaction, "."). Instead of needing two <cfswitch> blocks, one switching on url.fuseaction and the other switching on form.fuseaction, we can have one that does the job no matter what scope it is. It even works if you pass in the variable fuseaction in a <cfmodule> tag:

<cfmodule template="index.cfm" fuseaction="home.main">

Now we have four different ways to call a fuseaction, and only one set of code to handle all those requests.

Every time index.cfm (or whatever your default web document is) is run, it expects the variable fuseaction to be passed in. However, sometimes that variable is not passed in. This case occurs when a user types in something like this:

http://www.thirdwheelbikes.com/

There is no ?fuseaction=main.welcome in that URL, so Fusebox needs a default fuseaction. Default fuseactions are key to understanding how a Fusebox application responds. You set a default fuseaction in the root fbx_settings.cfm file for your application like this:

<cfparam name="attributes.fuseaction" default="main.welcome">

Now for every request of the Fusebox application, we can be assured that the variable attributes.fuseaction is available. Now the system can respond appropriately. Now that a fuseaction is known, how does the framework know which circuit to go to?

Which Circuit Runs?

The fuseaction variable always contains two values in what we refer to as a compound fuseaction. We know that the second part of the fuseaction is the actual fuseaction; it determines which set of fuses is run for a given user request. Imagine that a user requests the order.basket fuseaction like this:

<form action="index.cfm?fuseaction=order.basket" method="post">

We know that the basket fuseaction will be run, but we also know that the fbx_switch.cfm file in the order circuit should handle the request for that fuseaction. Using this compound fuseaction, we can specify any fuseaction in any circuit to be run. The first part is the circuit, and the second part is the fuseaction.

Imagine that a customer is buying a product on your e-commerce site. Halfway through the checkout process, she decides to review your company's privacy policy. All of the fuses in the checkout process are in a circuit called checkout, which is off the root of the site. The page that she wants to see, dsp_privacy.cfm, is in the policy circuit, also off the root. How would you write the link from the checkout page to the privacy policy fuseaction? How about this:

<a href="index.cfm?fuseaction=policy.privacy">

The first file that runs is index.cfm, which is the file that the link requested. The Fusebox framework file (fbx_fusebox30_CFxx.cfm) is included from the index.cfm page. The core file establishes the framework and calls the fbx_switch.cfm file from the policy circuit, which looks like this:

<cfswitch expression = "#fusebox.fuseaction#">
 <cfcase value="privacy">
  <cfinclude template="dsp_privacy.cfm">
 </cfcase>
 <cfcase value="security">
  <cfinclude template="dsp_security.cfm">
 </cfcase>
</cfswitch>

The dsp_privacy.cfm file is processed because the second part of the fuse-action (the part after the dot) matches the <cfcase value="privacy"> tag. After the Fusebox core file finishes processing, your display file is presented to the customer, who is satisfied with the privacy of your site and happily completes her purchase.

Exit Fuseactions

By now you might be imagining the fbx_switch.cfm as something of a roadmap for a circuit. In one easy-to-read page, it shows every possible action that can occur, every possible page that can be displayed, along with each fuse used to accomplish the job. Each fuse is specialized and knows its job well ("I insert a new customer into the database." "I display the privacy policy," and so on). But because each fuse contains links, form actions, and <cflocation>s, each fuse must know where those links go—what the circuits are called and what fuseactions are in which circuits. That is a tall task for a measly little fuse. Fuses should be designed so that they contain as few dependencies on the rest of the application as possible. It is with this in mind that we use XFAs rather than hard-coded fuseactions. Here is a sample XFA:

<form action="index.cfm?fuseaction=#xfa.submit#" method="post">

It's not too complicated, huh? XFAs are nothing more than fuseaction values as variables. They are set in the fbx_switch.cfm just before <cfinclude>ing the fuse:

<cfcase value="privacy">
<cfset xfa.continue="policy.payments">
<cfset xfa.back="policy.security">
<cfinclude template="dsp_privacy.cfm">
</cfcase> 

This allows the fbx_switch.cfm file to control where each fuse it calls is allowed to go next. In the preceding case, the file dsp_privacy.cfm has two links: most likely a forward and backward button to guide an inquisitive customer through the array of site policies. Because each fuse should not be required to be aware of its surroundings, its own exit locations must be dynamic. This becomes especially important if a fuse links to another circuit. If the target circuit is moved or no longer exists, the fuse does not need to be updated—only the fbx_switch.cfm file does. XFAs also promote reusability of code. By using XFAs, we can write the fuse once but use it in different locations, and the links can go to different places. XFAs are completely discussed in Chapter 6, "Exit Fuseactions."

Fusedocs

Because an individual fuse is supposed to be designed and coded as if it were unaware of the larger application using it, a formalized method needs to exist to describe everything that the fuse can assume and everything that it cannot. By carefully documenting every variable that a fuse is allowed to reference (#variable#) and every variable that a fuse is supposed to create (<cfset foo="bar">), we can be assured minimum coupling by our most discrete units.

A Fusedoc appears at the top of every fuse. Using XML, a Fusedoc describes all the variables that the fuse needs to get its job done as well as all the variables that it needs to create. It identifies the scope, structure, mask, and potential values of those variables. Following is an example Fusedoc. It is for an action fuse that deletes a task. Do not worry if all the code is foreign to you. A full explanation follows the listing.

<!--- 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fusedoc SYSTEM "http://fusebox.org/fd4.dtd">
<fusedoc fuse="act_deleteTask.cfm" language="ColdFusion" 
specification="2.0">
 <responsibilities>I delete a task and any user_tasks associated with 
 that task.</responsibilities>
 <properties>
  <history author="Nat Papovich" date="08/10/2001" email="nat@fusium.com" 
  role="Architect" type="Create"/>
 </properties>
 <io>
  <in>
   <list name="taskID" scope="attributes" optional="False"/>
  </in>
  <out>
   <boolean name="success" scope="variables"/>
  </out>
 </io>
</fusedoc>
--->

If you have not picked up XML yet, do not fear. Fusebox.org has tag chooser and tag insight files available to plug into ColdFusion Studio, which greatly simplifies creating Fusedocs:

<fusedoc fuse="act_deleteTask.cfm" language="ColdFusion" 
specification="2.0">

Starting at the top (below the mumbo about XML versions and doctypes), the tag <fusedoc> wraps the whole Fusedoc. Anything that falls within the opening and closing <fusedoc> tag is considered part of the Fusedoc. The <fusedoc> tag contains a number of attributes, including the name of the fuse:

 <responsibilities>I delete a task and any user_tasks associated with 
 that task.</responsibilities>

Next, the <responsibilities> tag describes what this fuse accomplishes, in plain English:

  <history author="Nat Papovich" date="08/10/2001" 
  email="nat@fuseboxtraining.com" role="Architect" type="Create"/>

The <history> tag is like a stamp of who did what when to this fuse. This example shows the creator of the fuse:

 <io>
  <in>
    <list name="taskID" scope="attributes" optional="False"/>
  </in>
  <out>
    <boolean name="success" scope="variables"/>
  </out>
 </io>

The final section describes the input and output (<io>) of the fuse: what variables are coming in and what variables need to go out. This example shows that a variable called taskID in the attributes scope is available and that a variable called success in the local variables scope should be created.

We now have an understanding of the benefits that Fusedocs offer to our applications. If you are uncertain about the XML format in which to write Fusedocs, don't worry; http://www.fusebox.org has a free Fusedoc toolkit that plugs into ColdFusion Studio and makes writing Fusedocs a snap.

That about covers the basics of Fusebox except for one thing—a common scope for variables that users can modify.

A Common Scope

One final characteristic that is fundamental to Fusebox is a shared scope for incoming variables. We have already mentioned how the Fusebox core file copies the second part of the incoming form, url, or attributes-scoped variable fuseaction into a variable called fusebox.fuseaction. That is how the fbx_switch.cfm knows which <cfcase> tag to run for the request. However, the core file also copies all url and form-scoped variables to the attributes scope. This feature is commonly referred to as "form URL to attributes" because it was originally accomplished using a custom tag created by Steve Nelson called formurl2attributes.cfm.

Having a single scope to refer to user-defined variables means that portions of Fusebox applications suddenly become incredibly reusable. Imagine you have a <cfquery> tag like this:

<cfquery name="customerDetail" datasource="#request.DSN#">
 SELECT * FROM CUSTOMERS
 WHERE customerID=#form.customerID#
</cfquery>

This bit of code is saved into a file called qry_customerDetail.cfm, but it can only be used if the previous page contains a form with a field named customerID. If you also want to be able to pass the customerID variable on a URL string, you would have to rewrite that query file to be something like this:

<cfquery name="customerDetail" datasource="#request.DSN#">
 SELECT * FROM CUSTOMERS
 <cfif IsDefined("form.customerID")> 
 WHERE customerID=#form.customerID#
 <cfelseif IsDefined("url.customerID")>
 WHERE customerID=#url.customerID#
 </cfif>
</cfquery>

The code is generally the same as the earlier code, but it now takes into consideration customerID coming from two different scopes. This is a kludge. What happens now if you want to be able to use this query file from <cfmodule>? You would have to add yet another <cfelseif> to the growing code to accommodate. In addition, you would have to add this chain of <cfif>s to every query you wanted to reuse.

Because URL, form, and attributes scope are all available for users to write to, Fusebox uses the attributes scope as a catch-all for those scopes. Early in the processing of the Fusebox core file, all variables in the form and URL scopes are copied to the attributes scope. Now you can write the same query like this:

<cfquery name="customerDetail" datasource="#request.DSN#">
 SELECT * FROM CUSTOMERS
 WHERE customerID=#attributes.customerID#
</cfquery>

By using one scope to reference all incoming variables, our applications gain a huge boost in reusability. We are no longer concerned with exactly how a request is being made. We do not need to differentiate between a <cfmodule> request and a form post. Reusability rules.

Peachpit Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from Peachpit and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about Peachpit products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites; develop new products and services; conduct educational research; and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email ask@peachpit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by Adobe Press. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.peachpit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020