Freelancing Gods 2014

God
11 Jul 2013

Gutentag: Simple Rails Tagging

The last thing the Rails ecosystem needs is another tagging gem. But I went and built one anyway… it’s called Gutentag, and perhaps worth it for the name alone (something I get an inordinate amount of happiness from).

My reasons for building Gutentag are as follows:

A tutorial example

I ran a workshop at RailsConf earlier this year (as a pair to this talk), and wanted a simple example that people could work through to have the experience of building a gem. Almost every Rails app seems to need tags, so I felt this was a great starting point – and a great way to show off how simple it is to write and publish a gem.

You can work through the tutorial yourself if you like – though keep in mind the focus is more on the process of building a gem rather than the implementation of this gem in particular.

A cleaner code example

Many gems aren’t good object-oriented citizens – and this includes most of the ones I’ve written. They’re built with long, complex classes and modules, are structured in ways that Demeter does not like, and aren’t particularly easy to extend cleanly.

I have the beginnings of a talk on how to structure gems (especially those that work with Rails) sensibly – but I’ve not yet had the opportunity to present this at any conferences.

One point that will definitely feature if I ever do get that opportunity: more and more, I like to avoid including modules into ActiveRecord and other parts of Rails – and if you peruse the source you’ll see I’m only adding the absolute minimum to ActiveRecord::Base, plus I’ve pulled out the logic around the tag names collection and resulting persistence into a separate, simple class.

I got a nice little buzz when I had Code Climate scan the source and give it an A rating without me needing to change anything.

Test-driven design

I started with tests, and wrote them in a way that made it clear how I expected the gem to behave – and then wrote the implementation to match. If you’re particularly keen, you can scan through each commit to see how the gem has evolved – I tried to keep them small and focused.

Or, just have a read through of the acceptance test files – there’s only two, so it won’t take you long.

So?

There are a large number of other tagging gems out there – and if you’re using one of those already, there’s no incentive at all to switch. I’ve used acts-as-taggable-on many times without complaints.

But Gutentag certainly works – the README outlines how you can use it – and at least people might smile every time they add it to a Gemfile. But at the end of the day, if it’s just used as an example of a simple gem done well, I’ll consider this a job well done.

21 Nov 2011

Cut and Polish: A Guide to Crafting Gems

As I mentioned here earlier in the year, a few weeks ago I had the pleasure of visiting Ukraine and speaking at the RubyC conference in Kyiv. My talk was a run through of how to build gems, some of the tools that can help, and a few best practices.

The video of my session is now online, if you’re interested:

There’s also the slides with notes, if you prefer that.

One of the questions asked towards the end was about publishing private gems, which I’d not dealt with before. However, Darcy was quick to tweet that Gemfury looks like a promising solution for those scenarios.

Please let me know if you think I’ve missed any critical elements of building and publishing gems – or if you have any further questions.

And many thanks to the RubyC team for putting together the conference and inviting me to speak – I had a great time!

05 Oct 2009

Better Gem Publishing with Gemcutter

If you’re working with Ruby and have been paying attention to Twitter or RSS feeds, then you’ve probably heard of Gemcutter. If not, it’s the latest flavour for publishing gems, and I’m finding the simplicity of it a delight.

Its appearance is doubly useful, as since GitHub has moved to Rackspace, automated gem building from projects has been disabled, perhaps never to return.

Getting Started

If you’ve not clicked the link to Gemcutter yet, let’s run down how easy it is to get it set up on your machine.

sudo gem install gemcutter
gem tumble

That’s it. Any future gem installs will look at Gemcutter’s growing library.

This doesn’t replace RubyForge or GitHub in your sources list, but it does set Gemcutter as the top priority – which is fine, as it has almost all of RubyForge’s gems ready for you anyway.

Publishing

Firstly, get yourself an account, click that confirmation email link, then hunt down a gem you want to publish, and run the following command:

gem push my-awesome-gem-0.0.1.gem

If it’s your first time, you’ll be asked for your login details, and then the gem is online and ready for anyone to download it. No waiting, no forms, no pain.

When you’ve got a new version, just run that same command again, pointing to the new gem file:

gem push my-awesome-gem-0.1.0.gem

One command. No authentication prompts. Available for everyone straight away. Awesome.

Migrating

If you’ve already got gems on RubyForge that you’d like to take ownership of on Gemcutter, it’s another one-step process:

gem migrate my-legacy-gem

You’ll be prompted for your RubyForge account name and password, and then Gemcutter does the rest.

Pretty easy, hey?

My Gems

Over this past weekend, I made Gemcutter the definitive source for all of my gems:

Incoming Confusion

There’s been some discussion about whether Gemcutter should replace the gem hosting facilities provided by Rubyforge. This may or may not happen, but it is confirmed that Gemcutter will be moving to rubygems.org soon.

Everything will still work fine via the gemcutter.org address, though, so don’t let that hold you back from diving in head first.

Hat-tip

The talented Nick Quaranto has been working hard on this for a while, and it’s great to see the Ruby community embrace Gemcutter so quickly. Here’s hoping it becomes the defacto gem source for all Ruby projects.

11 Oct 2008

Flavouring For Your Specs

One of the things I’ve tried to do with Thinking Sphinx has been to keep it friendly for a few different versions of Rails/ActiveRecord: 1.2.6, 2.0.x and 2.1.×. It’s not that easy, because I know I don’t think about which methods are pre-Rails-2.0, and which are even newer. And add on top of that the large (and very welcome) number of contributors, and it becomes a bit of a headache.

I was introduced to a potential aid for this at RailsConf EU, by fellow Australian Ian White, in the form of his library Garlic. It takes Rails plugins, instantiates them within Rails applications for each defined environment, and then runs their specs.

That in itself is pretty damn cool – except I don’t run Thinking Sphinx’s specs from within Rails – and it’s really only reliant on ActiveRecord (so it can be used in Merb). So, I’ve spent an afternoon coding up something slightly different, but in something of an acknowledgement to Ian’s library, my solution is called Ginger.

Now, it’s not exhaustively tested, but I’ve got it to the point where it runs as I would expect it to with Thinking Sphinx, so consider it ready for release.

If you’re interested in using it, here’s the basic guidelines. First up, install the gem:

sudo gem install freelancing-god-ginger --source=http://gems.github.com

(GitHub doesn’t have the gem loaded at the moment though, so you’ll have to install it manually)

git clone git://github.com/freelancing-god/ginger.git
cd ginger
gem build ginger.gemspec
sudo gem install --local ginger-1.0.0.gem

Then, in your spec_helper.rb file (or equivalent – this should work for Test::Unit as well as RSpec), add:

require 'ginger'

You’ll want to make sure that require is before any other require calls to libraries you want to test multiple versions of.

Next, you need to create a scenario file, outlining the different testing situations Ginger should run through. These details go in a file called ginger_scenarios.rb in the root of your project. Here’s my current one for Thinking Sphinx:

require 'ginger'

Ginger.configure do |config|
  config.aliases["active_record"] = "activerecord"
  
  ar_1_2_6 = Ginger::Scenario.new
  ar_1_2_6[/^active_?record$/] = "1.15.6"
  
  ar_2_0_2 = Ginger::Scenario.new
  ar_2_0_2[/^active_?record$/] = "2.0.2"
  
  ar_2_1_1 = Ginger::Scenario.new
  ar_2_1_1[/^active_?record$/] = "2.1.1"
  
  config.scenarios << ar_1_2_6 << ar_2_0_2 << ar_2_1_1
end

I’m adding three different scenarios – one for each version of ActiveRecord I want to test. I’m also adding an alias, as sometimes people have an underscore in the require calls, and while the require method isn’t fussy, the gem method is. That’s also the reason for the regular expressions, but strings will work as well.

If you want, you can have multiple gem requirements for each scenario – Ginger::Scenario is subclassed from Hash, so just add more key/value pairs as needed.

sphinx_scenario = Ginger::Scenario.new
sphinx_scenario["riddle"] = "0.9.8" 
sphinx_scenario["thinking_sphinx"] = "0.9.8"

And don’t forget to add each scenario to @config@’s collection.

The last step is the most important – running your tests through each scenario! This is done with the ginger command line tool – any arguments given to it get echoed onto rake, so in theory it should work with whatever rake task you like. I’ve only tested it with RSpec though.

ginger spec
ginger test
ginger spec:unit

This was built to scratch my itch, obviously, but happy to accept patches or suggestions. GitHub, as always, is the best way to do this – fork to your heart’s content.

11 Feb 2008

Link: smartbomb I love me some source

"As good as this is, I was really after something with less typing and smarter pants. Well tonight I cracked it and I thought I’d open the source"

02 Jan 2008

Postie - The Gem

An addition to auspostie.com, prompted by Dr Nic’s suggestion in the comments of the earlier blog post – the postie gem. It allows easy parsing of Postie search results, and also provides a command-line tool for searching.

By suburb:

postie Brunswick

By postcode:

postie 3070

To install:

sudo gem install postie

To use within your own ruby code:

require 'postie'

Postie::Locality.find("Melbourne")

Again, extremely simple, but just makes access to the data that little bit easier.

Now, what would be really cool is a Quicksilver plugin that queries the API. Any volunteers to code that up?

09 Oct 2007

Link: ActiveWarehouse: Let's Get Analytical

A library that looks really useful for when you're dealing with data to report on, as opposed to ActiveRecord models.

22 Feb 2007

Link: RubyGems User Guide | RubyGems Manuals

Tags:

Ruby doesn't load gems by default - ENV flag can be set so it does though

RssSubscribe to the RSS feed

About Freelancing Gods

Freelancing Gods is written by , who works on the web as a web developer in Melbourne, Australia, specialising in Ruby on Rails.

In case you're wondering what the likely content here will be about (besides code), keep in mind that Pat is passionate about the internet, music, politics, comedy, bringing people together, and making a difference. And pancakes.

His ego isn't as bad as you may think. Honest.

Here's more than you ever wanted to know.

Ruby on Rails Projects

Other Sites

Creative Commons Logo All original content on this site is available through a Creative Commons by-nc-sa licence.