Code is hard. One way to make it easier is to make it pretty. Even simple, short code can become difficult to reason about if it's all scrunched together:
That code is pretty simple, but difficult to reason about. The interspersed debug logging adds a lot of noise and detracts from overall legibility. Just spacing it out helps a lot:
What else can we do? The first declaration of ret is kind of pointless: let's move that closer to where it actually matters, and just return an empty object from the first guard clause. To make sure we print what's actually in the parameter we'll also JSONize it so we don't miss strings that look empty, but aren't. We'll also throw in a quick log wrapper.
The string pre-processing is fine as it is. We can ease our loop readability fairly easily:
Will we increase comprehension by switching to more-modern JS practices?
Kind of a toss-up, but I think so.
Ultimately, however, this is a function that would be better tested either via an actual test, or in the debugger. Logging is fine for long-running testing, but this function is short enough, and clean enough, that we might as well just set some breakpoints within the method, or at the call point.
Friday, July 17, 2020
Sunday, January 20, 2019
Snowflake Sociology
"Snowflake" isn't a term I enjoy using: it's derogatory, demeaning, and can be used as a dismissive approach to ideas we don't like. Until you're snowflaked, it's an easy thing to not like.
I was finally snowflaked awhile back. I sat on it for some time, but given today's general political and conversational climate, I wanted to discuss the experience. Someone asked a Stack Overflow question I thought was very clear in its intent, roughly:
What? Are all method names verbs? (No.) Are all method names in a DSL verbs? Most assuredly not (attr_accessor is not a verb, it's a declarative assertion of intent). To me, it was crystal clear what was being asked (and apparently it was equally clear to the two people that answered it).
I was accused of being condescending and misogynistic. Many people have accused me of being condescending; when you're far enough along on the spectrum to be diagnosable, it happens. Not proud of it, but it happens. Misogynistic?! To anybody that actually knows me the idea is laughable. I was insulted, and badly. It hurt. It was embarrassing.
Could I have expressed my opinion that I thought the question was obvious in a better way? Possibly (and probably, but honestly, it wouldn't even register with most people). Could I have said something like "It seems like they're asking for a DSL; given the provided examples I think the intention is to treat the function names like mathematical operators." I could have just said that and let it be.
I didn't: I said it was "obvious" what was being asked. That was the mistake. Why? Because when something isn't "obvious" to someone, and it is to someone else, it can make the other person feel stupid. This can escalate quickly (as it did).
I have a different view of things: if something is obvious to someone else, and not to me, it means I have a knowledge gap. I don't like knowledge gaps. I might feel shame: one of my traits is that I know things. It partially defines who I am. When I don't know something, it diminishes who I am in some way. It's a non-functional emotional behavior (that I'm working on).
That I didn't know something doesn't trigger an external redirection of that shame, however: I don't take out my (perceived) shortcomings on the person that brought it up, at least not in a public forum. And I certainly don't accuse other people of being biased in any way (if they're being a jerk I'll call them on that, though).
Here's the thing: nobody likes to be wrong. People like to be told they're wrong even less. Some people lash out when they're told they're wrong, or that something might be obvious to somebody else.
There's always a balance. Online intent is very easy to mis-judge. The word "obvious" can be a trigger.
Lesson learned.
I was finally snowflaked awhile back. I sat on it for some time, but given today's general political and conversational climate, I wanted to discuss the experience. Someone asked a Stack Overflow question I thought was very clear in its intent, roughly:
They want a math DSL, and they provided examples:I can't seem to wrap my head around the logic for writing a function that looks something likeeight(times(five))in JavaScript.
I mean... this is obvious. To me. Not to Ryan and Amy. They asked for clarification, I told them both it seemed very straight-forward what was being asked. Their hangup (at first)? "Eight isn't a verb, so it can't have behavior."
eight(times(five))should return 40three(plus(two))should return 5
What? Are all method names verbs? (No.) Are all method names in a DSL verbs? Most assuredly not (attr_accessor is not a verb, it's a declarative assertion of intent). To me, it was crystal clear what was being asked (and apparently it was equally clear to the two people that answered it).
I was accused of being condescending and misogynistic. Many people have accused me of being condescending; when you're far enough along on the spectrum to be diagnosable, it happens. Not proud of it, but it happens. Misogynistic?! To anybody that actually knows me the idea is laughable. I was insulted, and badly. It hurt. It was embarrassing.
Could I have expressed my opinion that I thought the question was obvious in a better way? Possibly (and probably, but honestly, it wouldn't even register with most people). Could I have said something like "It seems like they're asking for a DSL; given the provided examples I think the intention is to treat the function names like mathematical operators." I could have just said that and let it be.
I didn't: I said it was "obvious" what was being asked. That was the mistake. Why? Because when something isn't "obvious" to someone, and it is to someone else, it can make the other person feel stupid. This can escalate quickly (as it did).
I have a different view of things: if something is obvious to someone else, and not to me, it means I have a knowledge gap. I don't like knowledge gaps. I might feel shame: one of my traits is that I know things. It partially defines who I am. When I don't know something, it diminishes who I am in some way. It's a non-functional emotional behavior (that I'm working on).
That I didn't know something doesn't trigger an external redirection of that shame, however: I don't take out my (perceived) shortcomings on the person that brought it up, at least not in a public forum. And I certainly don't accuse other people of being biased in any way (if they're being a jerk I'll call them on that, though).
Here's the thing: nobody likes to be wrong. People like to be told they're wrong even less. Some people lash out when they're told they're wrong, or that something might be obvious to somebody else.
There's always a balance. Online intent is very easy to mis-judge. The word "obvious" can be a trigger.
Lesson learned.
Back yet again!
As part of a blogging/writing blitz I'm back on this platform as well as others.
I'll be blogging here, as well as one of the bloggers at the Maker's End Blog, discussing a wide variety of topics, generally related to technology, but occasionally stretching far afield into general Making, society, crafting, and so on.
A few of the upcoming topics will include:
* JavaScript
* Embedded Systems
* Projects/Builds
* Technology Landscape
* Automating creative workflows
* Refactoring (with specific examples, usually from Stack Overflow)
* Code Quality Issues and Metrics
* IoT
* Integrations
As always, I'm open to suggestions for topics.
I just built the Pimoroni Keybow keyboard; check out the build and review (and build video). It's a pretty slick 12-key auxiliary keyboard powered by the Raspberry Pi Zero WH with an RGB LED under each key. It acts like a standard keyboard (USB HID) and I'm pretty excited to experiment with it.
Also, stay tuned for excerpts from an upcoming Maker's End book series, the Inspiration Series, which will cover a number of embedded platforms including the Arduino, various Adafruit boards, Sparkfun QWIIC boards and components, and some DFRobot boards and parts. First out of the gate will be the Arduino Inspiration book, a project-based Arduino tutorial, with a goal of inspiring relative newcomers to the world of artistic expression using technology.
I'll be blogging here, as well as one of the bloggers at the Maker's End Blog, discussing a wide variety of topics, generally related to technology, but occasionally stretching far afield into general Making, society, crafting, and so on.
A few of the upcoming topics will include:
* JavaScript
* Embedded Systems
* Projects/Builds
* Technology Landscape
* Automating creative workflows
* Refactoring (with specific examples, usually from Stack Overflow)
* Code Quality Issues and Metrics
* IoT
* Integrations
As always, I'm open to suggestions for topics.
I just built the Pimoroni Keybow keyboard; check out the build and review (and build video). It's a pretty slick 12-key auxiliary keyboard powered by the Raspberry Pi Zero WH with an RGB LED under each key. It acts like a standard keyboard (USB HID) and I'm pretty excited to experiment with it.
Also, stay tuned for excerpts from an upcoming Maker's End book series, the Inspiration Series, which will cover a number of embedded platforms including the Arduino, various Adafruit boards, Sparkfun QWIIC boards and components, and some DFRobot boards and parts. First out of the gate will be the Arduino Inspiration book, a project-based Arduino tutorial, with a goal of inspiring relative newcomers to the world of artistic expression using technology.
Friday, October 20, 2017
Cura 3 on OS X Crashes on Startup
This one was easy to fix, although I'm not sure what the consequences will be.
On startup the new version of Cura would start to open (evidenced by Activity Monitor process) then close. I decided to delete my existing Cura app data since (a) need to recalibrate the printer anyway, (b) getting an additional new printer anyway, and (c) didn't know what else to try.
Navigate to ~/Library/Application Support/ and look for anything Cura-related. In my case, there was a Cura folder with a directory for the two previous versions I'd had installed.
Go ahead and delete those, you didn't want them anyway.
My Cura 3.0 now starts just peachy.
On startup the new version of Cura would start to open (evidenced by Activity Monitor process) then close. I decided to delete my existing Cura app data since (a) need to recalibrate the printer anyway, (b) getting an additional new printer anyway, and (c) didn't know what else to try.
Navigate to ~/Library/Application Support/ and look for anything Cura-related. In my case, there was a Cura folder with a directory for the two previous versions I'd had installed.
Go ahead and delete those, you didn't want them anyway.
My Cura 3.0 now starts just peachy.
Coming Soon
I have a number of projects, both software- and hardware-related, coming down the pike right quick now. Think Raspberry Pi 0W, Raspberry Pi 3, NodeMCU, IoT, Elixir/Phoenix, Kafka, AWS, Nerf gun mods/hacks, and so on. I'm open for business in a new workspace, with new tools, and new mindset.
Let the games begin.
Tuesday, August 11, 2015
Pirate Stack
LAMP? MEAN? No, mateys, PIRATE STACK!
(A)RRR(GH): React, Relay, RethinkDB.
The stack is mine. I win the internet.
(A)RRR(GH): React, Relay, RethinkDB.
The stack is mine. I win the internet.
Wednesday, August 05, 2015
Styling Atom Editor UI Elements
I'm in the process of switching to Atom as my daily text editor (from Sublime Text 3) and needed to have my UI element font much smaller. Doing this in Atom is blissfully easy, just edit your styles.less file and you're done. The trick is understanding which elements you want to style.
Most elements I needed re-sized are easy:
The styles.less is accessible directly in your $HOME/.atom directory, or through Atom itself in Settings -> Themes.
Most elements I needed re-sized are easy:
The styles.less is accessible directly in your $HOME/.atom directory, or through Atom itself in Settings -> Themes.
Friday, July 17, 2015
Saturday, June 06, 2015
CoffeeScript IIFEs
Immediately-Invoked Function Expressions are an easy way to hide your variables, preventing collisions with your code or the code of others. In JavaScript you'll see the following a lot:
In CoffeeScript the syntax can be the same; enclose the function in parens, and put parens after it to call it. It's ugly, though:
CoffeeScript has the do keyword, though, and it provides a cleaner way to do this:
If you're passing an argument the ugly way you'd put the closing paren at the same level as the IIFE's code block; this looks a little wonky to me, and the trailing paren looks lonely (odd for a Lisp person to say, huh?
The do version requires the variable to be set at the point of the do. I think I still prefer this method, but it reads a little funny to me:
In CoffeeScript the syntax can be the same; enclose the function in parens, and put parens after it to call it. It's ugly, though:
CoffeeScript has the do keyword, though, and it provides a cleaner way to do this:
If you're passing an argument the ugly way you'd put the closing paren at the same level as the IIFE's code block; this looks a little wonky to me, and the trailing paren looks lonely (odd for a Lisp person to say, huh?
The do version requires the variable to be set at the point of the do. I think I still prefer this method, but it reads a little funny to me:
Thursday, April 30, 2015
Easy Halloween Sound Hack, Part One
My aunt and uncle set up a "Haunted Forest" every year, where they take area kids through a section of their woods with groomed trails and various scary things. This year I'm helping "up the ante" with sound, lighting, and robotics (pneumatic and/or otherwise depending on time). I'll cover various means of tech-ing up the fear.
The first hack is pretty straight-forward, the only possible glitch being sound file format conversion (the board I'm using doesn't support MP3) to OGG. WAV is supported (and desirable under some conditions) but the storage space is somewhat limited, so I'm using mostly OGG except for when sounds are being looped or played sequentially. The compressed format introduces a small, but perceptible, delay under those conditions.
My test rig was designed to be cheap and mutable, so I used a mono amplifier (Adafruit ID 2130) and the mini sound trigger board (Adafruit ID 2342, 2M flash storage), about $19 altogether. There's an integrated version (2M flash, stereo amp) that I might consider, it's about $25. I'm anticipating we'll use anywhere from 2-6 of these across the forest, with a variety of triggering mechanisms.
The Adafruit docs detail how the device works. Nutshell: sounds are triggered via either the board's GPIO pins (pull to ground) or serial port. Only one of these mechanisms can be used at a time. (I have another project using serial control; this will be documented later.)
For the haunted forest (and my own display) we'll need several triggering options, including PIR, simple switches, and possibly audio. Trigger pins will be externally exposed via a simple jack, probably 1/8" audio. Speakers will be external with an option to stick it onto the project box.
One obvious usage is to hang the box from a tree with the PIR firing down, or towards the path. For extra giggles you could either point it so it fires after the victims have passed so the sound comes from behind them. With only minor effort, and separated stereo speakers, you could set up a sequential trigger that first comes from behind, then in front of, the victims, etc.
For my own Halloween display I'll be using two setups, one with a PIR for people approaching the house, and another at the house for when they dip into the candy bowl. With a 4 Ohm speaker the sound is more than enough to raise a hackle or two, although if you need to project over a distance you'll want something more powerful than the 2.5W amps shown here or on the integrated device.
Upcoming posts will detail the lighting (fire and lightning effects, other simple things), any robotics, and the integration of all these systems into a unified pee-inducing system.
The first hack is pretty straight-forward, the only possible glitch being sound file format conversion (the board I'm using doesn't support MP3) to OGG. WAV is supported (and desirable under some conditions) but the storage space is somewhat limited, so I'm using mostly OGG except for when sounds are being looped or played sequentially. The compressed format introduces a small, but perceptible, delay under those conditions.
My test rig was designed to be cheap and mutable, so I used a mono amplifier (Adafruit ID 2130) and the mini sound trigger board (Adafruit ID 2342, 2M flash storage), about $19 altogether. There's an integrated version (2M flash, stereo amp) that I might consider, it's about $25. I'm anticipating we'll use anywhere from 2-6 of these across the forest, with a variety of triggering mechanisms.
![]() |
| Breadboarded prototype; cheap version |
The Adafruit docs detail how the device works. Nutshell: sounds are triggered via either the board's GPIO pins (pull to ground) or serial port. Only one of these mechanisms can be used at a time. (I have another project using serial control; this will be documented later.)
For the haunted forest (and my own display) we'll need several triggering options, including PIR, simple switches, and possibly audio. Trigger pins will be externally exposed via a simple jack, probably 1/8" audio. Speakers will be external with an option to stick it onto the project box.
One obvious usage is to hang the box from a tree with the PIR firing down, or towards the path. For extra giggles you could either point it so it fires after the victims have passed so the sound comes from behind them. With only minor effort, and separated stereo speakers, you could set up a sequential trigger that first comes from behind, then in front of, the victims, etc.
For my own Halloween display I'll be using two setups, one with a PIR for people approaching the house, and another at the house for when they dip into the candy bowl. With a 4 Ohm speaker the sound is more than enough to raise a hackle or two, although if you need to project over a distance you'll want something more powerful than the 2.5W amps shown here or on the integrated device.
Upcoming posts will detail the lighting (fire and lightning effects, other simple things), any robotics, and the integration of all these systems into a unified pee-inducing system.
Sunday, April 26, 2015
Electric Imp + OLED + ... Squirrel?
The Electric Imp came out before the days of essentially-free ESP WiFi modules. It was designed to be embedded into devices, provide a WiFi interface, and some basic cloud connectivity. It's a bit of an odd duck: it's initialized by blinking lights, e.g., seizure-inducing screen flashes from your phone. This is a pretty unique way to get things set up, and it works great.
I had a few of these devices sitting on a shelf and recently ran across someone asking for help connecting them to a small color OLED with an attached SD slot for image storage. While I waited for my OLED to arrive I decided to hook it up to one I had on hand, a 128 x 64 monochrome OLED, hot on the heels of hooking up a different 128 x 64 monochrome OLED to an Arduino as part of another project (project blog(s) coming soon pending blogging platform change).
Both the monochrome OLEDs are based on the SSD1306 display driver. I wired the display to the Imp using SPI, but as the project requirements morphed, I realized the Imp dev board the project used, the April, didn't have the IO necessary to use SPI since we still wanted user input under Imp control. The next iteration will hook up the display using I2C. The caveat is that the OLED that'll actually be used, while I2Cable, will require a fair amount more effort to ensure access to both devices on the board, the OLED, and the SD card.
The final SSD1306 library combines to existing code bases: the first an Imp-specific Squirrel-based class optimized for image display under I2C (e.g., not pixel-oriented line drawing), the second the Adafruit SSD1306 library with line primitives supporting both I2C and SPI.
The end result is a new Electric Imp SSD1306 I2C library. I may continue development to support both I2C and SPI; the SPI data writes are faster, but exhausts the resources of the April board (an "imp001 device"). Since this is a bespoke project I decided to keep the original library small, focused, targeted at the project's exact needs, and over-documented. I will likely robustify this effort into a general-purpose Imp SSD1306 library.
The images above are with the original SPI wiring. The next episode will include a more in-depth writeup discussing the library itself, the I2C wiring with additional input (and output?) devices, a link to the library, and will include how to access the Imp from a phone and do something with the attached devices.
I had a few of these devices sitting on a shelf and recently ran across someone asking for help connecting them to a small color OLED with an attached SD slot for image storage. While I waited for my OLED to arrive I decided to hook it up to one I had on hand, a 128 x 64 monochrome OLED, hot on the heels of hooking up a different 128 x 64 monochrome OLED to an Arduino as part of another project (project blog(s) coming soon pending blogging platform change).
![]() |
| Not quite there yet; image buffer not written to OLED. |
The final SSD1306 library combines to existing code bases: the first an Imp-specific Squirrel-based class optimized for image display under I2C (e.g., not pixel-oriented line drawing), the second the Adafruit SSD1306 library with line primitives supporting both I2C and SPI.
The end result is a new Electric Imp SSD1306 I2C library. I may continue development to support both I2C and SPI; the SPI data writes are faster, but exhausts the resources of the April board (an "imp001 device"). Since this is a bespoke project I decided to keep the original library small, focused, targeted at the project's exact needs, and over-documented. I will likely robustify this effort into a general-purpose Imp SSD1306 library.
![]() |
| Now we're cooking with gas: I can haz pixels! |
Friday, April 19, 2013
Remapping a Control key to Windows / Super Under Ubuntu 12.04
My old ThinkPad keyboard rocks: it has a trackpad and a trackpointer, types nicely, has a palm rest, and is generally awesome. It does not, however, have a Windows button: this makes using it under... well, anything... difficult.
I'm currently developing with a company-bought Ubuntu laptop after having used OS X for the last three years almost exclusively. Like Windows and OS X, it pretty much demands the use of a Super key for accessing OS functionality and popping up utilities and applications.
I used two tools to do the remapping, xev and xmodmap. The lower-left control key is key code 0x25 (37). Ultimately it ended up being simple, and my .Xmodmap looks like this:
clear Control
keycode 37 = Super_L
add Control = Control_L Control_R
I'm currently developing with a company-bought Ubuntu laptop after having used OS X for the last three years almost exclusively. Like Windows and OS X, it pretty much demands the use of a Super key for accessing OS functionality and popping up utilities and applications.
I used two tools to do the remapping, xev and xmodmap. The lower-left control key is key code 0x25 (37). Ultimately it ended up being simple, and my .Xmodmap looks like this:
clear Control
keycode 37 = Super_L
add Control = Control_L Control_R
I also added the following to my .xinitrc, but it may be redundant:
xmodmap .Xmodmap
It's more awkward than a proper Super key, but it's workable, and I'm typing happier.
Tuesday, March 12, 2013
sftp "Received message too long" on OS X
Today I started receiving the following error when I tried to sftp to my localhost, both from the command line and from the Ruby Net:SFTP library:
$ sftp ftpuser@localhost
Password:
Received message too long 1399157792
Trivial digging revealed that ftpuser's .bashrc script was writing to stdout, which apparently is enough to confuse sftp all 'round. I modified the command it was running to redirect stdout to /dev/null, and the problem was resolved.
$ sftp ftpuser@localhost
Password:
Received message too long 1399157792
Trivial digging revealed that ftpuser's .bashrc script was writing to stdout, which apparently is enough to confuse sftp all 'round. I modified the command it was running to redirect stdout to /dev/null, and the problem was resolved.
Tied to the Web Layer
Struts 2 claims that "actions can be POJOs". Developers find out pretty quickly that not extending ActionSupport means you lose some Struts 2 functionality (primarily I18N and validation).
One source of confusion is what "POJO" means. POJOs don't mean you don't extend a base class. POJOs are classes not directly tied to unrelated libraries, specifications, etc. For example, Struts 1 actions were directly coupled to the Servlet specification and Struts 1: S1 action methods had signatures including things like HttpServletRequest and ActionForm.
I think of S2 actions as the interface between the client (browser, REST consumer, etc.) and the stuff that actually gets stuff done. S2 handles validation, type conversion, flow (or at least conversion of business-level flow into web-app flow), etc.
Heavy lifting happens outside of anything related to my web layer: persistence, logic, and calculations happen in services, utilities, models, and glue. How is it relevant that my web layer actions are tied to their web layer? What would be the cost of changing web layers?
Web layers all have their own ideas about how to interface to clients. Some use annotations. Some use XML. Some use conventions. They do validations differently. They handle flow differently. They handle form parameters differently. No matter what, the layer between the client and my business logic is going to change, radically or not, if I port to a new web framework.
That my actions extend ActionSupport isn't going to be the pain point: the request handlers are going to change no matter what. How I expose validation errors to the view will change. How I retrieve form parameters will change. How I define validation will change. How I do I18N will change. How I code the view layer itself will change.
That's not to say there aren't (or shouldn't be) unified ways to do all those things, but at the moment, there isn't a single standard approach (and maybe there shouldn't be, although a "web AST" would be cool). The trick is to minimize the coupling between the client and the application's guts.
- Work in progress -
One source of confusion is what "POJO" means. POJOs don't mean you don't extend a base class. POJOs are classes not directly tied to unrelated libraries, specifications, etc. For example, Struts 1 actions were directly coupled to the Servlet specification and Struts 1: S1 action methods had signatures including things like HttpServletRequest and ActionForm.
I think of S2 actions as the interface between the client (browser, REST consumer, etc.) and the stuff that actually gets stuff done. S2 handles validation, type conversion, flow (or at least conversion of business-level flow into web-app flow), etc.
Heavy lifting happens outside of anything related to my web layer: persistence, logic, and calculations happen in services, utilities, models, and glue. How is it relevant that my web layer actions are tied to their web layer? What would be the cost of changing web layers?
Web layers all have their own ideas about how to interface to clients. Some use annotations. Some use XML. Some use conventions. They do validations differently. They handle flow differently. They handle form parameters differently. No matter what, the layer between the client and my business logic is going to change, radically or not, if I port to a new web framework.
That my actions extend ActionSupport isn't going to be the pain point: the request handlers are going to change no matter what. How I expose validation errors to the view will change. How I retrieve form parameters will change. How I define validation will change. How I do I18N will change. How I code the view layer itself will change.
That's not to say there aren't (or shouldn't be) unified ways to do all those things, but at the moment, there isn't a single standard approach (and maybe there shouldn't be, although a "web AST" would be cool). The trick is to minimize the coupling between the client and the application's guts.
- Work in progress -
Monday, March 04, 2013
"Unknown error" while signing in to Apple App Store
I was unable to log in to the Apple App Store while trying to update Xcode on my MBP.
Here's an Apple discussion thread regarding possible solutions.
What ended up working was signing out, clicking "Store -> Create New Account", accepting the Terms and Conditions, then canceling out of new account creation and signing in again.
While deleting the network interface plist, cookies, etc. was educational, it didn't work.
Accepting T&C while not creating a new account so I could use my old one... "It just works"?
Here's an Apple discussion thread regarding possible solutions.
What ended up working was signing out, clicking "Store -> Create New Account", accepting the Terms and Conditions, then canceling out of new account creation and signing in again.
While deleting the network interface plist, cookies, etc. was educational, it didn't work.
Accepting T&C while not creating a new account so I could use my old one... "It just works"?
Thursday, August 23, 2012
A JRuby, Rails, RSpec, Spork, and an error walk in to a bar...
I was running a specific rspec over and over during a tight development cycle. The way our system was set up it was taking 30+ sec to run a single spec file, which made running them onerous.
We had Spork running at one point, but it wasn't working for me, with a "undefined method 'flush' for nil:NilClass" error (and a couple of others depending on the incantation):
After upgrading Spork (we had been running an older version), setting the JRUBY_OPTS environment variable, and restarting Spork, the spec time dropped to ~8 sec. Still not particularly fast, but faster-enough to make it worth it.
Not currently running Guard. Not sure if the upgrade or opts made it start working.
This post is a work-in-progress.
We had Spork running at one point, but it wasn't working for me, with a "undefined method 'flush' for nil:NilClass" error (and a couple of others depending on the incantation):
After upgrading Spork (we had been running an older version), setting the JRUBY_OPTS environment variable, and restarting Spork, the spec time dropped to ~8 sec. Still not particularly fast, but faster-enough to make it worth it.
Not currently running Guard. Not sure if the upgrade or opts made it start working.
This post is a work-in-progress.
Wednesday, August 08, 2012
RSpec Error With Implicit Subject
Ever write a trivial spec like this:
And get something totally baffling back, like this?
Backstory: Refactoring some pre-written classes to use metaprogramming to create some methods and values. I wanted specs in place before starting the metaprogramming to avoid breaking things.
In retrospect, I should have figured this out sooner. In my defense, I love the Olympics and was distracted. The constructor of the model gives it away:
A parameterized constructor, no default value: rspec couldn't instantiate the implicit subject.
Silly mistake, exacerbated by magic, hidden functionality–it's one of the greatest things about Ruby, but can occasionally lead to opaque behavior, especially during the Olympics.
And get something totally baffling back, like this?
Backstory: Refactoring some pre-written classes to use metaprogramming to create some methods and values. I wanted specs in place before starting the metaprogramming to avoid breaking things.
In retrospect, I should have figured this out sooner. In my defense, I love the Olympics and was distracted. The constructor of the model gives it away:
A parameterized constructor, no default value: rspec couldn't instantiate the implicit subject.
Silly mistake, exacerbated by magic, hidden functionality–it's one of the greatest things about Ruby, but can occasionally lead to opaque behavior, especially during the Olympics.
Saturday, November 12, 2011
Testing singletons while avoiding their constructors
Singletons are evil, and here's why.
Fair enough. Yet they exist, and they're not intrinsically evil--just misused. Can we mock enough to make testing them feasible? Yep, and here's a Contrived Example™ that shows how (and why we might want to).
"Embedded" singletons or utility classes can make testing is problematic. Injected singletons are different; then it's an issue of whether or not it should be a singleton at all--different discussion.
"Embedded" singletons look like this. (Utility classes are essentially the same, minus an instance.)
Let's say (a) we need to test this code, (b) we cannot modify this code, and (c) the singleton's constructor is long-running, but required for fetch() execution. For testing, then, we need to (a) avoid the constructor for speed reasons, and (b) mock the fetch() method to return known data for the test. We can't just mock fetch(), because the constructor would still run.
Here's our (contrived) singleton class; we sleep() in the constructor to pretend it's doing something interesting like caching data from a web service, to be returned by fetch().
The undecorated test does what you'd expect, and takes as much time as you'd expect.
Now, with a combination of PowerMock and EasyMock, we'll put the kibosh on that, eliminate the constructor, and return the data we want. (PowerMock sits on top of EasyMock or Mockito. (Both are great, although I tend towards Mockito.)
Most of the test class is self-explanatory. The nutshell version is that we annotate the test class itself and tell it to run with the PowerMock runner (@RunWith), and that we're going to be messing with LongRunningCtor's innards (@PrepareForTest).
Inside the test itself, we tell it to suppress LongRunningCtor's constructor (before mocking, otherwise the constructor will fire during the createPartialMock() call). We also prepare for mayhem by calling mockStatic(). (This mocks all the class's static methods; we could also choose specific static methods to mock using mockStaticPartial().)
Our test now takes a fraction of the time because we're skipping the slow constructor, and our mock returns known data so we can exercise only the calling code.
Ideally, code is structured so this kind of byte-code treachery is unnecessary--it's a great reason for dependency injection/inversion of control. In the real world, technical and timing constraints don't always allow the kind of restructuring we'd like.
With the aid of some tools that do the low-level dirty work for us, we have a relatively clean way to work around some types of system limitations, and still write tests that can execute quickly.
The gist used in this post also includes the relevant Maven dependencies.
Fair enough. Yet they exist, and they're not intrinsically evil--just misused. Can we mock enough to make testing them feasible? Yep, and here's a Contrived Example™ that shows how (and why we might want to).
"Embedded" singletons or utility classes can make testing is problematic. Injected singletons are different; then it's an issue of whether or not it should be a singleton at all--different discussion.
"Embedded" singletons look like this. (Utility classes are essentially the same, minus an instance.)
Let's say (a) we need to test this code, (b) we cannot modify this code, and (c) the singleton's constructor is long-running, but required for fetch() execution. For testing, then, we need to (a) avoid the constructor for speed reasons, and (b) mock the fetch() method to return known data for the test. We can't just mock fetch(), because the constructor would still run.
Here's our (contrived) singleton class; we sleep() in the constructor to pretend it's doing something interesting like caching data from a web service, to be returned by fetch().
The undecorated test does what you'd expect, and takes as much time as you'd expect.
Now, with a combination of PowerMock and EasyMock, we'll put the kibosh on that, eliminate the constructor, and return the data we want. (PowerMock sits on top of EasyMock or Mockito. (Both are great, although I tend towards Mockito.)
Most of the test class is self-explanatory. The nutshell version is that we annotate the test class itself and tell it to run with the PowerMock runner (@RunWith), and that we're going to be messing with LongRunningCtor's innards (@PrepareForTest).
Inside the test itself, we tell it to suppress LongRunningCtor's constructor (before mocking, otherwise the constructor will fire during the createPartialMock() call). We also prepare for mayhem by calling mockStatic(). (This mocks all the class's static methods; we could also choose specific static methods to mock using mockStaticPartial().)
Our test now takes a fraction of the time because we're skipping the slow constructor, and our mock returns known data so we can exercise only the calling code.
Ideally, code is structured so this kind of byte-code treachery is unnecessary--it's a great reason for dependency injection/inversion of control. In the real world, technical and timing constraints don't always allow the kind of restructuring we'd like.
With the aid of some tools that do the low-level dirty work for us, we have a relatively clean way to work around some types of system limitations, and still write tests that can execute quickly.
The gist used in this post also includes the relevant Maven dependencies.
Thursday, November 10, 2011
A trip to the Rake-track.
(Because it's like "racetrack", and it makes Rake tasks faster, and... oh, never mind.)
Tired of waiting for Ruby to spin up just so you can run a "routes" command, or your latest "db:migrate"?
Use rake-sh and start up a rake console for running tasks without the initial spin up. It'll take a "rake routes" from four seconds down to under a second. Rake task completion? Naturally. Use "t" for tasks, "! " (note there's a space after the bang) to run a shell command.
If you get a message about an "uninitialized constant Rake::DSL" when you run rake-sh, no sweat: add require 'rake/dsl_definition' to the top of your Rakefile.
Breaking flow sucks for developers: a few seconds doesn't sound like much. In actual time, it isn't much--but it's the distractions that kill, the times-between-doing. Keep them to a minimum by fully exploiting your tools.
Tired of waiting for Ruby to spin up just so you can run a "routes" command, or your latest "db:migrate"?
Use rake-sh and start up a rake console for running tasks without the initial spin up. It'll take a "rake routes" from four seconds down to under a second. Rake task completion? Naturally. Use "t" for tasks, "! " (note there's a space after the bang) to run a shell command.
If you get a message about an "uninitialized constant Rake::DSL" when you run rake-sh, no sweat: add require 'rake/dsl_definition' to the top of your Rakefile.
Breaking flow sucks for developers: a few seconds doesn't sound like much. In actual time, it isn't much--but it's the distractions that kill, the times-between-doing. Keep them to a minimum by fully exploiting your tools.
Thursday, September 15, 2011
Rails 3 Custom Validator Quandary -- Solution Step One
Remember when I had a Rails 3 custom validator quandary? My bottom-line question was "how should I access a specific error condition, cleanly, in both an action, and a template?" I sketched a few solutions, ranging from checking for a specific error message to providing a function that indicates if the error has occurred.
For now, I want simple boolean methods on the model to encapsulate the error condition. I don't want to write them by hand; I want the validator itself to dictate the interface. For example, if I'm validating an "email" property that can only repeat n times on a given day, I'd like to have an email_repeats_error? method available in the model, returning what we'd expect.
This will be developed in two steps: first, as a simple library (makes tweaking easier, at least for me). Second, as a standalone gem (the way it should be). Naturally, this led to a brief WTF spike as I couldn't figure out how to get the library to expose the validator properly.
Loading the Library
Rails 3.0 changed how libraries are loaded, at least a little bit. I did two things to get things loading from an arbitrarily-named file in the /lib directory. First in my application.rb file, I added the /lib directory to the autoload path.
module RepeatsValidatorWork
class Application < Rails::Application
config.autoload_paths += %W(#{config.root}/lib)
# auto-require; see next code fragment.
pry(main)> i = Item.new(:name => 'wat!')
=> #
pry(main)> i.name_repeats_error?
=> nil
Huh? Oh, right--the model hasn't been validated yet. Remember, as it stands right now, the method is added during validation.
(This may be a Bad Idea--it might be better to add the method to the model in some other way, but unless we add it manually, or add it to all our models, create a method our models can use to get the method from the same module our validator is in, or...? this (for now!) seems the way most-tied-to-the-validator, which was one of the things I wanted.)
We'll use create instead for illustration and keep creating items with the same name. Once we have two with the same name, additional items with the same name should have a validation error.
pry(main)> i = Item.create(:name => 'wat!')
=> #<Item id: 7, name: "wat!", ...>
pry(main)> i.name_repeats_error?
=> false
pry(main)> i = Item.create(:name => 'wat!')
=> #<Item id: 8, name: "wat!", ...>
pry(main)> i.name_repeats_error?
=> false
pry(main)> i = Item.create(:name => 'wat!')
=> #<Item id: nil, name: "wat!", ...>
pry(main)> i.name_repeats_error?
=> true
That, as they say, is that.
For now.
For now, I want simple boolean methods on the model to encapsulate the error condition. I don't want to write them by hand; I want the validator itself to dictate the interface. For example, if I'm validating an "email" property that can only repeat n times on a given day, I'd like to have an email_repeats_error? method available in the model, returning what we'd expect.
This will be developed in two steps: first, as a simple library (makes tweaking easier, at least for me). Second, as a standalone gem (the way it should be). Naturally, this led to a brief WTF spike as I couldn't figure out how to get the library to expose the validator properly.
Loading the Library
Rails 3.0 changed how libraries are loaded, at least a little bit. I did two things to get things loading from an arbitrarily-named file in the /lib directory. First in my application.rb file, I added the /lib directory to the autoload path.
module RepeatsValidatorWork
class Application < Rails::Application
config.autoload_paths += %W(#{config.root}/lib)
# auto-require; see next code fragment.
# ... etc ...
Second, I require the library manually since... well, I'm not 100% sure I understand why, although this blog entry pointed me in the right direction. For testing purposes, this is fine--it might not be a great idea in general. Once it's in a gem, it won't matter anyway.
config.autoload_paths.each do |path|
Dir["#{path}/*.rb"].each do |file|
puts "Auto-requiring #{file}..."
require file
end
end
The Validator Proper
We'll work a bit backwards to get to the final implementation--starting with the familiar and common, ending with tasty snacks.
I'd like to configure the validator as below. For now, we'll just use a lambda to determine how to count the repeats--in the future we might want shortcuts for common use cases. All mine have been different so far, so a lambda it is. We'll pass it the same things a custom validator normally gets (see next code block).
class Item < ActiveRecord::Base
validates :name,
:presence => true,
:repeats => {
:upto => 2,
:how_count => lambda { |rec, attr, val|
Item.count(:conditions => ['name=?', val])
}
}
end
The validator is an ActiveModel::EachValidator subclass. We'll save the "upto" and "how_count" options in the class's initialize method. Since we'll care which model attributes are using the validator, we'll save that before calling super: Rails initializes that option, and plucks it out again in the base class. If we want 'em, we gotta act fast.
The validate_each method uses a saved copy of the "upto" option, runs the "how_count" lambda, and compares the values.
def initialize(options)
@attributes = options[:attributes]
super
@how_count = options[:how_count]
@upto = options[:upto]
end
def validate_each(record, attr, value)
err = false
if @how_count.call(record, attr, value) >= @upto
record.errors[attr] << (options[:message] \
|| "repeats too much")
err = true
end
record.instance_variable_set \
"@#{attr}_repeats_error", err
end
The last line of the method is important: it sets an instance property to true or false depending on whether or not we had a repeats violation. Now we just need to access that in an attribute-specific method for every attribute that uses this validator.
The final bit of pseudo-magic occurs in our class's setup method. Turns out that Rails validation internals call a setup method in each of the registered validators that defines one. (Discovered while looking through Rails source--I can't emphasize the usefulness of reading through source code.) The argument is the class of the model--if that sounds handy, you're on to something.
The final bit of pseudo-magic occurs in our class's setup method. Turns out that Rails validation internals call a setup method in each of the registered validators that defines one. (Discovered while looking through Rails source--I can't emphasize the usefulness of reading through source code.) The argument is the class of the model--if that sounds handy, you're on to something.
def setup(clazz)
clazz.class_eval @attributes.inject("") {|s, attr| s += <<END
def #{attr}_repeats_error?
@#{attr}_repeats_error
end
END
end
This code is less-dense than it seems (it seems dense to me, I guess). In a nutshell, we're looping over our saved attributes (in @attributes) and using inject to build up a string containing everything between the two upper-case ENDs (except for the closing bracket). (Didn't know that was legal syntax.) If it makes it easier to visualize, think of it like this:
def plain_ol_setup(clazz)
s = ""
@attributes.each do |attr|
s += """
def #{attr}_repeats_error?
@#{attr}_repeats_error
end
"""
end
clazz.class_eval s
end
If it didn't make sense before, does it now? We're adding a method
The only thing left to do is to tell Rails that our validator is alive and we wants me some; this is just a single line at the bottom of our library file. (The validator code above lives in some nested modules.)
ActiveModel::Validations.__send__(:include, Newton::Validator)
Here's the complete code in a gist (also appended at the bottom of the post).
So, does it work?
pry(main)> i = Item.new(:name => 'wat!')
=> #
pry(main)> i.name_repeats_error?
=> nil
Huh? Oh, right--the model hasn't been validated yet. Remember, as it stands right now, the method is added during validation.
(This may be a Bad Idea--it might be better to add the method to the model in some other way, but unless we add it manually, or add it to all our models, create a method our models can use to get the method from the same module our validator is in, or...? this (for now!) seems the way most-tied-to-the-validator, which was one of the things I wanted.)
We'll use create instead for illustration and keep creating items with the same name. Once we have two with the same name, additional items with the same name should have a validation error.
pry(main)> i = Item.create(:name => 'wat!')
=> #<Item id: 7, name: "wat!", ...>
pry(main)> i.name_repeats_error?
=> false
pry(main)> i = Item.create(:name => 'wat!')
=> #<Item id: 8, name: "wat!", ...>
pry(main)> i.name_repeats_error?
=> false
pry(main)> i = Item.create(:name => 'wat!')
=> #<Item id: nil, name: "wat!", ...>
pry(main)> i.name_repeats_error?
=> true
That, as they say, is that.
For now.
Tuesday, September 06, 2011
Simple Ajax property toggle in Rails 3.0
Entry-level overview of one way to add trivial Ajax functionality to a Rails 3.0 app, originally written for a specific audience. The repository is on github.
Original Model Index View
Update the Template
Let's say we have an Article model with an "approved" flag. We need to be able to toggle this flag. Normal scaffolding would have us view the article, click a checkbox, and submit. We'll keep that functionality, but add a simple Ajax-based toggle on the articles index page.
Model Generation
rails g scaffold Article name:string approved:boolean
Original Model Index View
The default scaffolding includes the following chunk, repeated for each article.
<td><%= article.name %></td> <td><%= article.approved %></td> ...
An Approving Helper
"True" and "false" are a yucky user experience, what we really want is "approved" and "un-approved". We'll think ahead, and turn it instead into text suitable for a command link. We could also use images, but we'll stick with text for now.
def approve_link_text(approvable) approvable.approved? ? 'Un-approve' : 'Approve' end
Two quick things about how this was written.
1) It's not tied to articles; it'll quack at anything with an "approved?" method.
2) The parameter is named something that provides a hint to future devs, more useful in an IDE that provides popup help.
Add a Method to the ArticlesController to Toggle Approval Status
Two-step process: first, add a method to the articles resources routing.
resources :articles do get 'toggle_approve', :on => :member end
Then the method itself (this is not the final version).
def toggle_approve @a = Article.find(params[:id]) @a.toggle!(:approved) render :nothing => true end
Update the Template
Our first step will just toggle the attribute without any feedback. It's actually a one-liner, just make the true/false "approved" text from before be a link to our new action.
<%= link_to approve_link_text(article),
toggle_approve_article_path(article),
:remote => true %>
The :remote => true turns it into an Ajax request. Not too shabby.
If we refresh the page after clicking the link we'll see that the text has changed. Approved articles will have an "Un-approve" link, un-approved articles an "Approve" link. Clicky-clicky, it does what we expect.
But refreshing is deeply unsatisfying.
Dynamic Feedback, Part 1
Remember when fadey-yellow things were cool? Yeah, we're all about that.
In order to change stuff on our page, we have to be able to access the appropriate DOM elements. Let's say we'd like to highlight the entire row when we toggle an article's approval status, and change the link text.
We'll use "article_n" for the article rows, and "approval_link_n" for the links.
<% @articles.each do |article| %>
<%= article.name %>
<%= link_to approve_link_text(@article), toggle_approve_article_path(@article), :remote => true, :id => "approve_link_#{@article.id}" %>
Dynamic Feedback, Part 2
Now we can access the DOM elements we care about on a per-article basis. How do we make them change? By creating a JavaScript template for our action, just like we usually create HTML templates. Rails will execute the returned JavaScript. The JavaScript template can contain ERb constructs, also just like HTML templates.
Note that some people don't like creating JavaScript this way. An alternative is to create DOM elements that our JavaScript can pull from. That's fine, but honestly, for simple things like this, I don't have a big problem with doing it the "old-fashioned way".
Our action is called "toggle_approve". We name JavaScript templates the same way we do ERb templates, so we'll create a toggle_approve.js.erb.
$("#approve_link_<%= @article.id %>").text("<%= approve_link_text(@article) %>");
$("#article_<%= @article.id %>").effect("highlight");
Line 1 sets the link text to Approve/Un-approve using the same helper we used in the HTML template.
Line 2 highlights the row we just updated.
That's it--we no longer have to refresh our page--the text of our link changes after the property is toggled, the row is highlighted, and we're all set!
Subscribe to:
Posts (Atom)








