Nested forms, hashes, checkboxes and MongoMapper

While working on my upcoming BigAuthor project, I came upon an interesting challenge that turned out to be so simple with MongoMapper that I just have to share it here. Need to create a hash of multiple filter parameters on a MongoMapper document using a form that is cleanly resource-based, using InheritedResources? It’s not as difficult as you might think…
Continue reading Nested forms, hashes, checkboxes and MongoMapper

Starting a new Rails app? Here's my skeleton...

Not meant to be a “this is what should be done” as much as a “this is what Matt uses, based largely on community popularity, best practice, and Matt’s personal tastes.”

Take it for what it is: a point of discussion.

Of course, the skeleton of any Rails app will vary from project to project, depending on needs.  Agile approach is to only add it to your framework if you actually need it right now, though some stuff tends to be easier to use (like authentication systems and databases) if you build it in up-front.  That tends to be my approach for green-fielding Rails apps.

If you’ve got some favorites that you use, feel free to post in the comments about it! I’m always interested in hearing about new stuff that makes my life easier/more fun.
Continue reading Starting a new Rails app? Here’s my skeleton…

Why use HAML (and SASS)? I already know HTML.

The title of the post is more-or-less a verbatim quote from a coworker, as well as from an unrelated colleague of mine from a previous job. I was asked that question and, to be honest, I was a little thrown both times. I didn’t actually know why I use HAML.  I guess I’d never really considered it much after I started doing everything with it.  It just seemed better and more fun.

So I spent all last night thinking about the answer.  Why use HAML?  For that matter, why use SASS either?  It’s notable, I guess, that yesterday Chris Eppstein was polling his twitter followers on whether they wanted to break SASS and HAML apart to be separate gems … clearly others out there are using one but not the other.

And I suppose it’s not enough to answer that I use HAML and SASS because other luminaries in the Ruby world swear by it.  As my Mom was fond of saying, “If all the other kids jumped off a cliff…”  So I guess that’s not entirely a valid reason.

So, here’s my attempt to coalesce my various reasons for using HAML (and SASS) into a single post, and to try and convince you why I think it’s a great idea.  And to throw a bone to Eppstein, I’ll try to make a case for why, though I have no problem with them being split into separate gems, I still believe they should always go together, just like peanut butter and grape jam.

Continue reading Why use HAML (and SASS)? I already know HTML.

Mongo Beauty #1

Frequently, while working with MongoDB and MongoMapper, I run across an implementation of something that blows me away with its beauty. This, my friends, is one of those times.

Given: a Users collection where the users’ names are stored in an Array key called name. i.e. :name => ["Patterson", "Matt"]. It can be any length, so if they want middle names or titles or whatever, it just gets stuck in there as an element on the array.

Problem: Need to create a really quick lookup to do autocomplete when someone is looking for a particular person in the database.

Solution:

  def self.named(query)
    User.all({ :name => /^#{query}.*/i })
  end

So when the user types “m” into the autocomplete field, it will quickly populate the suggestions with ["Patterson", "Matt"] and ["Magdalene", "Mary"] and ["Munchausen", "Baron"] and ["Mr.", "John", "Arbuckle"]. But it won’t pickup people with ‘m’ in the middle of any of their name components, like ["Hammer", "Captain"].

How simple is that?

UPDATE: 11 Apr 2010
As it turns out, you can make the above even faster:

  def self.named(query)
    User.all({ :name => /^#{query}/i })
  end

without the ‘.*’ bit, apparently mongo’s regex implementation gets a huge speed boost since it’s not having to parse the rest of the string once it hits a match.

Mongosphinx with MongoDB and MongoMapper

Can that title have the word ‘mongo’ in it any more times? Well, fear not, I’m about to use it even more…

So, I had to fool around a bit to get the so-called “Mongosphinx” gem working with my app architecture. Thought it might be helpful to others to demonstrate how I did it. I’ll boil it down to a generic sort of implementation. Hit the jump to see the whole bloody mess…
Continue reading Mongosphinx with MongoDB and MongoMapper

Better Bundles: HAML and SASS

I use HAML and SASS pretty heavily. And it’s nice having a good Textmate bundle with macros and proper highlighting. For whatever reason, the ‘standard’ HAML and SASS bundles kind of petered out around 2008 and didn’t really keep up with the changes in HAML and SASS properly. But that’s okay! Behold github and its community! So here’s the two forked versions of the best original bundles that I’ve found and like the most:

SASS:

git://github.com/charlesr/ruby-sass-tmbundle.git

HAML:

git://github.com/benhoskings/ruby-haml.tmbundle.git

Rails Metal + Thin = no 'each' for String?

Just solved an interesting problem when using the latest Thin web server (1.2.5) with Ruby 1.9.1 and Rails Metal.

The code in Rails Metal endpoint:

  def call(env)
    if env["PATH_INFO"] =~ /^\/tags.txt/
      request = Rack::Request.new(env)
      params = request.params
      query = params['q']
      [200, { "Content-Type" => "text/plain" }, words_from(query).join("\n")]
    else
      [404, { "Content-Type" => "text/html" }, "Not Found"]
    end
  end

Don’t worry about what words_from(query) actually does. It just returns an array of words. The deal is, I was trying to output a list of tags for use with a javascript autocompleter — one tag per line in a plain/text file for speed. Sure, sure, I could use JSON or XML or whatever, but I didn’t, because it was easier to get the javascript thing working quickly this way and I’m lazy.

Under ruby 1.8.7 with thin or webrick, this works fine. Under ruby 1.9.1 with Webrick (ugh!), this works fine. Under ruby 1.9.1, with Thin, this bombs with:

!! Unexpected error while processing request: undefined method `each’ for #<String:0x000001037abd08>

After two hours of debugging, here’s the simple fix — pass an array with one string element to the return line instead of a pure string object:

[200, { "Content-Type" => "text/plain" }, [words_from(query).join("\n")]]

Seriously? Yes. Seriously.

This makes Thin happy and prevents it from trying to enumerate a String, which doesn’t work in Ruby 1.9.

I haven’t gone back yet to see if this borks the other web servers, but I’m using Thin on this one anyway, so at the moment I don’t really care. As always, your mileage may vary.

Sweet OS X aliases

Put all this crap in your ~/.aliases file. Do it!

alias migrate="rake db:migrate db:test:prepare"
alias remigrate="rake db:migrate && rake db:migrate:redo && rake db:schema:dump db:test:prepare"
alias gadd="git add -u && git add . && git status"
alias svnprecommit="git svn rebase && rake features && rake test"
alias cuc="cucumber -r features"
alias g="git"
alias tu="ruby_test unit"
alias tf="ruby_test functional"
alias su="ruby_tu_rs unit"
alias sf="ruby_tu_rs functional"
alias ti="ruby_test integration"
alias gi="sudo gem install"
alias giv="sudo gem install -v"
alias gci="git pull --rebase && rake && git push"

# [misc]
alias l="ls -alh"
alias finder="open ."
alias grep='grep --color=auto'
alias safari='open -a Safari'

# [git]
alias gsup="git submodule update --init"
# [rails]
alias gen='ruby script/generate'
alias con="ruby script/console"
alias taildev="tail -f log/development.log"

Hooray!

Installing CRM114 on OS X Snow Leopard

Here’s what I had to do to get it working:

Install ‘tre’

- but *don’t* use macports; tried that and it bombed, instead do:

wget http://crm114.sourceforge.net/tarballs/tre-0.7.5.tar.gz
tar zxvf tre-0.7.5.tar.gz
cd tre-0.7.5
./configure
make &amp;&amp; sudo make install

Install ‘crm114′

 wget -m -np http://crm114.sourceforge.net/src/

Follow Directions!

now, follow these directions

Enjoy!