Have you ever needed an open-ended Date range in Ruby? Well, check this out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Pretty rad stuff.
Have you ever needed an open-ended Date range in Ruby? Well, check this out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Pretty rad stuff.
Here’s a run of the mill test for a Rails controller action:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
This isn’t a horrible test, but there’s a common antipattern where we are requesting the resource: we’re explicitly using the record’s database ID, line 10. All ActiveRecord objects have a URI friendly name via the ActiveModel::Naming#to_param method. Let’s rewrite our test to use this method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
This insulates us from changes to how a resource might be represented in the URI, and more accruately represents how Rails internally handles your resource with URI helpers. For more of the gory details, check out ActionDispatch::Routing::PolymorphicRoutes.
Ah, January. It’s a new year, and a time wherein we set new goals for the year. An important part of goal setting is visibility – not only being reminded of your goals, but being able to track and measure your progress towards attaining them.
I mostly do object oriented programming using Ruby on a day-to-day basis. It’s high time I learn a functional language. The paradigm shift will not only help me think in new ways, but it will open up new avenues of solving problems.
Here are some candidate languages:
I’ve been reading Learn You a Haskell, and I’m quite enjoying it, but Clojure has a certain appeal to me I can’t quite put my finger on yet.
I primarily work on HTTP APIs, but I don’t feel that I understand enough about HTTP, TCP/IP, and networking in general. I need to rectify this.
I want to ensure my learnings have been captured and thought out, so I intend on blogging about them much more frequently than I have in the past. This article, in fact, is the first step towards this goal.
Back in December I did a presentation for the Toronto Ruby Brigade introducing Git, and its core concepts. Here are my slides:
DRY code makes me a happy camper, so when I see patterns in my regular expressions in my Cucumber stories, I get a little agitated. These patterns come up quick frequently if you are using the explicit record retrieval pattern in your stories. Here are some examples of the steps we want to refine:
1 2 3 4 5 6 7 8 9 10 | |
Note the "(["]+)" and (?:st|nd|rd|th) patterns. Let’s extract those patterns so that we never have to type them out again.
The key to this is to recognize that Cucumber automatically loads all Ruby files in the “support” and “step_definitions” directories. Let’s create a file called “constants.rb” in “support”. Here’s mine:
We can now rewrite our step definitions above to use these constants:
1 2 3 4 5 6 7 8 9 10 | |
Now we have cleaner steps, with less repetition, and they should take us a little less time to write out in the future. Use, abuse and fork my module above.
Vim is my text editor of choice. It doesn’t have all of the niceties of TextMate, so you often have to assemble them yourself through user scripts and configuration. One of those areas that Vim needed a little assistance in was its support of Markdown. The following are some quick tips for improving Vim’s handling of Markdown.
Ben Williams has written a fairly good syntax definition for Markdown. It’s unfortunately not on Vim’s script index, so you’ll just have to grab it from his blog.
Chances are your package management system has Discount available. Install it. Once you do so, you’ll have a command line tool called “markdown” at your disposal. Once you do so, open up your vimrc and add the following to it:
1 2 3 | |
This will generate a preview of your Markdown file that you are currently viewing. If you’re really clever, you’ll also add “*.mkd.html” to your gitignore file so that you don’t have to worry about the generated preview.
Head on over to Vim Casts to learn about how to use soft word wrapping in your documents. I find soft wrapped text much more natural looking when writing documents.
The below is kept merely for historical purposes. You should not use the techniques described below as Rails’ Asset Pipeline is a much better option
Sometimes, in larger Rails projects, we want to group together JavaScript or CSS files. Let’s use the the Uploadify project to illustrate how we can use a seldom discussed Rails feature to simplify inclusion of CSS and JavaScript files that are used in conjunction with each other: ActionView::Helpers::AssetTagHelper.
Rails defines a set of default JavaScript files to include in our view when we use #javascript_include_tag(:default). From the Rails documentation we can see an example of the output:
1 2 3 4 5 | |
This is called an expansion. We have expansions for JavaScript and Stylesheets. We can use with both #javascript_include_tag and #stylesheet_link_tag. We can also register our own. It’s through expansions that we can bundle together JavaScript and and CSS files.
Registering expansions is done through two different methods: ActionView::Helpers::AssetTagHelper.register_javascript_expansion, and ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion. Each of these methods takes a Hash as an argument which points to a list of asset names (e.g. “jquery.js”).
Let’s look at how we would define the default :default for our JavaScript bundle:
1 2 3 4 5 6 | |
That’s a little verbose for setting the default, so Rails provides us ActionView::Helpers::AssetTagHelper.register_javascript_include_default. Let’s try this again:
1 2 3 4 5 6 | |
Let’s set a default using jQuery:
1 2 3 4 | |
Easy as pie! Let’s setup expansions for Uploadify:
1 2 3 4 5 6 7 8 | |
Now we can easily maintain asset bundles. Cool, eh?
In my last post I discussed different ways to define objects using the CommonJS module system as implemented in Node.js. There’s one particular example I wanted to revisit:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
I had decried this form as awkward as illustrated by this scenario:
1 2 3 4 5 6 | |
I was reading some of the source code for the new 0.1.90 release of Node, and I saw an example that made me realize we’re using this object wrong. Here’s a better way to use the above definition:
1 2 3 4 5 6 | |
Look at that! We’ve got traditional style objects without polluting the global object.
I’ve been playing with Node.js lately. Node is an asynchronous, JavaScript library for building server-side applications that uses CommonJS conventions. One of these conventions, modules, has confused me for quite a while now. Let’s take a closer look at them.
We’re going to be using Node version 0.1.33 in this article. Let’s get to it.
Let’s build some functions to deal with circles. Here’s some code you can find in the Node documentation:
1 2 3 4 5 6 7 8 9 | |
Okay. Now let’s use this in Node. If you’re like me, your first session in Node will look something like this:
1 2 3 4 5 6 7 8 9 | |
Coming from a Ruby background, I would have expected methods I required to be available to me. That’s not the case with CommonJS modules. Let’s take a look at how you should have used this module:
1 2 3 4 5 6 | |
Success! We can now do what math that every grade four student can do. Let’s try something else:
1 2 | |
Nada! Node doesn’t spell it out, but we’ve just called a property of circle that doesn’t exist. Let’s verify:
1 2 3 | |
Is the above a little confusing for you? It sure was for me at first. If you read the Node documentation, you’ll see a nugget that might provide a clue. Check this out:
To export an object, add to the special exports object. (Alternatively, one can use this instead of exports.)
So, we can rewrite our circle like this:
1 2 3 4 5 6 7 8 9 | |
And what is this? Well, it’s your object! So, we can think of this module as this:
1 2 3 4 5 6 7 8 9 10 11 | |
You’re seen this before. It’s a JavaScrip object. So modules are really nothing more than objects. As a short form, we’re just defining the body of the object. Now we have a mental model of how CommonJS modules work. In fact, we’d use this object just like we used our circle functions with Node:
1 2 3 | |
You, probably like me, come from an Object-Oriented background. Let’s look at how we’d write our circle in my favourite language, Ruby.
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
And to use it…
1 2 3 4 | |
If you’re anything like me, you’d be tempted to do something like this when you first try out Node:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
What happens when we try to use this module?
1 2 3 4 5 6 | |
Hmm. Awkward. We can get around this simple by removing the var, and dropping exports as follows:
1 2 3 4 5 6 7 8 9 10 11 | |
And we can use it like we did with our Ruby object:
1 2 3 4 5 6 7 8 | |
Our Circle object was defined on the global object. So, surprise, surprise, it’s globally available to us too.
However, we’ve seen that we don’t really need to do this most of the time. We can simply write the body of our function and export the API we wish to make public.
Let’s look at what we’ve learned:
export it.area can access the value of PI, but we couldn’t. In this way, PI is private.Try writing a module in Node. Practice what we’ve learned.
In reading comments on Reddit, I wanted to make note of masklinn’s comment:
The piece of code at the end is downright dangerous (because it mucks up
global objects, potentially overwriting properties in other modules), and
there’s nothing object oriented about ruby’s behavior, if anything it’s
abject-oriented. Ruby’s require is akin’s to PHP’s include or C’s very own
#include, it just dumps the required file in the local namespace and executes
it.Node.js’s original behavior, where require actually creates and returns a
full-fledged object is infinitely cleaner and far more object-oriented.
Masklinn is absolutely correct! In case it was entirely clear above, I feel it important to reiterate that this is not a good way to make objects when using Node. It’s dangerous, and unnecessary. Try to think of the file as the contents of your class’ body, and the exported methods as the public interface.
This is my blog. This was going to be a mission statement. Instead I’ve decided to just ramble incoherently for a bit and suggest that I may eventually have content.