| | 1 | [[TOC(heading=Training Section Contents, Training*)]] |
| | 2 | |
| | 3 | = Section 7: Crossing the Generational Gap = |
| | 4 | |
| | 5 | In this next exercise, we'll be creating a searchable interface for our plants. If you've been paying attention, you know that for every user interaction we pretty much need some Model-Glue XML, a Controller, a Controller Method and a View. While all these pieces are important for consistency and for proper standardization, manually creating all of these pieces can add friction into the development process. Model-Glue 3 introduces Event Generation, an automated way of creating the boilerplate code for you. |
| | 6 | |
| | 7 | == Exercise: Event Generation == |
| | 8 | |
| | 9 | 1. First, let's visit a fictitious Event Handler: |
| | 10 | |
| | 11 | [http://localhost/PlantOMatic?event=Plant.Search http://localhost/PlantOMatic?event=Plant.Search] |
| | 12 | |
| | 13 | ''We'll get an error telling us no event named "Plant.Search" is defined.'' |
| | 14 | |
| | 15 | 2. Next, open /PlantOMatic/config/ColdSpring.xml and find the definition for modelglue.modelGlueConfiguration. Then Locate the setting for generationEnabled and change it from: |
| | 16 | |
| | 17 | {{{ |
| | 18 | |
| | 19 | <property name="generationEnabled"><value>false</value></property> |
| | 20 | |
| | 21 | }}} |
| | 22 | |
| | 23 | To: |
| | 24 | |
| | 25 | {{{ |
| | 26 | |
| | 27 | <property name="generationEnabled"><value>true</value></property> |
| | 28 | |
| | 29 | }}} |
| | 30 | |
| | 31 | |
| | 32 | ''Now, each time you request an undefined Model-Glue Event Handler, Model-Glue will generate Model-Glue XML definitions, Controller bodies and methods and views. This is a powerful feature and should only be enabled when you wish to generate new code. Model-Glue does not distinguish typos from intent, so be careful!'' |
| | 33 | |
| | 34 | 3. Simply refresh the page, and Model-Glue will generate a bunch of free code to support our new Plant.Search functionality |
| | 35 | 4. Open /PlantOMatic/config/ColdSpring.xml and change the generationEnabled property back to false |
| | 36 | |
| | 37 | == Event Generation Results == |
| | 38 | |
| | 39 | Below is a list of the changes that happened by Model-Glue Event Generation. Take a moment to examine these files to better understand what was generated for you. After you finish, we'll need to clean up a few items to conform to our naming scheme. |
| | 40 | |
| | 41 | == New Files: == |
| | 42 | |
| | 43 | /PlantOMatic/views/Plant/Search.cfm |
| | 44 | |
| | 45 | == Changed Files: == |
| | 46 | |
| | 47 | /PlantOMatic/config/ModelGlue.xml |
| | 48 | * New Event Handler: Plant.Search |
| | 49 | |
| | 50 | /PlantOMatic/controller/PlantController.cfc |
| | 51 | * New Method: Search() |
| | 52 | * '' '''Note:''' if !PlantController did not already exist, Model-Glue would have created it for us '' |
| | 53 | |
| | 54 | |
| | 55 | == Event Generation Clean Up == |
| | 56 | |
| | 57 | 1. Delete These Files |
| | 58 | |
| | 59 | /PlantOMatic/views/Plant (the whole directory) |
| | 60 | |
| | 61 | 2. '''Update The Model-Glue XML Event Handler for Plant.Search''' |
| | 62 | |
| | 63 | {{{ |
| | 64 | |
| | 65 | <event-handler name="Plant.Search" type="templatedPage"> |
| | 66 | <broadcasts> |
| | 67 | <message name="needPlantSearch" /> |
| | 68 | </broadcasts> |
| | 69 | <views> |
| | 70 | <include name="Primary" template="SearchResults.Plant.cfm"> |
| | 71 | <value name="xe_PlantSearchForm" value="Plant.Search" /> |
| | 72 | </include> |
| | 73 | <include name="Secondary" template="SearchForm.Plant.cfm"> |
| | 74 | <value name="xe_HandleSubmitForm" value="Plant.Search" /> |
| | 75 | </include> |
| | 76 | </views> |
| | 77 | </event-handler> |
| | 78 | |
| | 79 | }}} |
| | 80 | |
| | 81 | 3. Update the Search method in /PlantOMatic/controller/PlantController.cfc |
| | 82 | |
| | 83 | {{{ |
| | 84 | |
| | 85 | <cffunction name="search" output="false" access="public" returntype="void" hint="I search plants"> |
| | 86 | <cfargument name="event" type="any" /> |
| | 87 | <cfset var SearchFilter = arguments.event.makeEventBean( "PlantOMatic.model.PlantFilter", "CommonName,Family,ScientificName,Symbol" ) /> |
| | 88 | <cfset arguments.event.setValue( "PlantList", beans.plantManager.search( SearchFilter ) ) /> |
| | 89 | <cfset arguments.event.setValue( "PlantFilter", SearchFilter ) /> |
| | 90 | </cffunction> |
| | 91 | |
| | 92 | }}} |
| | 93 | |
| | 94 | 4. Open /PlantOMatic/views/SearchForm.Plant.cfm and prepend the following: |
| | 95 | |
| | 96 | {{{ |
| | 97 | |
| | 98 | <cfsilent> |
| | 99 | <cfimport prefix="uform" taglib="/PlantOMatic/uniform" /> |
| | 100 | <cfset event.copyToScope( variables, "CFUniformConfig,PlantFilter,xe_HandleSubmitForm" ) /> |
| | 101 | <cfset handleSubmitForm = event.linkto( xe_HandleSubmitForm ) /> |
| | 102 | <cfset bean = PlantFilter /> |
| | 103 | </cfsilent> |
| | 104 | |
| | 105 | }}} |
| | 106 | |
| | 107 | 5. Open /PlantOMatic/views/SearchResults.Plant.cfm and prepend the following: |
| | 108 | |
| | 109 | {{{ |
| | 110 | |
| | 111 | <cfsilent> |
| | 112 | <cfset event.copyToScope( variables, "PlantList,xe_doPlantSearchForm,xe_PlantSearchForm" ) /> |
| | 113 | <cfset linkSearchForm = event.linkTo( xe_PlantSearchForm ) /> |
| | 114 | </cfsilent> |
| | 115 | |
| | 116 | }}} |
| | 117 | |
| | 118 | == Putting It All Together == |
| | 119 | |
| | 120 | Refresh the Plant.Search event and take a look at your handiwork. We've used the fancy Model-Glue Event Generation to jump start our development process. Your screen should look like the figure below: |
| | 121 | |
| | 122 | [[Image(training07-1/png, nolink)]][[BR]] |
| | 123 | '' Plant Search Results '' |
| | 124 | |
| | 125 | * This functionality uses several good object oriented techniques. Take a look at the source code for both views and notice how little business logic there is. |
| | 126 | * Review the Search method of the !PlantController also to see which portions of processing belong inside the view. |
| | 127 | * Lastly, examine how the the /PlantOMatic/model/PlantFilter.cfc works with the /PlantOMatic/model/PlantManager.cfc to compartmentalize the business logic. Proper Encapsulation Leads To Maintainable Software! |
| | 128 | * For extra points, try using a few characters with a trailing asterisk (as shown above) in the Scientific Name Text Input in the search form. Then trace how this functionality works. |
| | 129 | |
| | 130 | ---- |
| | 131 | |
| | 132 | Back: [wiki:Training/Section06 Training Section 6: Flow and Dependencies] |
| | 133 | |
| | 134 | Next: [wiki:Training/Section08 Training Section 8: Extending Model-Glue] |