23 Aug 2007, 9:08am
/dev/rails
by

Comments Off

Dr. Nic Sells His Baby

Well, one of them anyone and maybe not the one he loves the most.

All-around pretty smart Rails-guru guy Dr. Nic is selling his Rails-based MyConfPlan site for charity so he can attend a conference session:

Why? Because all the money paid by the winner is going to the Chad Fowler and Marcel Molina Jr fund for all-things Humanitarian, and so I can go to their Testing Training Day on the 17th of September in Berlin. Minimum donation is $75.

That’s right, the winner’s money could be entirely tax-deductible as its all going to charity. (You get the site’s code base and the myconfplan.com domain (cost of transfer is yours) are yours. I get entry to the workshop.

If it raises $500 then you are donating $500. If it raises $2,000,000 then you are donating $2×10^6.

I like it. Rather than let an interesting niche site languish on the vine it gets sold off to someone who can either learn from it or extend it, Dr. Nic gets some testing edumacation, and the charity gets some cash.

As of this posting bidding is up to AU $355. Not too shabby.

MyConfPlan in action.

16 Aug 2007, 12:14pm
/dev/rails /dev/random
by

3 comments

Handy bash Aliases

Today I finally got around to editing my .bash_profile to include the following aliases. I find they make general command line use more pleasant.

The first one remaps ls to show a useful amount of information. Never in my lifetime of using computers have I ever wanted ls to output the way it does by default.

The next two just save a couple of characters by removing the cd from their respective command and optimizing the dual backstep (a cool shell script would be one that counts the number of consecutive periods and cd's back that many directories – 1).

The last one is Rails-specific and simply fires up the default server from your Rails project directory.

alias ls=’ls -alh’
alias ..=’cd ..’
alias …=’cd ../..’
alias home=’cd ~’

alias ss=’script/server’

Update: See Sam’s suggestions for fast ls variants below.

8 Aug 2007, 11:45pm
/dev/rails
by

Comments Off

Rails ActiveRecord Instances and ‘super’

For a class of objects in my database I extract data from one or two ways: the first directly from the database via ActiveRecord, the second from Amazon using Amazon::Ecs.

When the asset calls to Amazon to populate its properties I want to use the Amazon-provided data. When I refrence the asset without calling to Amazon (ie: the data has been cached) then I want to reference AR's properties directly. I don't want to have to make two calls dependent upon the data's source location.

In otherwords, I always want to be able to call

book.title

no matter what.

Turns out ActiveRecord makes this pretty easy:

RUBY:
  1. def title
  2.   return @atts ? @atts.get( 'title' ) || "" : super
  3. end

If there are attributes and an attribute called "title" exists, return that. If attributes don't exist then call the super class's title() which contains the data extracted from the database.

Pretty cool ActiveRecord, pretty cool.

19 Jul 2007, 3:14pm
/dev/rails
by

Comments Off

Where Does “– tables()” Come From?

When starting up one of my Rails apps the initial console output looks like this:

=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
-- tables()
-> 0.0576s
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart).
** Rails signals registered. HUP => reload (without restart). It might not work well.
** Mongrel available at 0.0.0.0:3000
** Use CTRL-C to stop.

Note that little chunk in the middle that shows how long it took to read the table structure from the database:

-- tables()
-> 0.0576s

Where the heck does that come from??

Of the three Rails apps I currently have in development that only gets output in one of them. The config and environment files are the same across all three platforms (save for database access credentials) and yet only one of them spits out that data.

It's really messing up the production server since Apache attempts to jam it into the HTTP header which causes a 500 error, as one might expect.

Anyone know? A plugin? Lesser-known config option? Elves? I am stymied.

10 Jul 2007, 4:32pm
/dev/rails
by

Comments Off

Solving the Depricated @Flash Warning

Long long ago I ran into an issue in which my use of flash always generated a warning, though I thought I was implementing it properly.

In the comments Dmitry finally solved the mystery:

Don’t name your flash partial “_flash.rhtml”, name it something else, like “_flash_box.rhtml”. This is a known bug.

And with that, no more warnings.

12 Jun 2007, 1:28am
/dev/rails /dev/ruby
by

Comments Off

The Power of rake

rake is one of those little things about Ruby on Rails that I suspect most of take completely for granted, running the odd rake tast without really ever thinking much about it. Turns out rake is pretty damned cool.

Gregg over on Rails Envy has written a very nice intro to rake in Ruby on Rails Rake Tutorial (aka. How rake turned me into an alchoholic) :

In this article we're going to discover why Rake was created, and how it can help our Rails applications. By the end you should be able to write your own tasks, and learn how to get piss drunk using rake in no less then three steps.

He's written well enough that by about midway down the article I was already thinking of ways to use rake to do some of the unpleasant maintenance tasks every site needs that I was consequently putting off thinking about. rake: not bad at all.

23 May 2007, 5:21pm
/dev/rails
by

3 comments

options_for_select and <<

It's fairly common to want to grab a bunch of unique database entries and display them as a set of form option tags. Rails has which does quite a nice job of it.

But what to do when I also want to include items not in the database, such as "all" or "none"?

RUBY:
  1. <%= select_tag :activity, options_for_select( ( Activity.find( :all ).collect{ |x| [ x.name, x.id ] } ).uniq <<[ "all", 0 ] ).sort, { :o nchange => "submit();" } %>

In this case I'm appending "all" onto the hash that constitutes the options.

(Note that it's probably better to have the uniq be in the SQL as DISTINCT but that's for another day.)

3 May 2007, 10:59am
/dev/rails
by

3 comments

‘rake db:migrate’ on Production Server

When the time comes to deploy on a production server, the following sets up the database:

rake db:migrate RAILS_ENV=production

13 Apr 2007, 5:47pm
/dev/rails
by

Comments Off

in_place_editor_field as a textarea

You want to use in-place editing but you've got a large amount of text and the default textfield created by in_place_editor_field just isn't large enough? Set the rows property:

RUBY:
  1. <%= @activity_item_note = note; in_place_editor_field :activity_item_note, :note, {}, :url => { :controller => 'activity_item_note', :action => 'set_note_text', :id => note.id }, :rows => 4 %>

When the rows property is set to any value greater than 1, in_place_editor_field renders a textarea instead of a textfield.

13 Apr 2007, 4:08pm
/dev/rails
by

2 comments

in_place_edit_for, in_place_editor_field and Complex Cases

In-place editing of content is a very cool feature and for the most part dead-simple to do in Rails. Unfortunately all the examples around, including the ones in Rails Recipes, assume you'll be implementing this functionality in only the simplest of cases, usually when displaying just that editable data on the page.

In my case I have much more complex requirements - an instance of an event can have many notes attached to the event. If the author of the note is viewing the event they should be able to edit any notes they've written, and edit them in the page using in_place_editor_field.

In this instance the controller for the notes is different than the controller for the page.

Here's how I finally managed to get it to work, using the editing of a note title as an example.

First, add the following line to the note controller:

RUBY:
  1. class ActivityItemNoteController <ApplicationController
  2.     in_place_edit_for :activity_item_note, :title

This automagically sets up a function in the controller called set_activity_item_note_title for us.

Second, in the view, which is app/views/activity/show.rhtml and thus controlled by the ActivityController I display all notes via:

RUBY:
  1. <% activity_item.activity_item_notes.each do |note| %>
  2. ...
  3. <% end %>

At this point every other example of in_place_editor_field would tell you to add the following to your page to create an in-place editor:

RUBY:
  1. <%= in_place_editor_for :note, :title %>

or some variant of that (or something even worse if the author is building their example off of Rail's scaffolding). But that won't work in this case for many, many reasons which you have probably already discovered for yourself if you're reading this.

So, third, I customized the in_place_editor_for like so:

RUBY:
  1. <%= @activity_item_note = note; in_place_editor_field :activity_item_note, :title, {}, :url => { :controller => 'activity_item_note', :action => 'set_activity_item_note_title', :id => note.id } %>

@activity_item_note = note; - set our iteration as an instance variable instead, since in_place_editor_for requires one of these to work (sigh).

:title - define the property to be edited.

:url => { :controller => 'activity_item_note', :action => 'set_activity_item_note_title', :id => note.id } - take back control of the controller and point it to the one that should handle the edit. Add the name of the method and make sure the id of the note being edited is in there as well.

And that does it.

Warning: Because we're passing the id in the URL there's pretty much nothing in this to stop someone from hijacking the URL, injecting their own id's and running rampant through the database, mucking with titles as they see fit. The default set_activity_item_note_title created when I defined in_place_edit_for :activity_item_note, :title has no provision to manage this sort of authentication. As such it is probably a good idea to wrap the auto-generated functions with your own code to manage authentication, something like:

RUBY:
  1. note = ActivityItemNote.find( params[:id] )
  2.   if @user.id == note.user_id
  3.     # pass along to built-in 'set_activity_item_note_title' here
  4.   else
  5.     # scold the user for trying to edit someone else's note
  6.   end

In my case a simple version of this is:

RUBY:
  1. def set_note_title()
  2.     begin
  3.       note = ActivityItemNote.find( params[:id] )
  4.       if nil != note
  5.         note.user_id == @user.id ? set_activity_item_note_title : render( :text => note.title )
  6.       end
  7.     rescue
  8.       render :text => ' --- '
  9.     end
  10.   end