Rails

Rebecca NessonGrowing the Ranks of Female Devs

Rebecca Nesson posted on Thursday, September 6th, 2012 | Rails, Ruby, Ruby on Rails | 1 Comment

At PRX I am the only woman on a team of six.  With a team that size, it could be a coincidence that I’m the only one.  But it is not.  In most companies with six developers, zero would be female.  I’m here at PRX because of my skills but also because PRX cares about having and encouraging a diverse workplace.  We took that beyond our office a few weeks ago when we participated in a full-day free workshop focused on teaching Ruby on Rails development to interested women.  In one evening and one long day we taught 44 students enough so that by the end of the workshop they had each deployed their own web application live on the Internet.  You can read an interesting and thorough recap of the event, replete with pictures, feedback, etc., here.  Also, if you’re interested in participating, we plan to do another workshop with the same format later this fall.  You can find out more on our site.

PRXers had roles in every aspect of the workshop.  Dan Choi, a former PRX employee and contractor and permanent PRX friend, was the driving force behind the workshop and the main organizer.  We developed the curriculum with a team of volunteers from BostonRB including Andrew K., Chris R. and me from the PRX team.  I was the main lecturer/teacher for the workshop,  Andrew was a teaching assistant and lecturer, and Kathryn Bennett, a tech intern at PRX, also TA’ed. Genevieve, who works on the content side of PRX and does a lot of work in our content management system, participated as a student.  And PRX backed the event financially as one of the sponsors.

The main goal of the event was to encourage people with no previous experience to get involved with Ruby/Rails development, and I believe we succeeded.  But for me there was another positive outcome.  In putting on the event we pulled together a team of volunteers, teachers, and sponsors who all see the importance of an inclusive, diverse community of developers.  At this one event I met and worked with over ten other female Ruby/Rails developers many of whom work in places where they are the only girl.  I had only met two of them before, and I was frankly but happily surprised that there were so many of us.  It helped show me that the community we were envisioning is already nascent among the women who are working as developers and the colleagues, companies, and organizations that are supporting us.

I’m proud of what we accomplished and of PRX for having a strong hand in it.

Chris RhodenPolymorphic Associations and Abilities

Chris Rhoden posted on Monday, November 1st, 2010 | Rails, Ruby | 8 Comments

I recently had a conversation with an old friend who is in the process of learning Ruby on Rails. He had run into a problem with polymorphic associations and I recommended he try something I had done for another project using polymorphic associations. It turns out that it was a good solution to the problem, and since I haven’t seen the pattern talked about elsewhere, I thought I should get it down on paper.

For the sake of example, let’s say we’re building a Tumblr clone, where the polymorphic association lives inside of a Post model, and the different kinds of posts are all models unto themselves. We could use single table inheritance, but maybe the models vary enough or the storage method differs enough that that’s a bad idea. For that matter, Single Table Inheritance often just feels wrong.

Simplicity will work best in this case, so let’s say that every post has a title, timestamps, and belongs to a user.

# db/migrate/001_create_posts.rb
class CreatePosts < ActiveRecord::Migration
  def self.up
    create_table :posts do |t|
      t.string :title
      t.references :user
      t.integer :postable_id
      t.string   :postable_type
      t.timestamps
    end
  end

  def self.down
    drop_table :posts
  end
end
# app/models/post.rb
class Post < ActiveRecord::Base
  belongs_to :user
  belongs_to :postable, :polymorphic => true
end

Before we even get into the different kinds of posts we might want to make, let’s abstract this model so that we can tack it onto nearly any model in our application. How? A little bit of metaprogramming.

# lib/postable.rb
module Postable
  def self.included(klass)
    klass.instance_eval do
      has_one :post, :as => :postable
      alias_method_chain :post, :autocreate

      [:title, :user, :created_at, :updated_at].each do |method|
        delegate method, "#{method}=", :to => :post
      end
    end
  end

  def post_with_autocreate
    post_without_autocreate || build_post
  end
end

What does this get us? Well, in just a few lines of code, we have saved ourselves from really having to think about this problem very hard again. Consider creating two kinds of posts, something like a quote post and a freeform text post (called a blob, in this example):

# db/migrate/002_create_quotes_and_blobs.rb
class CreateQuotesAndBlobs < ActiveRecord::Migration
  def self.up
    create_table :quotes do |t|
      t.string :quotee
      t.text :quote
    end
    create_table :blobs do |t|
      t.text :content
    end
  end

  def self.down
    drop_table :quotes
    drop_table :blobs
  end
end

I have deliberately chosen separate interfaces for these two kinds of model so I can show off some other stuff later. But to get them posting, all we need to do is include our “Postable” module and we are up and running:

# app/models/quote.rb
class Quote < ActiveRecord::Base
  include Postable
end

# app/models/blob.rb
class Blob < ActiveRecord::Base
  include Postable
end

That’s it. We can get started immediately by creating our forms. Because of the Postable interface we have created, both models will automatically have the fields on Post (and, in fact, will work transparently thanks to delegation). The only other thing we need to think about is creating a common interface back to the individual post types from the Post model. We can do this with a helper, the model, or we can take advantage of Rails’ partial rendering and just create a views/quote/_quote.html.erb and views/blob/_blob.html.erb. Those views might look something like:

# app/views/blob/_blob.html.erb
<h2>
  <%= blob.title %>
</h2>
<div class='byline'>
  by <%= link_to blob.user.name, blob.user %> on <%= blob.created_at %>
</div>
<div class='blob-content'>
  <%= blob.content %>
</div>

I’ll leave the quote partial as an exercise for the reader.

At this point, we can put all of our posts on a single page like this:

# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.order_by('created_at DESC')
  end
end

# app/views/posts/index.html.erb
<h1>All Posts</h1>
<%- @posts.each do |post| %>
  <%= render post %>
<% end -%>

The same technique can be used in a number of situations, such as many kinds of authenticable users with one login screen or some other sort of shared attributes. What’s nice is that it is trivially extensible. You create a model with any extra fields that you need, include your module, and you’re up and running.

Support Us!

PRX

Categories & projects

Archives