faithfulgeek.org

Agile web development

Sprint 0 Completed!

April 6th, 2008

Tonight I finished Sprint 0 on the Ruby on Rails Blog Starter Kit. It’s not much, but it’s starting to take shape. In this sprint I implemented the following features:

There are still many, many refinements to be made across the board, but the initial work is done.

This coming week will mark the beginning of Sprint 1. The features targeted for Sprint 1 are:

These are some pretty big features, but I believe I should be able to tackle them for this sprint. I’m fairly excited about most of them, especially Akismet and Textile integration. Akismet is something I’ve wanted to play with for some time now, just to see how it’s setup & how it works. Textile will be nice because it’s going to make my posts look pretty!

Featured Code Snippet

For this sprint, I have one piece of code that I’m particularly proud of. It stems from the need to render (or do) something different based on the user’s authentication/authorization status. For example, if the user is not logged in, do not give them access to this action. Or, if the user is not an admin, show them this view, otherwise show them a different view. I accomplished this by adding two methods to my application controller: the first deals with authentication, the second with authorization. Let’s take a look:


    def for_admin_only
      unless @current_user
        redirect_to(root_url) 
      else
        yield
      end
    end

    def for_users_by_type
      if @current_user
        yield :admin 
      else
        yield :anonymous
      end
    end

These methods are consumed by the controller like so:


    for_admin_only do
      render :html => @posts
    end

    for_users_by_type do |type|
      case type
        when :anonymous
          render :html => @posts
        when :admin
          render :template => 'admin/posts/index', :html => @posts
      end
    end

In the second snippet, we call for_admin_only first, which says that if the user is logged in, then run the specified snippet of code, otherwise redirect to the homepage (this could also redirect to a 403 page, or whatever else you prefer). Next, we call for_users_by_type, which passes back a type variable saying if the user is anonymous or admin. If the user is anonymous we render the basic view, if s/he’s an admin, we render the admin index view.

So head on over to the official github repository and check out the source! It’s very pretty! (EDIT: Also, you may see a summary of these details on the project wiki)

Announcing Ruby on Rails Blog Starter Kit

April 1st, 2008

I am currently working a Ruby on Rails Blog Starter Kit. This will be an open source blog application to serve as a base for anybody else’s blog. Thus far I have been unable to find a satisfactory blogging engine written in Rails. I’ve tried a number of them, but they all seem abandoned, or at least development is quite slow. Because of this, and my constant urge to become a better Rubyist (Railsist?) I decided to write my own. However, I have no interest in writing or using a “full featured” blogging platform. I want something small, easy to use, with only the features I need, instead of the features I might use… someday. I also like looking at sample code. When I first started with Rails I would have loved a good sample application that I could customize. The Ruby on Rails Blog Starter Kit is that app.

The Process

I have decided to take a structured approach to developing the Blog Starter Kit (BSK). I will be heavily following the practices of “release early, release often” and TDD to efficiently create a stable, maintainable system. I am planning one week sprints in which I will complete a subset of the features on my blog and have them online, somewhere. I have yet to figure out the number of sprints that will be required, it will depend on my velocity, which I have yet to determine. For anyone unfamiliar with the terms I am using, a sprint is a period of implementing a feature of a product, at the end of which the team usually has a working product, whether or not it’s feature-complete. Velocity refers to the amount of time it takes a programmer to complete a feature.

The Features

This will be a fairly basic blog, with reliance on third-party plugins wherever possible. It will have basic posting features, commenting, feeds (RSS/Atom/etc?), Akismet integration for battling comment spam, adding to del.icio.us & digg, Gravatar integration, tagging, Metaweblog API integration, dynamic modules, and an admin login through OpenId for creating new posts/managing comments (edit/delete). As stated above, the focus of this blog is not creating the next great blogging platform; I’m building a very simple blog app that meets my needs. I’m opening it up to the community as a starter kit for anyone learning Rails (seasoned professionals, complete newbies, or anyone in between) to fork/customize for his/her own needs. I will not be taking feature requests. Instead, I would encourage anyone who feels this is lacking to fork it and add the features for themselves.

The Future

I’m sure over time I will add additional features as I see the need. This should be a good basic set to start off with. I could see this starter kit kick off a series of “starter kit” apps for other developers to build from. For example, who wouldn’t want a project management starter kit? I would love to see a Rails starter kit community spawn from this initial concept. However, that is the future, and the future doesn’t actually exist, so let’s concentrate on the present :).

I will begin by posting my code on github. I will do my best to update the source control regularly. I will post some more information to the project wiki, including details on what features will be in each sprint.

acts_as_currency Ruby on Rails Plugin Released!

March 26th, 2008

Some time ago I wrote an entry on using a dollar sign with fields that are stored as decimals in your database in Ruby on Rails. As of tonight, the code I showcased is now available as a plugin! More information (including robust installation instructions, as it’s hosted on git) on this plugin is available in the README. Check out the source and give it a try! As always I appreciate feedback; unfortunately, I’m having problems with comments in Mephisto at the moment, so please email me your questions/thoughts: joe at faithfulgeek dot org.

Making Routes Grow Up a Little

March 19th, 2008

When I saw Scott Hanselman’s first screencast tutorial on ASP.NET MVC Preview 2 I immediately asked “Where’s the named routes?” For those who don’t know, named routes is an extremely useful feature in Ruby on Rails that allows you to create a route and give it a name (if you don’t know what I’m talking about with the whole “route” thing, check out this screencast which goes over it).

The purpose of named routes is to define your URL in one place (the routes file) and give it a unique identifier (a name). Then, throughout the rest of your application you can get that URL by referencing the name, instead of typing the entire URL. Because of this, when your site structure changes (and let’s face it, it will), you only need to change the URL in one place, instead of all over your application. This is in keeping with the DRY principle (Don’t Repeat Yourself) that permeates Rails.

In response to my comment on his blog, Scott says that named routes are possible, but no amount of Googling has shown me how. Well, as any good developer does, I went ahead and figured it out for myself. So here it is, making your routes grow up by adding names.

The process is actually very simple. The name is an optional first parameter to the RoutesCollection.Add method called in your Application_Start. So we can define the following:


            routes.Add("send_message", new Route("message/new/{id}", new MvcRouteHandler()));

This defines a route to the “message” controller, calls the “new” action, and passes a parameter called “id”. To access this route in your view, all you have to do is call Html.RouteLink like so:


            <%= Html.RouteLink("[send a message]", "send_message") %>

and voila! You now have name routing in an ASP.NET application! It’s just getting cooler every day, isn’t it?

Making HtmlHelper.TextBox Act Like it Should!

March 18th, 2008

I was working on my ASP.NET MVC demo and tried something new. I’ve been dying to be able to create form fields just like I can in Rails and MonoRail. So in Rails I can say:


<%= text_field :title %>

and in Monorail I can say (syntax may be a little rusty, forgive me, it’s been awhile):


<%= FormHelper.TextField("employee.FirstName") %>

and both will generate the similar code (given an employee named Joe):


<input type="text" name="employee.FirstName" id="employee_FirstName" value="Joe">

Notice that the framework automatically fills the value for employee.FirstName in the textbox. This is very nice for reusability because you no longer have to conditionally pass in the value of your textbox based on whether or not FirstName is null. Using either of these two frameworks I can now reuse the EXACT SAME form control for both Add & Edit. Beautiful.

Now imagine my dismay when I typed a similar command into the ASP.NET MVC Framework:


<%= Html.TextBox("employee.FirstName") %>

and got as output (paraphrasing):


<input type="text" name="employee.FirstName" id="employee_FirstName" value="">

Notice that now the value is not inferred. Wah! I realize they are still developing heavily on this framework, but I thought I’d add some code that will do this for me. Here is an extension method you can add to your classes that will give you this desired functionality. Please note that this is VERY basic, and currently does not accept attributes. I will add it as I see the need:


        public static string TextBox(this HtmlHelper helper, string name, string nothing)
        {
            string[] object_and_method = name.Split('.');
            if (object_and_method.Length == 2)
            {
                // Get the ViewData object from the current view
                object data = helper.ViewContext.ViewData;
                // Get the particular property in question
                var properties = from 
                                     property 
                                 in 
                                    data.GetType().GetProperties() 
                                 where 
                                    property.Name.ToLower() == object_and_method[1].ToLower() 
                                 select property;
                // Find the first property that was returned above 
                //  (there will only be one property with a given name)
                var p = properties.First();
                // Get the value from the ViewData object for the given property
                object value_object = p.GetValue(data, null);
                // Default to empty string if null (for new objects)
                string value = value_object == null ? string.Empty : value_object.ToString();
                // Return the TextBox HTML
                return TextInputBuilder.TextBox(name, value, 20, 0, null);
            }

            return helper.TextBox(name, "", 20, 0, ((IDictionary<string, object>)null));

        }

As I mentioned, this is an extension method. The existing TextBox methods are also implemented as extension methods on a class called TextInputExtensions. This class has a method with the signature:


public string TextBox(this HtmlHelper helper, string htmlName)

Unfortunately, this keeps me from being able to define my own method with the same signature, therefore I added the second string parameter called “nothing”; otherwise ASP.NET throws an exception saying that my method & the afore mentioned method are ambiguous. If anyone knows a way around this, please let me know.

This was very quickly coded, so I’m sure it could be a lot better. I just wanted to show one way my desired functionality could be achieved. If you have any comments, please email them to me as my comments aren’t very stable at this point in time (joe at faithfulgeek dot org). I’d love to hear some thoughts around this!

Moving on...

March 6th, 2008

So Mephisto has been giving me some problems lately. Mainly it no longer accepts comments. That, combined with a lack of active development on the project, has led me to the decision to migrate away from Mephisto. I am in the process of designing a new blog engine in Rails for my own personal use. Keep checking here for updates and hopefully soon I’ll have a brand new blog that looks and smells much better than this one does. More to come!

Distributed Source Control with Corey Haines

February 24th, 2008

Welcome to Episode #1 of the faithfulgeek podcast! In this episode I sat down with Corey Haines to talk about Distributed Source Control Management. He gives us an overview of Bazaar (screencast coming soon), mentions Mercurial, and we also have some good tangents. Go ahead and take a listen. Feel free to leave a comment letting me know what you think of the first episode! I would love any suggestions for content you would like to see on this show!

Download here: Episode 1 (MP3) 40:42

Nate the Great and the Case of the Messy Desk

February 15th, 2008

So I’m calling this more of a pod special than a podcast. Don’t know where it’s gonna go, but take a listen and let me know what you think! If I get decent feedback, maybe I’ll put another one together, maybe on a more exciting topic ;). Anyhow, enjoy My First Podcast and leave any comments below!

Messy Desk

Download here:

Super special iTunes-based AAC format Normal, plain-Jane, everything compatible MP3 format

Update: It would appear that comments are broken in my Mephisto install. If you would like to comment, please email me at joe at faithfulgeek dot org. Thanks, sorry for any inconvenience.

My Appearance on WebDev Radio

January 27th, 2008

During the CodeMash conference, I sat down with Michael Kimsal to talk about my experiences with ASP.NET and Ruby on Rails. Thanks to Michael for the opportunity to talk about the technologies that get me excited (and for an awesome editing job)! Take a listen here: Web Dev Radio.

One correction, I noticed I called Joe O’Brien Joe O’Neil. My apologies Joe!

How to allow users to enter a dollar sign in money fields on a form using Rails

January 16th, 2008

Long title, but well worth the article:

[Update (3/27/2008): I have released this code as a plugin. Please see my entry announcing the acts_as_currency plugin.]

I’m still newbieish to Ruby on Rails. I recently had a form in which I had a field that took a monetary amount (let’s say, hourly rate). In the database (and therefore in ActiveRecord), we want to store that as a decimal type so we can perform calculations on it. However, on the front end we want the user to be able to enter $55. Unfortunately, this is not completely straightforward. Since ActiveRecord sees the type as a decimal, it will rip out the ’$’ and set anything after it to zero (0). Therefore, $55 becomes 0. That is no good! I played around with a few different ideas, trying to modify the validation of the attribute. While it seemed a good idea at the time, it did not work; this is because at the time we start validating, the salary attribute has already been cast to a decimal and we lost our data. After that I tried using a before_validation callback (thanks to Nate Klaiber for the idea), but that caused problems with my rspec test, because when I set the hourly_pay attribute it doesn’t revalidate, therefore the before_validation callback never fires.

meh.

Then I decided to consult my good friend, Google. I came across this gem from one of my tweeps, Joe O’Brien. After reading that, I was able to write:


    def hourly_pay=(hourly_pay)
        hourly_pay.gsub!(/^\$/, '') if hourly_pay =~ /^\$/
        write_attribute(:hourly_pay, hourly_pay)
    end

I reran my rspec tests, and all passed! Yay! However, I could have more currency fields in the future. Not to mention, this was a huge pain in the ass for me to figure out, and I want to save everyone else the hassle that I went through. Therefore, I used a little metaprogramming to create an acts_as_currency method for the model class:


1    class ActiveRecord::Base
2    
3           def self.acts_as_currency(*args)
4
5            args.each do |arg|
6                define_method arg.to_s + '=' do |currency_string|
7                    currency_string.gsub!(/^\$/, '') if currency_string =~ /^\$/
8                  write_attribute(arg, currency_string)
9             end
10                
11               end
12
13      end
14
15  end

Here is the line-by-line explanation, due to popular demand:

So line 1 redefines the ActiveRecord::Base class from which all ActiveRecord objects inherit.

Line 3 defines the acts_as_currency method as an instance method on the ActiveRecord::Base class. *args allows multiple arguments to be passed in a comma-delimited format.

Line 5 Loops through each argument, running the code inside do…end, with arg being the current argument in the loop.

Line 6 This is the real magic! define_method allows you to dynamically define a new method on whatever class you are currently working with. Here we use arg.to_s + '=', so in the case of our acts_as_currency :hourly_pay we are defining hourly_pay=(currency_string), which is a custom setter for the hourly_pay attribute. If we add more symbols ala acts_as_currency :hourly_pay, :tax_withheld then we’ll get more setters defined (tax_withheld=(currency_string)).

Line 7 This is the body of the method you are defining. In this case, we check if currency_string starts with $, and if so, strip it out.

Line 8 We then write this new value to the attribute already defined in the ActiveRecord model.

That’s it! Six (you read that right: 6! [that’s for you, Corso]) lines of code is all it took to add an innumerable amount of currency attributes to any ActiveRecord model. If you think you’ll have a need for it, download the code here (right-click | Save Link As…) and drop in the ‘lib’ folder of your Rails project. Eventually I may make a plugin out of it. Please note: I am not responsible for the behavior of this code in your environment; it is provided merely to help you if you can use it; if you have questions I will try to answer, but no promises :).

Anyway, with that out of the way, enjoy! If you have any suggestions, questions, whatever on this code, please comment!

How to fix divs floating outside their container

January 12th, 2008

Have you ever had two div tags floated next to each other? Don’t you love how they’re outside the container? Thanks to David Mead, I can show you the fix! Check out the code!

If you have any questions, leave them in comments. I’ll try to fumble out an answer!

Fun with Ruby.NET!

December 26th, 2007

I started really playing with the Gardens Point Ruby.NET compiler. I wrote a little script that shows the true coolness of Ruby.NET:


require 'mscorlib.dll'

#Using System.Console.WriteLine to print to the screen
System::Console.WriteLine "Hello World!" 

names = ['Joe', 'Katie', 'Bob', 'Sue', 'Ann']

names.each do |name| puts "Hello #{name}!" end

# Create a .NET ArrayList
list = System::Collections::ArrayList.new

# Add the Ruby array to the .NET ArrayList
list.AddRange names

# Iterate through ArrayList and print Hello, name to the screen using System.Console.WriteLine
0.upto list.Count-1 do |i|
  System::Console.WriteLine "Hello {0}!", list[i]
end

Enjoy!

Fun with method_missing

December 14th, 2007

If you know me, you probably know I’m learning Ruby. It’s an amazing language that just keeps getting better as I learn more. I recently started playing with method_missing, which is a method that is called when the message you are passing to a class does not exist. I wrote the following Hello World example tonight to print “Hello, ” followed by a name, in a unique way.


Hello.Joe # Prints Hello, Joe
Hello.Tom # Prints Hello, Tom
Hello.Katie # Prints Hello, Katie

The code that makes it work:


class Hello
    def self.method_missing(id, *args)
        return "Hello, #{id}" 
    end
end

Hope you and find this at least somewhat useful. If not, at least as much fun as I had writing it!

Ruby on Rails 101

December 13th, 2007

Tonight I presented an introduction to Ruby on Rails at the NEO Ruby Users Group. My goal was to show, rather than tell, so my slides don’t contain a ton of information, but the slides combined with the sample code should be a helpful reference as you get started with Rails. For those who missed the presentation, I walked through creating a basic web app to display a recipe (as in cooking). This shows off most of the major, unique features of Rails, save for Ajax & RJS templates.

Download slides

Download code

For those interested in learning more about Ruby & Ruby on Rails, check out the following resources:

And for your enjoyment, here is the Dilbert cartoon I had on the final slide, but was not fully visible due to the stupid projector cutting off my screen:

Why ALT.NET is worth it

December 13th, 2007

I’m on the altnetconf mailing list, full of great discussion about the emerging ALT.NET community. There has been a lot of debate around whether ALT.NET should be prescribing Agile methodologies, when the group states:

[bq] You’re the type of developer who uses what works while keeping an eye out for a better way. – altnetpedia

The following is the response I posted earlier today, for your consideration. Let me know your thoughts in the comments!

My thought is that ALT.NET is not about adherence or dedication to one specific process, rather a mesh of many different practices and guidance as to the best of those.

I don’t want to start a religious argument, but TDD & XP have been shown to provide value for a large number of projects in many, many different industries. If ALT.NET is going to provide guidance on the best practices for us, then it is going to suggest what we have seen work the best most often. It is up to us, the individual developers, to find areas where these practices fit into our current environment. In most cases they will, but there may be a few where they do not. If that is the case, then maybe ALT.NET in general won’t work for your organization. ALT.NET-recommended practices won’t apply to everybody (because, let’s face it, there’s no silver bullet, and if we constantly look for one, we’ll end up disappointed), but if they do to a majority, then it’s worth following.