CFWheels 2.0.0-Beta 1 released

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:

  • Direct Download: Download zip
  • Commandbox quick install : install [email protected] (Just downloads and unzips)
  • Commandbox install wizard via CFWheels CLI (with url rewriting included):  wheels new
    (make sure your version of the CLI is up to date with install cfwheels-cli)

Make sure to check the “Breaking Changes” section below, and please report any bugs.

Read more:

CFWheels 2.0.0-beta.1 Now Available

CFWheels updates

Shockingly, I’ve not been blogging much. There are however some new posts I’ve done on the CFWheels Blog in prep for CFWheels 2.x;

More to come too..

Speaking at cfCamp

Pleased to say I’ll be speaking on CFWheels 2.x and the new CLI at CFCamp, 20-21 October 2016. Would be great to catch up with people – do come and say hello (and indeed, come to my session!)

Session Details:

CFWheels 2.x and the new CLI

CFWheels is an open source CFML framework inspired by Ruby on Rails that provides fast application development, a great organisation system for your code, and is just plain fun to use. One of our biggest goals is for you to be able to get up and running with CFWheels quickly.

We want for you to be able to learn it as rapidly as it is to write applications with it. CFWheels has a long history, with the first commit over 10 years ago. Over 3000 commits later, this talk will take a look at what’s new in CFWheels 2.x, which brings huge leaps forward with tonnes of new features integrated into the core.

Along with 2.x comes the new CLI commands for CommandBox, which allow real “rails-style” scaffolding, complete with database migrations, controller, model and view templating, ability to run test suites from the command line, and much, much more.

Even if you’re not familiar with CFWheels, this talk will aim to give you enough to get going on your first app at breakneck speed!

CFWheels CLI for Commandbox (Alpha Test)

Ok.. so this is what I’m working on at the moment. Work in progress! It’s the beginning of a port of the Rails CLI, but for CFWheels using Commandbox.

Adding Markdown to CFWheels

I needed to do this the other day, so thought I might as well document quite how easy it is! The following was done on Lucee, so if you use ACF your mileage may vary. This uses MarkdownJ, a Java port of Markdown written by Pete Bevin.

Download markdownj.jar (I’ve included a copy here, as it can be a little tricky to track down these days). The attached is zipped, so unzip into your miscellaneous folder, so you have markdownj.jar in there.

In /config/app.cfm, add a mapping to your miscellaneous folder so we can load .jar files easily.

this.javaSettings = {
LoadPaths = ["/miscellaneous"]
};

In /events/onapplicationstart.cfm, add the createObject call:

application.m = CreateObject( "java", "com.petebevin.markdown.MarkdownProcessor" ).init();

Now, after an application restart, you can just do application.m.markdown(myContent) to parse.

Testing for cfheader in cfwheels

In the process of trying to write a plugin for cfwheels, I can across the issue of trying to test to see if “cfheader” had been set.

So, if you had:

<cfheader name="foo" value="foo">

How do you test for this in rocketunit? Specifically, I had a function, setCustomHeader() which literally calls wheels’s internal $header() function (which in turn sets cfheader);

Turns out there’s a solution by looking directly at the page context:

// Set a custom header and check it's in the response
function Test_Set_Custom_Header_Foo(){
  setCustomHeader(name="foo", value="bar");
  loc.headers=getPageContext().getResponse().getHeaderNames();
  loc.headerValue=getPageContext().getResponse().getHeader('foo');
  assert("loc.headers.toString() CONTAINS 'foo'");
  assert("loc.headerValue EQ 'bar'");
}

In this example, using getReponse().getHeader() returns a java.util.hashSet, where we can just convert to a string and look for the value we’ve set. Nifty!

cfWheels: hasChanged() and changedFrom()

One of the more overlooked nice features of cfWheels is the ability to determine whether an object’s properties have changed before you save them. With that information, we can then easily set other model properties dependent on the change.

Why would we do this? Let’s take an example of a ticketing system where each ticket would have a status, i.e “Available, Pending Payment, Sold, Void”, but for each of those conditions, other columns in your dataset might need to be altered, and you only want to alter them when the status actually changes, not every time the object is saved.

So if a ticket’s Status goes from from Pending Payment-> Sold, we might want to change another column as part of the work flow, in this case, we might want to dictate that now that ticket is Sold, that it now needs to be printed out and delivered. In our example, we want to programmatically change deliverystatus to “Print Me” or something. Maybe we’ve got a condition setup which removes tickets from a shopping basket via cron job when a date has expired (these are just examples).

In wheels, we can add this logic once on the model, and then we never need to worry about it in our controllers again. The trick is using this.changedFrom(“ticketstatus”) and this.ticketstatus as the “before and after” values to compare against.

In our Ticket.cfc model’s init() method, we can add a function call to trigger beforeSave:

beforeSave("checkTicketConditions");

Then, in the same file, add a function to handle this:

public void function checkTicketConditions() {

  if(this.hasChanged("ticketstatus")){
    oldStatus=this.changedFrom("ticketstatus");
    newStatus=this.ticketstatus;

    // Reserving Tickets in shopping basket
    if(newStatus EQ "INBASKET"){
      this.removeFromBasketAt=dateAdd("s", 3200, now());
    }

    // Remove cron basket timelimit (i.e, when the status changes from INBASKET to anything)
    if(oldStatus EQ "INBASKET"){
      this.removeFromBasketAt="";
    }

    // etc
  }

  // Update delivery status
  if(this.hasChanged("delivery")){
    if(this.delivery EQ "eticket"){
      this.deliverystatus="PENDING EMAIL DELIVERY";
    } else if(this.delivery EQ "postal"){
      this.deliverystatus="PRINT AND POST ME";
    } else if(this.delivery EQ "pickup"){
      this.deliverystatus="PRINT ME";
    }
  }
}

With this type of model logic you can actually fire off some pretty complex workflows, and keep it all out of your controller!

OxAlto Roombooking System 1.2 Released!

Firstly, there’s now some pretty comprehensive documentation at http://roombooking.readme.io/ – This was a bit of blood, sweat and tears, but the system at readme.io makes this relatively painless, and it’s free for open source projects – hurrah!

This is a pretty big release this one – LOTS of new features and tweaks. Don’t forget to read the Upgrade notes for this one…

Here’s the feature list, but the highlights probably are simple concurrency warnings when booking, event moderation, custom fields and templating from within the application, support for running in a subdirectory and a better list view.

Download 1.2 now

Features:

  • New and comprehensive documentation
  • Creating a new booking now does a simple concurrency check
  • Bookings can now have basic event moderation
  • Moderator permissions can be assigned by role
  • Booking can exist in three states – approved, pending & denied
  • Locations can now have custom layouts
  • Locations can now belong to ‘buildings’
  • Locations now have a basic information page
  • Calendar view shows pending/denied events with different colours/opacity
  • Calendar view location filter now supports buildings and hover filter states
  • Events & Locations can now have Custom Fields added (and stored in the database)
  • Events & Locations can now use Custom Templating for both input + output
  • Added New Custom Template drag and drop creator (from gridmanger.js) for building forms and outputs
  • Installer simplified
  • URL rewriting now off by default to help support sub directory installations more seamlessly
  • Can now run in a subdirectory
  • Roles are now dynamic
  • List View now supports date ranges, multiple locations and filtering by status.
  • Notification emails updated to support mobile/responsive clients
  • Not deleting the /install/ folder now shows a nag message rather than throwing a full error
  • Footer now displays current code + database schema version
  • [Removed] Day view is now deprecated in its current form

JS/CSS:

  • Upgraded to fullcalendar.js 2.3.2
  • Improved datepickers again
  • More JS moved to external js file rather than being embedded in page

Serverside:

  • Moved to cfwheels 1.4.1.

Data:

Tables:

  • Added: customfields,customfieldjoins,customfieldvalues,templates
  • Events – added status column
  • locations – added building /layouts columns

Settings:

  • Added: approveBooking,bccAllEmailTo,bccAllEmail
  • Changed: – siteEmailAddress changed category to Email, version number updated.

Permissions:

  • Added: accessCustomFields,allowApproveBooking,bypassApproveBooking

cfWheels Plugin Survey

Use cfWheels? Help us get an idea of what plugins you guys use, and which you think might qualify for some core team support! The survey will only take a minute – please do fill it in if you use any plugins in cfWheels..

https://www.surveymonkey.com/s/9P7PJCV