FakeWeb; the most awesomest for stubbing HTTP content

On my new open-source project TwitterCompare I wanted to have a better way of receiving JSON data in my tests when using HTTParty.

The following calling is to verify credentials against the Twitter API using HTTparty:

get('/account/verify_credentials.json')


The get() makes a call to Net::HTTP.request. However, I don't want to request data from Twitter in my tests since I'll be running them quite frequently and it's a waste of resources to contact their servers, wait a few seconds, receive some data, and then all my tests finish 5 seconds later as well as data that may change.

The FakeWeb fork by Chris Kampmeier is what I used and it is awesome. It will:
  • Intercept calls to Net::HTTP.request
  • Check to see if the requested URL is one that needs to return test data
  • Returns test data
The interception is automatic once you require the following libraries in your spec_helper.rb:
# spec/spec_helper

require 'fake_web'
require 'open-uri'

To setup which URLs you want to be recognized and stubbed during your tests with FakeWeb do the following in your tests wherever you wish:
FakeWeb.register_uri('http://twitter.com:80/account/verify_credentials.json?', :response => '/testfiles/http_responses/verifiy.response.json.txt')
You can pass :response a string that is a path to a file to return that file or you can have it return a string.

NOTICE: The port specification in the register_uri() call.  You need to include the port for the FakeWeb.registered_uri?(url) to return TRUE on an exact match.

And that's it! 



Deploying your Webby site

I've been using webby a lot lately.  It's hot for static-like sites.  The site that I've been really digging into Webby with is TheDailyRefactoring.com.

The cool thing about webby is it's capistrano-like deployment.  You can deploy your site after generating it by using the following command:
$ webby deploy
This won't work until after you setup some constants though.  In your "Sitefile" in the root of your webby-application, you need to set the user, host, and directory of where your site is going to be hosted.

# Sitefile
SITE.user = "web"
SITE.host = ""
SITE.remote_dir = "/www/thedailyrefactoring.com"

After that, you can deploy your site immediately! 

Word to the wise, it pays to setup public-key-authentication between your servers to make this process super simple.

Blueprint CSS for the Non-designer

I know that I'm not the only developer that sucks at graphic design.  When I'm hacking on a project or attempting to actually finish something useful I always use a CSS website template while doing it from somewhere like Open-Source-Web-Design.org.  I like things to look pretty. Even if it's in development.

That's where Blueprint CSS comes into play.  I've used it on 2 little projects so far and it's marvelous.  It provides a very simple set of rules to follow to lay your site out in a grid-format, much like how a newspaper is laid out (for those of you that actually still read newspapers). 

The downside is, you still have to have a sense of style. 

Some links to help are: 

Photoshop Tutorials: http://psdtuts.com/
Get a feel for what good design is by Allan Branch's Flickr stream of good designs he comes across: http://flickr.com/photos/ispypurdydesigns

Damnit, I'm tired of testing!

I lied!  I love it and it's totally helpful in the long-run.

Bryan Liles came up with a cool acronym -- TATFT (test all the fucking time).  As soon as I heard him talk about this at ActsAsConference2008, he instantly made the best possible answer to testing.  It doesn't matter what framework you write your tests in as long as you write tests.

Below are some quick guidelines for your tests to try to make it easier for those that are getting stuck as to "how to test" or "what should my tests contain for this type of test".  By no means are they the answer to all your problems, but somewhere that you can build off of:

Model tests:
  • In rails, I would use rSpec or Test::Unit
  • STRONGLY suggest not to use instance variables
  • If you start to write any code that interacts with an object other than your model, something is wrong with your model, don't try to fix it with shitty tests
Controller tests:
  • In rails, I would use rSpec
  • rSpec Storyrunner is nice, but *I* think it's a completely different realm for those that haven't been used to writing tests for very long
  • Try not to hit the database if you can
  • When dealing with tests that MUST hit the database or SOLR or Sphinx or (OLAP Cubes for those in a Enterprise-y environment) outside of the application code, categorize them somehow to separate them from the faster running tests so you can run them at night or every hour while running your main test suite in seconds
View tests:
  • I hate view tests
  • But I do them with rSpec

association.is_working_properly?

When working with a team on a project things can get quickly out of sync. However, when working with a geographically seperated team, things can get out of sync before it even happens -- quick. With source control and high level languages of today, being disorganized amongst team members is much better than it was a few years ago, but still still happens just as much.

Things can go wrong while working on a team like this and usually do, quickly like I stated previously. One area they can go wrong is with migrations. This is where an issue can pop up when creating an association between your domain models.

manufacturer = Manufacturer.new(:name => "Chevrolet")
manufacturer.models.build(:name => "Corvette")
manufacturer.models.build(:name => "S10")
manufacturer.save


In Rails, they're supposed to just work and most people can continue building their application without testing to make sure a "model" is associated (added to) a "manufacturer". The issue is if someone on your team blindly creates a migration and checks it in because they think they're a "guru" and don't need to test or run tests before checking-in. This is a major-fail. This problem happened in my current project and stopped development which pissed me off since my pair and I had to go back and fix someone else's mistakes when we should have been able to continue on with the features we needed to implement.

When creating an associated domain model there's usually some sort of change that needs to happen to the database. This interaction or creation of, is created by a human -- you or me.  It's in the form of a migration as well.  The human element introduces a point of failure so it must be tested, even if it's something minor like adding a column that is used by the framework.

The moral of this story is, test everything if a human has changed the state of it.

PayPal Sandbox Username/Password error

Developing applications that utilize Paypal can be a bear. I've done it twice so far and for some odd reason Paypal likes to change things up frequently.

After going through the 2,000 steps to signup for a developer



trunk/vendor/plugins/activemerchant-1.3.2/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb


URLS = {
:test => { :certificate => 'https://api.beta-sandbox.paypal.com/2.0/',
:signature => 'https://api-3t.beta-sandbox.paypal.com/2.0/' },
:live => { :certificate => 'https://api-aa.paypal.com/2.0/',
:signature => 'https://api-3t.paypal.com/2.0/' }
}

Goals

Goals are a bitch. Over the years of doing research on being more productive or achieving what you really want, I've found goals to be a very powerful force. When a goal is defined in writing, it's tangible. That's why I believe so many people don't achieve what they want these days. Everyone is either too busy to write the goals down or they don't know how. I love examples and they really express what is being taught through application. So to help everyone out, here are some real goals that I made for myself when I first started consulting last year:


* Have 1 customer for atleast 3 months of work
* Atleast 10,000 in the business checking account for 1 quarter
* Not have to bill more than 30 hours a week

That was it, those 3 goals. And 1 of them was severely underestimated while the other two I blew out of the water. You can guess. Had I not written these down, I would have had nothing to shoot for. Lately my life has been filled with other things I really want to do or obtain and those have been turned into goals as well. As of late, the goals that I had last year also included completing a Sprint and Olympic triathlon, which is what I did as well.

The moral of the story is, write it down -- don't open Notepad or Things, use good ole fashioned paper and pencil and write them down on a little notecard and throw it in your sock drawer. I'm not going to tell you to look at it everyday, you'll look at it everyday just because your mind will drive you to look at it since they are things you want.

By doing this, you'll accomplish what you want. You have to want to write them down first though.

Capistrano full-stack recipes now on GitHub

After bitching and complaining, I've put my almost-complete-capistrano-tasks on GitHub to start maintaining.

I created the tasks to help setup my VPS in as little time possible since I really don't want to be doing sysadmin stuff anymore. Been there, done that a few years ago. I'm done with it. So I created a few capistrano tasks that will take a bare-bones vanilla VPS and set it up to host rail(s) applications.

Originally, I had nginx install and setup as part of it, but ended up deleting it at the last moment before putting it on GitHub. I don't want to deal with Nginx if I don't have to since I really love Apache -- especially with Passenger (mod_rails) now!

So that's the first order of business is to add the http-server setup ASAP! Other than that, just some overall cleaning up will be done and documentation since the tasks were hacked out in as little time as possible to setup my server.

Enjoy and please contribute ;) I'll be making it available as a gem ASAP too since it is usable in its current state, just not pretty -- yet.

http://github.com/cgrusden/capistrano-server-assembly/tree/master

Having an issue pushing to GitHub or other git repos?

After going through all the correct setup steps to put your open-source project on RubyForge or GitHub you try to do a git-push and then receive errors when trying to git-push.

So the question is, did you add your public key (if you created a new one for git'ing) to your authentication agent via ssh-add?

$ ssh-add ~/.ssh/my_public_key


Done.

ssh-add documentation here

Removing unwanted new files from your SVN working copy

So you have a project in SVN. You create a few new files and decided you just want to delete them via the commandline real quick.

projectroot$ svn st | grep '?' | awk '{print $2}' | xargs rm

mod_rails : RAILS_ENV fun

When hosting multiple Rails applications using the new mod_rails for Apache, all of the RAILS_ENV variables will default to 'production'.

The way you can change what environment your Rails applications run in is by adding/modifying the following line in your httpd.conf:

RailsEnv staging


This is really the only inconvenience that I've found so far with mod_rails. Surely someone will allow for the RailsEnv variable to be located inside a VirtualHost block.

Apache+mod_rails(passenger)

Wow, this is HOT.

I have been using a shared VPS for hosting my rails/PHP applications and using NGinx to do so. Yesterday I told myself I wanted a better solution if there was one. So on my VPS, I installed Apache and mod_rails (Passenger) in a matter of minutes and had all my sites back up with ease.

I'm glad to be back on Apache, even though most of the configuration and performance tuning I've long become rusty on since alot of new features have come out for Apache.

The fun will continue.

Generating Migrations just got easier for me

I wanted to add a column "content" to the user's table. Most of us run the following to create a migration:

script/generate migration addContentToUsers


That creates a migration with the following:

class AddContentToUsers < ActiveRecord::Migration
def self.up
end

def self.down
end
end



What's generated is pretty green, so we'd have to add some add_column/remove_column statements like so:

class AddContentToUsers < ActiveRecord::Migration
def self.up
add_column :users, :content, :text
end


Lots of not needed work. Why not just enter what we want onto the commandline when we run our migration? Enter the cool generator way of creating a simple migration:

script/generate migration AddContentToUsers content:string


This generates a sweet, simple migration like this:

class AddContentToUsers < ActiveRecord::Migration
def self.up
add_column :users, :content, :string
end

def self.down
remove_column :users, :content
end
end


Hot. Thanks for pointing this out l4rk

Gem: eycap

For some odd reason, I had to put double-quotes around the URL for the source in the following for the EngineYard gem that helps with deployment

gem install eycap --source "http://gems.engineyard.com"

Plugin: ResourceController

The Mechnical Turk from Argument from design wrote this sweet ass plugin. It cleans up your controllers, removes redundancy -- hot!


http://svn.ardes.com/resources_controller/trunk/resources_controller/

Jamit sucks. Yea, you heard me.

Today I had an epiphany while looking at the codebase of a COTS (commercial off-the-shelf). Don't' get me wrong, I'm all for leveraging someone else's blood, sweat, and tear's for one-low-price. This time was different. It is the shittiest code I've everseen in a product that was purchased.

All over the place you see the following:

Nastiness #1:
//TODO: clean this up

Nastiness #2:
//$siteHeader = mysql_connect()
$siteHeader = get_site_header();

Nastiness #3 through infinity:
Code that is cryptic and forces duplication.

This is from JamitJobBoard.

Jamit, you suck. Plain and simple.

Give your capistrano script some EngineYard config love

I was attempting to deploy the latest changes to the server for the very first time on my machine and got a wonderful little message from capistrano telling me:

`mongrel:restart' is only run for servers matching {:only=>{:mongrel=>true}, :roles=>:app}, but no servers matched

The fix? From what I understand is that you need to tell capistrano that your web and app roles are running mongrel like so:

role :web, '42.69.187.666', :mongrel => true
role :app, '42.69.187.666', :mongrel => true


That should do it for you, should you have this issue.

RubyJax pairing fun

Tonight's RubyJax meeting rocked out! Getting everyone to pair up and work on something interesting was exciting. I myself was able to work with Russ, really nice guy that wanted to learn more about Rails to kick his ColdFUSION habit!

Also, thanks to the Jacksonville Developer's UserGroup headed up by Jonathan Bates and crew. They sent out a reminder as well as their posting that helped bring in some new faces tonight, thanks guys!

specialized collections using has_many

Here's the following scenario:

You have a ticketing system. You have a User that can create tickets. That same User can be assigned tickets. So how can you specify a has_many for both cases for the User?

Table Schema:

CREATE TABLE User
(
id INT,
title VARCHAR(42),
created_by INT,
assigned_to INT,
)




The answer:

class User
has_many :assigned_tickets, :foreign_key => 'assigned_to', :class => 'Ticket'
has_many :created_tickets, :foreign_key => 'created_by', :class => 'Ticket'
end



In action:
u = User.find(:first)

render :partial => 'tickets/assigned_tickets', :collection => u.assigned_tickets
render :partial => 'tickets/created_tickets', :collection => u.created_tickets

NGinx + PHP5 + MySQL

Had a bitch ass time getting NGinx + PHP5 + MySQL working on Fedora 8. There's very little documentation and what little documentation there is, is in Russian.

At anyrate -- Nginx is the webserver. It serves up content that's it. Because it does it's 1 job really well, that means you have to hook-in all the other shit that you want to use. In my case, I want to serve up PHP pages. Nginx isn't like Apache where you can compile PHP into. You have to host the PHP-FastCGI in a wrapper (lighttpd) that will be accessed by Nginx.

When a request comes in for a .php file, nginx connects to the localhost usually on a port you specify to LightTPD. LightTPD is just sitting there twiddling it's thumbs waiting for shit like this to be requested. At that point, everything should work as planned -- your .php is served. See below for a list of steps that I think is close to being true.
  • user_connects_to_your_page
  • nginx sees request for .php page
  • nginx contacts lightTpd and passes php page to be parsed
  • lightTpd passes page onto PHP-FastCGI being hosted
  • PHP-FastCGI handles .php page/request
  • page returned to nginx
  • user_is_happy
The install instructions below are Fedora 8 specific, so I'm sorry if you aren't running it. You should be able to follow the process flow regardless of your flavor.

Install the following:
  • Nginx - the vanilla install will work
    • yum install nginx -y
  • Lighttpd - vanilla install will work yet again
    • yum install lighttpd -y
  • Php5 - here's the bitch.
    • download the source
    • untar it somewhere
    • ./configure --prefix=/opt/php --enable-fastcgi --with-mysql
    • (If you are running on the 64-bit version of Fedora you'll pull your hair out if you don't add the switch --with-libdir=lib64 at the end of the previous line)
  • cross your fingers that everything got installed properly and will "Just-work" the first time

Now the fun starts. I'm not going to go into crazy detailed configurations, I'm just going to tell you which files you'll probably want to look at and some options since alot of that information is out there already. (do a find for the files if they aren't in the same spot as mine)

  • nginx.conf - this acts like apache's httpd.conf, pay attention to the server directories and port # in red.
    • The port number, corresponds to the port that light-tpd is running on that you launch
    • the directory is obviously the root of where all your php scripts will be running from


server {
listen 80;
server_name myspace.com;
access_log logs/myspace.access.log main;
location / {
root /sites/myspace.com;
index index.html index.php;
}
location ~ \.php$ {
fastcgi_param SCRIPT_FILENAME /sites/myspace.com/$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass 127.0.0.1:10004;
fastcgi_index index.php;
}
}

  • start-fastcgi.php - a script I made to just get the thing working

/usr/bin/spawn-fcgi -a 127.0.0.1 -p 10004 -u lighttpd -g lighttpd -f /opt/php/bin/php-cgi

Vote NO on Joomla

A recent customer of mine had a small issue. His site was running on Linux utilizing Joomla. I realize how nice it is to use software right out of the box, but if the idea is to add ANY features, don't use Joomla.

This specific customer wants some customization and it's going to be a royal pain in the ass to work with the code-base as it is. It makes me sick to my stomach having to work on a codebase that I know is not built for ease of maintenance or anything like that.

One thing that stands out for an open-source project like this, is the amount of code that is commented out.

Frameworks are nice to use, but you're better off trying to piece-meal together some other packages and build the application and THEN extract out what you like.

PHP5 + Smarty Templates + phpAdoDB is your man, if he can't do it, you damn sure can't!

divergentCRM

I just released an open-source project that I did in RubyOnRails. I had a project that I needed to do that starts out very similar to a basic CRM so I figured why not put out a basic CRM before I get into anything specific for the project I'm working on.

It's very bare-bones. In fact, I'm sure I'll get a lot of "Whyd you do that" or "You suck", that's ok. Long as you follow it up with a "this is why". If not, then you should probably just put your laptop (or desktop) back in the box from the store you bought it from and take it back.

The project is on RubyForget at: http://rubyforge.org/projects/divergentcrm/

HashRocket debut

I was lucky enough to be in the right place at the right time for the guys (and devchix) at HashRocket to invite me to take part in one of their 3-2-1 LAUNCH'es. It was awesome. Thanks to Obie, l4rk, BigTiger, Desi, and Lisa! And whoever bought those marvelous chocolate chip cookies.

My love, My Queen, Ruby

Ok, now that I'm drinking all the Ruby on Rails kool-aid it's time to start kicking ass and diving deep into the heart of Ruby.

I realize theres a craze for Rails, but Rails is built on Ruby so .... I rather learn Ruby since it'll be really sexy to build other things with other than just web-applications ;)

GEM_HOME is where the party's at

I was having an issue when I issued the following command:

c:\myrailsapp\mongrel_rails start

..buncha error stuff...
mongrel_service/init.rb (LoadError)

This was partly my fault. Since I had been trying to load local gems and setting my gem repository to the current. At anyrate, here is the following info to know about GEM_HOME and GEM_PATH.

  • GEM_PATH
    • This is where the gems are that will be "read"
  • GEM_HOME
    • Should the gems need to write anything, this is where they will be written to