A quick overview of routing in Wheels 2.x
A quick overview of routing in Wheels 2.x
Today sees a maintenance release for the 2.x series.
Download 2.0.1 today to fix the following:
dbname
in cfdbinfo
calls when using custom database connection string – #822 [Per Djurner]humanize()
function – #663 [Chris Peters, Per Djurner, kmd1970]rel
attribute for stylesheetlinkTag()
– #834 [Michael Diederich]NULL
value from a query with NULL support enabled no longer throws an error – #834 [Michael Diederich]Today sees a maintenance release for the 1.4.x series. Please note that as 2.0 is now released, future updates to the 1.x branch will be limited to essential bug fixes only.
Download 1.4.6 today to fix the following:
Ok, it’s been a while, but *finally*, CFWheels 2.0 has gone gold!
install cfwheels
(Just downloads and unzips)wheels new
install cfwheels-cli
)Make sure to check the “Breaking Changes” section, and please report any bugs.
Needless to say, this has been a massive undertaking with over 1000 commits, and over a year in the making. The core team wishes to thank all the many contributors, testers, and well, just users of the framework. We think we’re in a pretty strong place to move forward with loads more exciting things in the future.
For a comprehensive list of changes, check the Changelog, but for a quick summary:
Need help upgrading? Check the upgrade notes, and feel free to post questions to the Google Group, or hit us up on the #cfwheels room on the CFML Slack Channel
It’s been about a year in the making, and well over 1000 commits, but the beta for 2.0 has now arrived! We’re still catching up on the main documentation as there’s so much to cover in this release, so bear with us a bit! In the meantime, please do check it out:
install [email protected]
(Just downloads and unzips)wheels new
install cfwheels-cli
)Make sure to check the “Breaking Changes” section below, and please report any bugs.
There will be some more posts coming up covering some of the big topics like routing & migrations, but in the meantime:
install upgradeadvisor
)select=false
to property()
to not include a calculated property by default in SELECT clauses – #122 [Adam Chapman, Per Djurner]returnIncludedAs
and returnIncluded
arguments to properties()
for returning nested properties – [Adam Chapman]updateProperty()
with dynamic argument, e.g. updateProperty(firstName="Per")
– [Per Djurner]update(transaction=false)
– #654 [Adam Chapman]isPersisted()
and propertyIsBlank()
methods – #559 [Chris Peters]timeStampMode
setting ("utc"
, "local"
or "epoch"
) for the createdAt
and updatedAt
columns – [Andy Bellenie]handle
argument to finders now set the variable name for the query so it’s easier to find in the debug output – [Per Djurner]where
argument – #483 [Per Djurner]lowerCaseTableNames
, to always lower case table names in SQL statements – [Per Djurner]flashMessages()
are now in default layout.cfm – #650 [Tom King]textField()
, passwordField()
and hiddenField()
– #633 [Per Djurner, Chris Peters]method
argument in buttonTo()
helper – #761 [Adam Chapman]ram://
resources to sendFile()
– #566 [Tom King]sendMail()
so that it can return the text and/or html content of the email – #122 [Adam Chapman]renderWith()
can now set http status codes in header with the status
argument – #549 [Tom King]humanize()
keep spaces in input – #663 [Per Djurner, Chris Peters]validatePresenceOf()
with default on update – [Andy Bellenie]box.json
files and are displayed in debug area #68 [Tom King]box.json
now available in application.wheels.pluginMeta
scope #68 [Tom King]http_x_forwarded_for
when doing maintenance mode exclusions – [Per Djurner]urlrewrite.xml
to support Tuckey URL rewriting with Commandbox #649 – [Tom King]beforeAll()
, afterAll()
, packageSetup()
, packageTeardown()
methods to test framework #651 – [Adam Chapman]errorEmailFromAddress
and errorEmailToAddress
config settings – #95 [Andy Bellenie, Tony Petruzzi, Per Djurner]assert()
in tests – [Per Djurner]/app/
mapping pointing to the root of the application – [Per Djurner]processRequest()
function that simplifies testing controllers – [Per Djurner]design
mode – [Per Djurner]cacheRoutes
setting – [Per Djurner]cacheFileChecking
and cacheImages
settings are now turned off in development mode – [Per Djurner]includeErrorInEmailSubject
setting – [Per Djurner]allowEnvironmentSwitchViaUrl
– #766 [Tom King]events/functions.cfm
file has been moved to global/functions.cfm
.models/Model.cfc
file should extend wheels.Model
instead of Wheels
(models/Wheels.cfc
can be deleted).controllers/Controller.cfc
file should extend wheels.Controller
instead of Wheels
(controllers/Wheels.cfc
can be deleted).init
function of controllers and models should now be named config
instead.modelRequireInit
has been renamed to modelRequireConfig
.cacheControllerInitialization
has been renamed to cacheControllerConfig
.cacheModelInitialization
has been renamed to cacheModelConfig
.clearServerCache
has been renamed to clearTemplateCache
.updateProperties()
method has been removed, use update()
instead.mapper()
.confirm
and disable
have been removed from the link and form helper functions (use the JS Confirm and JS Disable plugins to reinstate the old behaviour).createdAt
, updatedAt
) is now in UTC by default (set the global timeStampMode
setting to local
to reinstate the old behaviour).where="x=''"
becomes where="x IS NULL"
).<img src="x">
instead of <img src="x" />
).encode
argument to mailTo
now encodes tag content and attributes instead of outputting JavaScript.field-with-errors
instead of fieldWithErrors
).renderPage
function has been renamed to renderView
.One of the nicest things about CFWheels 2.x is the tighter integration with command-line tools such as Commandbox. We can take advantage of the new testing suite JSON return type and the new CFWheels CLI in Commandbox 2.x to easily build a Travis CI test. It’s perhaps easiest to just show the .travis.yml
file – this goes in the root of your gitHub plugin repository, and once you’ve turned on testing under Travis.org, will run your test suite on every commit.
In sum, this:
Naturally, you could do more complex things with this, such as multiple CF Engines, and maybe even multiple CFWheels versions, but for a quick setup it’s a good starting point!
Hands up if you’ve ever found a bug in your application..
Upgrades, feature enhancements and bug fixes are all part of the development lifecycle, but quite often with deadlines, it’s difficult to manually test the entire functionality of your application with every change you make. What if there were an automated way of checking if that change you’re making is going to break something?
In the past, writing an automated test suite against your application meant downloading, configuring and learning a completely separate framework. To help address this issue, CFWheels includes a small, simple, yet powerful testing framework. Whilst this has been part of the core in 1.x, it’s never been properly documented, and with 2.x, we’ve introduced lots of new features to help test your application.
Here is a simple example of unit testing a helper function that adds two numbers.
The same idea can be applied to just about any function in your application. Here are some of the things you might want to test:
Once you have a comprehensive test suite, you can make code changes with a greater sense of confidence that you have not introduced bugs (regressions) into your application. This gives you the opportunity to implement automated test runners into a continuous integration platform like Jenkins or TravisCI.
Don’t just take our word for it.. well actually, DO take our word for it as CFWheels 2.0 has been developed exclusively against the inbuilt test framework.
For those of you who have been using the testing framework in your CFWheels 1.x applications, the 2.0 framework has a number of improvements around setup, teardown and a super handy processRequest
function:
You get lots of handy information back, like the body
contents, the status
code of the request, and more.
Want to get going? Check the comprehensive tutorial at guides.cfwheels.org
With CFWheels 2.0 beta around the corner, it’s time to have a cold hard look at the CFWheels plugin ecosystem.
With 2.x, we’ve taken the opportunity to modernise how we deal with plugins. If you’re a plugin author who has previously released something for 1.x, you’ll be pleased to hear there aren’t that many changes required to get your plugins playing nicely with 2.x, but it’s definitely a good time to revisit what you’ve got out there.
One of the main problems we had previously was a lack of a centralised repository of CFwheels plugins. The old system relied on a bit too much manual updating, and over time got a little long in the tooth. So now, all plugins should be added to forgebox.io, specifically in the CFWheels Plugins
category. If you go and have a look now, you’ll see a few added by the core team as examples. Adding your plugin shouldn’t be too much hard work, but it’s definitely worth setting yourself up properly to publish to forgebox automatically via the commandline. There’s an extensive tutorial over at guides.cfwheels.org which we recommend you follow. In short, you ideally need a properly configured box.json
file and for your plugins to use git tagged releases (ideally). If you’ve not installed commandbox and the CFWheels CLI, now is definitely the time to try it!
Once your plugin is in the forgebox system, other CFWheels users can install your plugin with a single CLI command: install slugName
; If they’ve got the CFWheels CLI installed, it will automatically create appropriate .zip
files with the correct version number (which you’ll have set in box.json
) too. They’ll also be able to view all existing plugins with wheels plugins list
making it extra quick to find the plugin they need. Dependencies are then tracked in that user’s box.json
file, so they can even distribute an app without your plugin, and then simply run install
to go and download the correct version later: they can even update to the latest version of your plugin via the CLI too, or freeze it to a specific version.
One of the nice new features of 2.x is the automatic java library mappings which plugins can now take advantage of. Previously, you had to rely on the developer to manually add an entry into this.javaSettings.loadpaths
if your plugin required use of a .class
or .jar
file. Now, we scan the plugin folders on startup, and automatically add any folders which contain .jar
or .class
files. One less step for configuration! You can see an example of this in the CFWheels bCrypt plugin, which adds a quick wrapper around the bCrypt java class.
In a previous post, we talked about the new embedded documentation: plugins can now take advantage of this. For plugin authors, we’re recommending you comment all public functions – here’s a quasi code example below.
The important part is the [section: Plugins]
and [category: Plugin Name]
part, which will automatically sort your functions in the correct place in the internal documentation. It’s a good habit to get into, and will help other users of your plugin too.
Don’t forget to write some unit tests too (hey, don’t we all do TDD?); there’s been some changes to the test suite in 2.x, and writing unit tests is loads easier. More to follow on:
One of a developer’s biggest time sinks is coming up with and writing accurate and engaging documentation. Even if it’s an internal project with.. well, just you… it’s still incredibly valuable to have: coming back to projects a few months or even years later can often lead to a bit of head scratching and screams of “why?”, especially with your own code.
Whilst we’re not promising that CFWheels will write all your documentation for you, we have put some tools in place to hopefully make the process a little less painful. With a small amount of adjustment in how you document your core functions, documentation doesn’t necessarily have to be such a time consuming process.
The first thing to notice is the new ‘[View Docs]’ link in the debug section in the footer:
Following that link leads you to the internal documentation. This is a dynamically created set of documention created via javaDoc commenting in the main CFWheels Core.
The three column layout is designed to allow for quick filtering by section or function name. On the left are the main CFWheels core categories, such as Controller and Model functions, which are then broken down into sub categories, such as Flash and Pagination functions etc. Clicking on a link in the first column will filter the list in the second and third columns with all the functions which match (including child functions of that category).
Filtering by function name is made simple by a “Filter as you type” search field in the second column, so getting to the right function should be very quick.
The third column contains the main function definition, including tags, parameters and code samples.
Each function in the core is now appropriately marked up with javaDoc style comments. This, combined with getMetaData()
allows us to parse the markup into something useful.
The [section]
and [category]
tags categorise the function as appropriate, and the @html
part describes the function’s parameter. The additional parameter data, such as whether it’s required, type and any defaults are automatically parsed too. This results in a display like:
Any function which is available to Controller.cfc
or Model.cfc
is automatically included; if there’s no javaDoc comment, then they’ll appear in uncategorized
. But of course, there’s nothing stopping you creating your own [section]
and [category]
tags, which will then automatically appear on the left hand column for filtering: you’re not restricted to what we’ve used in the core.
As an example, if you wanted to document all your filters, you might want to have a [section: Application]
tag, with [category: filters]
. This way, your application documentation grows as you create it.
Something as simple as a sublime text snippet for a new function which includes the basic javaDoc skeleton can get you in the habit pretty quickly!
We also introspect plugins for the same markup. We encourage plugin authors to adjust their plugin code to include [section: Plugins]
at the very least. We do appreciate it will take a while for the plugin eco-system to catch up with this though. More on plugins later.
You can export the docs via JSON just by changing the URL string:
i.e ?controller=wheels&action=wheels&view=docs&type=core&format=json
You could also include the functions used to create the docs and create your own version (perhaps useful for a CMS or other application where you have internal documentation for authenticated users). Whilst this isn’t officially supported (the main functions may be subject to change!) it is technically possible. The best example is the thing itself – see the main output if you’re interested. Please note that the user interface isn’t available in production mode (for obvious reasons we hope!), so if you wanted to expose this data to an end user, you would probably need to “roll your own” with this approach.
Note that the CFC introspection doesn’t automatically happen on every request, so you will need to ?reload=true
to see changes to your code. Additionally, Adobe ColdFusion is more aggressive in caching CFC metadata, so depending on your settings, you may not see changes until a server restart.
Whilst the core has additional code samples which can be loaded from text files, there’s no support for your application functions to take advantage of this yet.
Whilst this API/function explorer is a great first step, you’ll notice your controller and model specific functions aren’t included (only those shared amongst controllers, or in the /global/functions.cfm
file. This is because we’re only looking at the main Model.cfc
and Controller.cfc
and what it can access.
In CFWheels 2.1, we’ll look at adding a full Controller and Model metadata explorer using the same techniques, and map functions like show()
to their respective routes too.