Tag Archive: ruby: Social Memory Complex

Embedding users in accounts with Devise and Mongoid

This gist referred to by the Devise wiki is no longer accurate as far as I can tell. So I wanted to share my approach for how to use devise in a situation where user documents are embedded in account documents, especially in the scenario where your account has a subdomain assigned to it.

Obviously, the first thing you need to do is make sure you always have access to the current account as keyed by the subdomain. This means a before filter on any controller that runs under the subdomain that loads in your account. The idea is that once you load the account, you never have to pull it from the database again:

class AccountSubdomainController < ApplicationController
  before_filter :current_account

protected
  def current_account
    @account ||= params[:current_account] ||= get_account_by_subdomain
    params[:user][:current_account] = @account if params[:user]
    @account
  end

  def get_account_by_subdomain
    Account.where(:subdomain => request.subdomain.downcase).first
  end
end

If you're not using an account-specific subdomain, just modify this to pull out the account from the URL or something.

Read more...

Written on Friday, January 04, 2013
Tags: ruby, rails, devise, mongodb, mongoid
Comments

Reordering embedded documents in Mongoid

One of the great things about embedded documents in MongoDB is that you can design your "schema" according to how you're going to use the data. Ordered lists of objects is a great use for embedded documents, as you can just shove objects in an array and read them out in order. This allows one to dispense with the unpleasantness of "acts_as_list"-style approaches where you have to juggle a "position" field and do an explicit sort.

But what if you want to reorder the embedded documents? Should be simple to sort an array. Our ODM - Mongoid in this case - would never represent the embedded collection as an array and not let us work with it as an array, right?

class Container
    include Mongoid::Document
    embeds_many :items
end

class Item
    include Mongoid::Document
    embedded_in :container

    field :title, :as => String
end

c = Container.create
c.items.create :title => "first"
c.items.create :title => "second"

>> c.items
=> [#<Item _id: 4dd2d971322bcdab7c000003, title: "first", _id: BSON::ObjectId('4dd2d971322bcdab7c000003'), _type: nil>, #<Item _id: 4dd2d981322bcdab7c000004, title: "second", _id: BSON::ObjectId('4dd2d981322bcdab7c000004'), _type: nil>]
>> c.items.reverse!
=> [#<Item _id: 4dd2d981322bcdab7c000004, title: "second", _id: BSON::ObjectId('4dd2d981322bcdab7c000004'), _type: nil>, #<Item _id: 4dd2d971322bcdab7c000003, title: "first", _id: BSON::ObjectId('4dd2d971322bcdab7c000003'), _type: nil>]
>> c.save
=> true
>> c.reload.items
=> [#<Item _id: 4dd2d971322bcdab7c000003, title: "first", _id: BSON::ObjectId('4dd2d971322bcdab7c000003'), _type: nil>, #<Item _id: 4dd2d981322bcdab7c000004, title: "second", _id: BSON::ObjectId('4dd2d981322bcdab7c000004'), _type: nil>]

OK, so not that easy, but maybe this means we just need to set the new array explicitly.

Read more...

Written on Tuesday, May 17, 2011
Tags: mongodb, mongoid, ruby, rails
Comments

Treeoid
Tree hierarchies for your Mongoid::Document objects

I'm a bit late mentioning this, but I released another super-beta gem in the hopes it might help another poor soul: treeoid, the missing "acts_as_tree" library for mongoid. It couldn't be simpler, really: it gives you a "parent" accessor and a "children" collection. On top of that, it provides a scope allowing you to list a set of treeoid objects in hierarchical order, which is perfect for front end integration.

The tests are there but nominal; I'd love to see them fleshed out. I also had some ideas for making it cooler; for example, I keep an array of an object's descendants in the object, allowing me to hierarchically order objects. This opens up some novel means to simplify how I implement the parent and children accessor. Imagine this:

field :ancestry, type => Array # contains ids of all ancestors including self, already exists

# but instead of a parent_id accessor

def parent_id
  ancestry.at(-2) # the parent can be fetched from the ancestry list
end

This also allows all descendants of a given object to be easily fetched - if the id shows up in the ancestry, return it! It's this kind of out-of-the-box thinking that has really endeared MongoDB to me. I hope you can benefit from this and help me improve it. Or help with greedy. I'd love to get said help at CVREG's upcoming Why Day hackfest.

Written on Wednesday, August 11, 2010
Tags: mongoid, ruby, rails, development
Comments

Announcing greedy

This weekend I released my first ruby gem: greedy. Greedy provides a layer on top of the Google Reader API to facilitate the consumption of feed items syndicated by Google Reader for a given Google account. John Nunemaker's GoogleReader gem was the inspiration, but it used an authentication method that has been discontinued by Google. I switched to using the gdata gem.

Right now I can't figure out how to post information to the Google Reader API. Anybody who could help me figure out why my code isn't working is welcome to fork and submit pull requests - I know I'm missing something simple. When that feature works, you'll be able to use greedy to change the state of items to "shared", "read", "unread", etc. However, the code that merely consumes feed items is ready for action.

Greedy was extracted from another project that went up today, although not for the first time: leftlibertarian.org. Now that the Google Reader API stuff has been successfully extracted, the next step is to make the code that runs leftlibertarian.org into something anybody can use to publish their Google Reader stream as a website. Hopefully, that won't be too long in coming...

Written on Sunday, July 25, 2010
Tags: ruby
Comments

RailsConf Dispatch - Test Always?
How not thinking carefully about your test suite can hold you back

There were two conveniently sequential presentations today at RailsConf that reminded me of some thoughts I'd had regarding testing: Michael Feathers' talk on legacy code and Glenn Vanderberg's talk on real software engineering. It seems to me that both talks had a theme in common: what is the function of tests? Why do we want them, what role do they play from an engineering perspective in the larger process, and what precisely are they meant to indicate to us?

Michael at one point talked about the expense of 100% code coverage for tests, instead recommending we test the parts of the code that change the least and are most important. Ugly code in legacy projects has utility, he explained, and untested code is a rational response to churn. Afterwards, Glenn discussed software development in the context of engineering principles from older, more established disciplines like structural engineering, finding areas of similarity, analogy, and abject difference. However, his testing point compared experiments in code to experiments in more physical engineering fields, remarking on how relatively cheap tests are for us. I suppose the common thread I found concerned the emphasis on cost: that what it means for us to do our job well is to do it effectively, and not subordinate our conscience and creativity to a mechanical process.

For some background, I've been practicing behavior driven development for a year or two. I love the confidence that testing gives me, independent of the value to the client. Verifying that my code works is fine and all, but what lets me sleep at night is the assurance derived from approaching a problem in a rational, systemic manner. By moving in small chunks and expressing problems in terms I understand well enough to programmatically recreate, I ground myself in a real comprehension of the system I'm building at the most relevant level and stage. I avoid the confusion of jumping ahead, thinking too large scale or minutely, or making unwarranted assumptions that come back to bite.

Read more...

Written on Tuesday, June 08, 2010
Tags: ruby, rails, bdd, testing, development, railsconf
Comments

RailsConf Dispatch - Rescue Missions
Tammer Saleh on parachuting into disaster codebases

The first tutorial class at RailsConf on Rails Anti-Patterns has been phenomenal and incredibly validating given my experiences with consulting. Tammer Saleh gave a wonderful talk on how to handle troubled legacy codebases - what he calls "rescue missions". It's particularly relevant for me as much of my early freelance work centered on failing projects I was dumped into.

Because of the success of Rails, there's a lot of shitty code out there for you to fix. The harder issue is figuring out why shitty code was delivered, which can be trickier to figure out than you'd think. It can be really difficult to change the course of a project when much more than merely the code is dysfunctional.

Tammer suggested a ton of coping strategies, many of which end up being good practices for most situations. I'm sharing my cursory notes here in case others are interested. Feel free to strike up a conversation in the comments to explore these points. I'll link to the slides when they become available.

Read more...

Written on Monday, June 07, 2010
Tags: railsconf, refactoring, development, ruby, rails
Comments

GridFS with Mongoid and CarrierWave on Rails 3

Over the last week I've started a project with Rails 3 and I'm impressed. The increased configurability of the framework has not diminished its ease of use nor its core concepts in the slightest. You'll have to get used to a few new conventions, especially regarding routing, but there's lots of help out there.

Since this project is something I'm doing in my off time, I decided to experiment with MongoDB using the Mongoid framework. I had played with MongoMapper before, but always felt like I was using an ActiveRecord clone that didn't take advantage of the full capabilities of a document database and was forcing and ActiveRecord-style approach on me. With Mongoid you get has_many, has_one, and belongs_to relationships that map to MongoDB concepts like embedded documents. Mongoid is fully compatible with the ActiveModel interface for Rails3, and things like associations and nested attributes work out of the box.

I also had been hearing great things about CarrierWave from co-workers. It employs the concept of an "uploader" outside of the MVC ecosystem. The uploader handles resizing, storage, and all other details. In your model, you simply "mount" the uploader and you're golden. Of course, for this project the killer feature is the GridFS storage option, which is something I wanted to play with.

Read more...

Written on Wednesday, June 02, 2010
Tags: rails, ruby, mongodb, mongoid, carrierwave, rails3
Comments

Add Sound to Autotest on OS X

To me, development is all about communication. With clients and other developers, sure, but mostly with the computer itself. I'm trying to describe to the computer how to accomplish a task it does not have any capacity to understand or appreciate. On the other hand, the context of a given problem can be so natural to me that I have a hard time articulating it. Using autotest, I can engage in a sort of conversation with the computer, where it tells me in real time as I program whether it understands what I'm telling it or not.

A Growl notification informing me of test results is great, and I can even tell Growl to play a sound when the notification is ready. But that sound tells me to look for the notification, not whether the tests pass or fail. To make this conversation more fluid, it would be nice if I had not just visual but also audio feedback which told me immediately what the test results were, instead of having to constantly context switch to the test results.

There have been a few attempts to do this already, but they all seem so complex. I found a simple command line sound file player called afplay that makes all this trivial. In your ~/.autotest file, add the following:

Read more...

Written on Wednesday, April 14, 2010
Tags: ruby, tdd, bdd, testing
Comments

Full Disclosure

You can inspect the software that generates this blog on Github. I borrowed heavily from one developer to integrate Haml with pagination into Jekyll. It took a while (like all night) but it works. Tests are failing all over the place, though, so fork with caution.

Written on Sunday, March 14, 2010
Tags: ruby, programming
Comments

leftlibertarian.org Beta Relaunch

leftlibertarian.org is back! I've moved the site off WordPress, which was giving me too many problems. The site should be simple enough - there's no commenting, and the core functionality has nothing to do with creating content, only publishing it. So I started thinking about why I was going out and gathering / parsing feeds when Google Reader does it perfectly well, and has an API I can access.

The new site has a Google Reader account associated with it (leftlibertarian.org). Instead of going out to a list of feeds, downloading them, databasing posts, and generating web pages on requests, I just grab a JSON encoded version of my reading list as if my site were a Google Reader user and generate pages off of that! Super fast, super lightweight, super easy (once I figured out how I wanted to go about it).

The cool thing about this is that the API makes available just about all of the Google Reader features, including starring, comments, sharing, etc. The Google Reader web application is really just a front end for a rather powerful backend. Over the long run, I'd like to leverage these features to make the site more socially driven and dynamic but without needing a database or anything but a basic web server, cron, and ruby.

The site is very much beta right now. I'm using a HTML parsing library to truncate posts, so if you see anomalies there or have any other comments, let me know. admin atsign left libertarian period org

Written on Wednesday, December 30, 2009
Tags: ruby, left-libertarian
Comments

acts_as_enumerated Blowing Up Your Testing Spot?

If acts_as_enumerated classes are borking when you run your tests, here's a nasty workaround I did that just might work for you:

class MembershipStatus < ActiveRecord::Base
  if RAILS_ENV == 'test'
    def self.[](label)
      case label
      when :pending
        MembershipStatus.new(:id => 1)
      when :accepted
        MembershipStatus.new(:id => 2)
      when :denied
        MembershipStatus.new(:id => 3)
      when :invited
        MembershipStatus.new(:id => 4)
      end
    end
  else
    acts_as_enumerated
  end
end
Written on Thursday, December 24, 2009
Tags: ruby, rails, testing, development
Comments