Recent Blog Posts by Ben Nadel
Formatting Dates In The Local Timezone With Alpine.js
On a recent episode of Syntax.fm, Wes Bos, Scott Tolinski, and guest Scott Jehl discussed the current landscape of "Web Components" (aka, custom elements). I haven't worked with custom elements directly; but, I have been playing around a lot with Alpine.js. And, one thing that Jehl mentioned that caught my ear was the use of custom elements to format date/time values on the client-side. I wanted to see what it might look like to perform this task with an Alpine.js component... read more →
Counting The Occurrences Of A Substring Or RegEx Pattern In ColdFusion
The other day, in my Incident Commander app code, I needed to count the number of back-ticks in a truncated piece of text in order to make sure that the count was balanced (ie, that there were an equal number of starting and ending back-ticks for a Slack-formatted message). I don't often have to count substrings in ColdFusion; but, I was surprised to find that even in recent releases of the language there's no native method for counting occurrences of a substring or regular expression pattern. As such, I wanted to take a quick look at how this can be done in Adobe ColdFusion... read more →
Rebuilding Incident Commander As A ColdFusion App
Years ago, I created a simple Firebase and Angular app for triaging incidents at work. The app allowed the incident commander (IC) to record notes and share messages in Slack (via copy-paste). But, one thing that it never allowed for was the storing of supporting screenshots. To remedy this (and as a fun thought experiment), I've rebuilt my Incident Commander app in Adobe ColdFusion with a MySQL data store; and, it now allows screenshots to be embedded within the shareable timeline... read more →
Using fileGetMimeType() To Determine File Type In ColdFusion
This morning, in a discussion about inspecting file upload contents within the temp directory, Brian Reilly taught me that there is a native ColdFusion function for determining a given file's mime-type: fileGetMimeType(). This function—when operating in the default "strict mode"—will inspect the contents of a given file and return the true mime-type, regardless of which file extension is being used. I can't believe this has existed since ColdFusion 10 and I didn't know about it!.. read more →
Building A Moment-Inspired .fromNow() Date Formatting Method In ColdFusion
I'm working on a small personal tool for incident triage and management. And, one of the things that the tool does is render a timeline of status updates in reverse chronological order. I'm been wrestling with how to best render such a timeline when everyone lives in different timezones. One thought that I have is to use a Moment.js-style "from now" format where the dates are labeled relative to the current time. I've done this in Angular before; but, I've never done this in ColdFusion. As such, I wanted to try porting my logic over to the server-side... read more →
Inspecting The Form Upload File Field Metadata In ColdFusion
When you upload a file in ColdFusion, the fileUpload() function and the CFFile[action=upload] tag aren't actually uploading the file to the server—at that point in the workflow, the file already exists on the server. The fileUpload() function is just moving the file from a temporary location to a permanent location of your choosing. And, when you're uploading files through a standard form post, the form field that represents your file upload contains the path to that temporary location. Which means you can therefore inspect a file in ColdFusion before you move it to its permanent location... read more →
VARCHAR(Length) Limit Refers To Characters, Not Bytes, In MySQL
When you define a varchar field in a MySQL database table, you can provide a length limit, ex varchar(255). For as long as I can remember, I thought this limit referred to the number of bytes that could be stored in the field. And, to be fair, back when I was only consuming ASCII characters, this assumption was coincidentally true—one ASCII character is represented by one byte. In reality, this length limit refers to the number of characters that can be stored in a field, regardless of how many bytes are needed to represent said character string... read more →
Using JSoup To Report Untrusted HTML Elements And Attributes In ColdFusion
Yesterday, I took my first look at using JSoup to sanitize untrusted HTML in ColdFusion. Historically, I've been using the OWASP AntiSamy project to do the same thing; and while the JSoup approach feels more flexible is easier to consume, it's missing one important feature that AntiSamy had: an ability to report on which aspects of the untrusted DOM (Document Object Model) were being removed during the sanitization process. As such, I wanted to look at how I can use JSoup to report the untrusted HTML elements and attributes that were being removed in my ColdFusion processing... read more →
Using jSoup To Sanitize Untrusted HTML In ColdFusion
For years, I've been using the OWASP AntiSamy project to sanitize untrusted HTML in ColdFusion. And for years, James Moberg has suggested that I just use JSoup. I'm not one to switch tools unnecessarily. However, when I went to install AntiSamy in a new project and remembered just how many JAR files were required, I figured it was time to look at JSoup's single JAR approach to cleaning and sanitizing HTML... read more →
Safe-Navigation Operator Swallows Method Errors In Adobe ColdFusion 2023
This morning, I was running into a strange null-reference error in my ColdFusion dependency injector (DI). A CFProperty-based component wasn't being injected; but, no error was being thrown or logged. After commenting-out a bunch of code, I finally narrowed it down to a bug in ColdFusion. If you use the safe-navigation operator to invoke a component method, any error thrown in that method will be swallowed up and the method will be short-circuited. I confirmed this behavior in both Adobe ColdFusion (ACF) 2021 and 2023... read more →
Working Code Podcast - Episode 200: We're Taking A Break
After recording 200 episodes, we've decided to take a short break from the show. We never really had a plan going into this endeavor; and, there was no sense of a seasonal cadence to what we were doing. As such, we're gonna call this the end of "season one" and take a hiatus through the end of the calendar year 2024. In January, we'll regroup and start "seasons two". Thank you all for listening to the show and for following along on this journey... read more →
Feature Flags Book Playground, Videos, And Code
As a companion piece to my Feature Flags Book, I've created a feature flags playground to provide my readers with some lightweight hands-on experience. It's great to read about a concept in a book. But, some concepts don't become tangible until you can roll your sleeves up and get little bit dirty. This feature flags playground gives people an opportunity to define feature flags, add rules, target cohorts, and incrementally release new features to a demo user-base. The primary goal of this playground is to add dimension to the content of the book; but, if you want to see the underlying code, I've made it all available on GitHub—it's built in ColdFusion, Parcel.js, Alpine.js, and Less CSS and runs on Docker... read more →
Playing With Window Functions In MySQL 8
Earlier this week, I went through the High Performance SQLite course by Aaron Francis. Among the many SQL topics that he covered, he included something that I've never tried before: Window Functions. These functions allow you to calculate data based on the current row. These functions behave somewhat like a subquery that is locked-down to the existing result-set. And, which can be further subdivided using a partition column... read more →
High Performance SQLite Video Course By Aaron Francis
Last night, I finished the High Performance SQLite video course by Aaron Francis. It is one of the best video courses that I've taken to date. Aaron strikes the perfect balance between density of content, depth of discussion, levity, and flow. And the quality of the video production is outstanding—this is obvious from the very first video; and, remains consistent through to the end. Using a distraction-free staging context, Aaron delivers the information in bite-size morsels that are easy to consume. If you're interested in learning more about SQLite, I highly recommend this course... read more →
Working Code Podcast - Episode 199: Country Code TLDs
All 2-character top level domains (TLDs) represent country codes. For example, .us is the TLD for the United States; .ai is the TLD for Anguilla; and, .io is the TLD for the British Indian Ocean Territory. In addition to their original purpose, these TLDs have been heavily co-opted by the tech sector. Normally this wouldn't be an issue; however, the British government has recently ceded control over the India Ocean's Chagos island. This may obviate the need for an .io TLD. Which could mean—in theory—that .io domains eventually stop working. This gives us a moment to pause and reflect upon the practice of overloading country code TLDs... read more →
Running Memory Leak Detection After Every ColdFusion Request
In the comments of a post over on LinkedIn, I was talking to Charles Robertson about how unnerving it is to have unscoped local variables leak into the variables scope of a persisted component. This type of memory leak can lead to the cross-contamination of requests; and, in a worst case scenario, will cause one user's data to be shown to another user. Inspired by that conversation, I decided to add memory leak detection to the post-processing of every ColdFusion request in my feature flags playground application... read more →
Collocating My ColdFusion, CSS, And JavaScript Files
When building a ColdFusion multi-page application (MPA), I've never been satisfied with how files are organized. Client-side files (CSS and JS) that are tightly coupled to server-side files (CFML) are often located in completely different parts of the application's folder structure. This adds friction to the maintenance of the ColdFusion application. In an effort to experiment with a more cohesive file strategy, I want to try putting CSS and JavaScript files right next to their CFML counterparts... read more →
Dave Farley On What Makes High Quality Code
This morning, on the latest episode of the Engineering Room podcast, Dave Farley said something about code quality that really connected with the way in which I see software development. In the past, I've talked about the importance of writing code that's easy to find and easy to delete. But, both of these concepts tactically roll-up in a higher-level strategy that Dave identifies: write code that's safe and easy to change:.. read more →
Making A Case For Var Declarations In ColdFusion Templates
Last week, I opened a feature request in the Adobe bug tracker to allow for var declarations in CFML templates. After I opened this, I shared it within the Working Code discord; and, all those who responded did so in opposition to the idea. As such, I wanted to take a moment to more clearly articulate my case for allowing var declarations in, essentially, any ColdFusion context... read more →
CSV To CTE Transformer In Angular 18
When generating reports at work, I make heavy use of common table expressions (CTE) as well as the VALUES / ROW construct to create derived tables in MySQL 8. Thanks to the awesome power of SublimeText multi-cursor functionality, going from CSV (comma separated values) to CTE only takes a minute or two; but, it's a repetitive task that I'm keen to create a utility for (see my blog's utilities section). As such, I wanted to create a rough draft of this utility using Angular 18... read more →
Working Code Podcast - Episode 197: Potluck
On this week's show, we talk about a variety of topics. Adam examines the notion that you get promoted into the job that you're already doing. Carol discusses the AI training course that she just took in order to start using chat-bots in government work. Tim talks about leading your team through hard times; and how to focus on the one most important goal. And I lament the idea that I don't spend enough time sitting alone with my thoughts and connecting with the world at large... read more →
Using Canonicalize() To Embed Emoji In Email Subject Lines In ColdFusion
In my previous post on using canonicalize() to render emoji characters in ColdFusion, I mentioned that this technique can be helpful in contexts where HTML entities aren't well supported. Email subject lines appear to be one such context; as I discovered yesterday when trying to add a police siren emoji to an email subject line for a time-sensitive (expiring) link. To get around this, we can use the canonicalize() function to embed emoji safely within email subject lines in our CFML... read more →
Using Canonicalize() To Render Emoji In ColdFusion
In ColdFusion, the canonicalize() function is used to reduce a given string down to its simplest form. This is typically used during user input sanitization and validation; but, this normalization process can also be used to convert HTML entities into their associated characters. In other words, we can use the canonicalize() function to convert encoded emoji characters into native emoji glyphs... read more →
Working Code Podcast - Episode 195: Isn't Worth The Squeeze
On a recent episode of the Economics of Everyday Things, Zachary Crockett explains that the perfect amount of money laundering is not zero. Attempting to eliminate all money laundering would be so disruptive to commerce that the net-loss of such an extreme position would far outweigh the potential benefits. Over here on our podcast, that got us thinking about areas within our work in which lofty goals aren't worthwhile. Topics include error logs, code coverage, feature completeness, consistency, time tracking, elegance, and requirements gathering... read more →
Dynamically Define For-Loop Increment In ColdFusion
In my Lopem Ipsum generator, I take a collection of paragraphs and I split them up into sections of random lengths. To do this, I iterate over the collection using a dynamically defined increment. In other words, the "step" value is randomly assigned on every for-loop iteration. I don't think I've ever done this before; and it worked like a charm. So, I thought it was a mechanic worth sharing in ColdFusion... read more →
Generating Lorem Ipsum Text In ColdFusion
As a fun code kata for my /utils section, I wanted to create a Lorem Ipsum text generator. Lorem Ipsum is a common way to create placeholder text during the design phase of the prototyping process. Lorem Ipsum text uses Latin words to embody English-looking text distributions without the distraction of being readable (except by those 4 people who took Latin classes in high school). What follows is my attempt to generate this placeholder text in ColdFusion... read more →
ColdFusion: Comparison Method Violates Its General Contract
This week, a single instance of an error showed up in my ColdFusion logging: "Comparison method violates its general contract!". The stacktrace pointed to something in the Java layer called TimSort; which is what ColdFusion's Array.sort() method is using under the hood. This error may be thrown if the .sort() callback / operator doesn't adhere to the set of requirements defined by the Comparable interface... read more →
Working Code Podcast - Episode 193: Bonding In The Foxhole
Without a doubt, there is a special bond formed between people who've shared an intense experience. At work, we see this all the time during incident triage and remediation—there is something truly special about those Zoom calls in which everyone on the team is suddenly on the same page and is working with a singular purpose. But, do we end up glorifying these metaphorical foxholes? Can we build those lasting bonds during the good times? Or, is there something unique about a company that has gone through trial-by-fire?.. read more →
TODO: Granting Yourself Permission To Move Forward
I just read Chris Ferdinandi's latest newsletter, Gardening and code, about the importance of solving the problems in front of you. In it, Chris touches upon an issue that we all struggle with at some point: feeling like our first solution has to be the perfect solution. It reminded me of a powerful cognitive tool that I use in my own programming: the TODO: comment... read more →
Signals And Array Mutability In Angular 18
Like many change detection mechanisms, Signals in Angular 18 rely on reference changes in order to trigger change detection. When consuming simple values, this is fine because simple values are passed by value, not by reference. But, when wrapping complex objects in a Signal, the mutability of objects becomes a point of consideration. It's important to understand how the change detection mechanisms in Angular work so that you don't end up falling down the immutability rabbit-hole... read more →