hayley 365

home

I'm in love maybe

26 Jan 2014

2014-01-26 15:37:12 -0600

You can tell I'm a geek by the fact that I spent a good chunk of my free time this weekend falling in love with a toolset.

Specifically, I finally decided to dig into Opal.

My previous plan was to get back into Dart to see if/how things have changed since they're now at version 1.0. I just couldn't do it though. I want something that is obvious as to how I can immediately jump in and more so, how I'm going to actually publish the idea once I'm ready to make it public. And apparently I'm either an idiot, or moving to version 1.0 hasn't made Dart any easier to break into for me.

So somehow I decided to just say eff it and go after Opal regardless of whether it might not be mature/stable/whatever enough to jump into.

10 hours or so later and I'm thinking I've finally found a JavaScript related toolset I can live with.

As far as I can remember, I only ran into one issue where Opal didn't work quite the same as standard Ruby and that was with the .round method. I should also mention, that as I write this, .round in Opal is only available on master, so maybe this will be fixed by the time it's part of an official release.

Specifically, in Ruby, you can do this:

7.466.round(2)
=> 7.47

In Opal, it just ignores anything in parentheses and always gives you the equivalent of 7.466.round which is 7 in this case.

Luckily, I was able to think of a workaround, which was this bit of hackery:

("%0.2f" % (7.466)).to_f
=> 7.47

As a bonus, I also learned that things like %0.2f do rounding for you, which isn't something I would've originally assumed.

Basically, all of the other hiccups I've run into, are things related to jquery and my not being very experienced with browser quirks.

Like with keyup, keydown, and keypress. Like, for instance, keypress won't "hear" things like arrow keys being pressed.

And apparently, if you're trying to mimic things like Angular's two-way binding with a form field, then you want to use a keyup. In my experience with keydown, it would generally be one character behind (presumably because it was grabbing the form value before the key had been released). So far, keyup has worked.

And then I learned that Firefox will keep form values on page refresh, which was kind of a problem because my toy app was only listening for changes. Simple enough, on page load, I just check now to see if there's already values in the form fields.

my toy app - BMI calculator

For some reason, I keep building/rebuilding this BMI calculator. The hilarious thing to me is that the I think the BMI metric is largely bull. And if you read up on it, it was never intended to be used on individuals; it was supposed to be for larger population samples where, in general, it would correlate with a person's size.

But it was a handy/fun project to build in AngularJS, specifically because I liked the idea of having calculators that would respond immediately to user input (thanks to the data binding).

So for v1 (Angular), it accepted pounds and inches as inputs and then it would tell you what your number was, what range that number put you in, and what you'd need to weigh in order to make it to the ranges above and below you.

My intention was to expand it to allow units of any type (e.g. kilos, centimeters). And more importantly, I wanted a form input field that was intelligent enough to know what unit you were inputting rather than how 99% of the forms out there just have you use a different input box depending on what type of units you want to use.

I never got around to it.

V2 was with Dart. This time, I started with having a flexible input field. I did this by writing tests around what I thought the input values might be and making sure it returned what I wanted.

However, I never even got to the part of doing the front-end. At the time, webui was on the way out, but polymer.dart wasn't very well documented. Any momentum that remained was extinguished by the unclear road ahead.

And so here we are: v3 in Opal.

As with Dart, this time I started by writing tests (to be clear, I never did write tests for the Angular version).

Frankly, I actually enjoy this method. Though I still have yet to write proper front-end tests, I like the simplicity of just being able to think of inputs and outputs before I have to think of the web way of outputting them.

For instance, when a user wants to use inches, I want them to be able to use any of the following methods to input their height:

So I basically started the project by brainstorming all of the different ways to input units. In fact, I think I basically put in like 4 or 5 hours of TDD before I even started writing HTML (or Haml in this case).

Basically, I've been writing everything in the jquery style of having elements with IDs and then doing manual data-binding. It's messy, but what I've found so far, is that I can tolerate it when I get to use the awesome-sauce that is Ruby.

The good thing / bad thing is also the lack of magic through that method. For instance, I know exactly how the two-way binding works because I implemented it by hand with listening for keyups on the form fields.

Magic is one reason I've never learned Rails. Actually, the much bigger reason is that it would be overkill for almost every single one of my projects. I use Middleman for almost everything and Sinatra if I need something that's more dynamic. See, I tend to build "dynamic" sites in Middleman by frequently updating the data and then rebuilding them and then sending them off to something like S3 to be hosted on the cheap.

At this point, I haven't yet figured out how I'd integrate this with my traditional Middleman workflow. Like, I'm thinking about how I could write an Opal project possibly in a modular way to be easily included on several different sites.

Unlike Dart, however, I have previously figured out how to get Opal projects into Middleman, so at the worst, I'll just

I'd also like to start digging into front-end testing. Frankly, for as much TDD as I do, I've written almost no front-end tests. I get burned from time to time on Cyclocane because of this (all of the web scraping has testing coverage, but the middleman side of things has zero test coverage).

In general, I'm pretty happy though. Opal is apparently stable enough for my standards. And frankly, I'm willing to take the hit from however much it will cost in disk space and bandwidth to include Opal on my projects, because I think I've finally found the toolset where I'll actually enjoy doing front-end work, rather than just suffer through it.

In fact, it was surprising to me to look at the Dart code I had written for my v2 of the BMI calculator. It was just so full of noise and boilerplate type code. Especially with the regular expression code. Ruby, by comparision, is 100 times more elegant. In fact, one of the reasons I love Ruby so much is how well integrated regular expressions feel. They feel like first class citizens in the language.

What I think is really going to determine my success with Opal is whether I'll be able to figure out how to integrate it with existing JavaScript libraries. Like Leaflet. I don't want to end up in a situation where I have tons of raw JavaScript littered in with my Opal/Ruby code.

My plan is to take some time to really dig into the source code of the current official opal projects to find out how they've wrapped native methods. I figure, even if I don't stick with Opal, it will be a worthwhile experience because I'll get to see more of how class-driven Ruby is written (all these years later, I still tend to write everything as functions, with very few classes) and of course, I'll get to see raw JavaScript which ought to be really helpful if I switch back to JS or to CoffeeScript.

For now, I'm quite excited about the possibilities and really looking forward to finally actually building some of my someday-maybe ideas.