I just published a new gem, inherited-attributes, for Active Record that works with the Ancestry gem to provide a tree data structure the ability to inherit attributes from their parent node, or farther up the tree. We’ve been using this technique for a long time to support configuring our multi-tenant application.
Once the gem is installed, its very simple to configure:
create_table :nodes, :force => true do |t|
t.string :ancestry, :index => true
class Node < ActiveRecord::Base
From there, you can access the effective attributes which look up the tree ancestry to find a value to inherit.
root = Node.create!
child = Node.create!(:parent => root, :value => 12)
grandchild = Node.create!(:parent => child)
root.effective_value # nil
child.effective_value # 12
grandchild.effective_value # 12 -- inherited from child
There are more options and examples in the gem, including has-one relationships, default values and support for enumerations.
We’ve found it helpful and writing a gem made this code much easier to test. What code do you have that would be easier to test as a gem or would be useful to others?
Today, I wrote my first Ruby on Rails gem. It was a very simple refactoring of our code that I undertook when I needed to add the same functionality to a new model and I decided to do it as a gem instead of keeping it within our project. I wanted to see how it worked and this is what I ended up with. You can follow the Rails Guide, but it didn’t cover everything I wanted to do.
Create a repository for your gem.
You can do this on github
, like I did for my gem, locally, or somewhere else.
Create a skeleton gem
The rails guide for creating a plugin has this, but the details in the guide are thin.
Rails 3.1 ships with a rails plugin new command which creates a skeleton for developing any kind of Rails extension with the ability to run integration tests using a dummy Rails application.
I used this to create a skeleton for my plugin:
This creates a skeleton gem with a dummy rails application you can use for testing your gem.
Switch to rspec
I’ve used rspec
for all my rails testing and I wanted to use it with my new gem as well. However, the generator creates a test-unit dummy application out of the box. This StackOverflow question
had a good answer that I used to switch from test-unit to rspec.
- Add rspec as a development dependency in your gemspec
- Bundle Install
- Convert from test-unit to rspec
- Modify spec_helper.rb with code taken from test_helper.rb
- Run the tests
- Commit the skeleton gem to source control
Author your gem
At this point, you have a skeleton gem that you can use to write your code. The gem I wrote added some behavior to ActiveRecord models, so I started out by generating some models in the dummy rails application located in spec/dummy and using test-driven development to build my gem.
Try it with a real project
The tests you author along with your gem are very helpful, but a time will come when you want to try your gem on your local file system with a real project. You can include a gem from the local file system with this in your gemfile:
Squash your commits
When you’ve got your gem working and you are ready to publish it, you may want to squash all your commits to the repository into a single commit.