captured sparks

Archive for 2008

Intaeco

Background

The client required a brochure site that would showcase the products that were available. In addition to the products on show, the site also provides useful information relating to each of the technologies available. Javascript is discreetly used to enhance the browsing experience whilst degrading gracefully in browsers with Javascript switched off.

Equal height columns

One of the common issues that has plagued web designers is how to ensure that a sidebar column with a background colour will fill the height of the page when a second column is much longer. One of the most used options is Faux Columns by Dan Cederholm.

I’m going to show you how to quickly achieve identical height columns using jQuery.

We start with a simple layout:

<div id="main">
  <div id="sidebar">
     Lorem ipsum..
  </div>

  <div id="content">
    Lorem ipsum...
  </div>
</div>

We can then use the following jQuery code to ensure that the sidebar is always equal to the height of the content column:

var mainHeight = jQuery('#main').height();
  if (mainHeight > 280) {
    jQuery('#sidebar').css({
      height: mainHeight
    });
  } else {
  };

This grabs the height of the #main div and if that height is greater than 280px, dynamically adjusts the height of the sidebar to match.

Want Beans Update

You no longer need to create an account to create a cafe on Want Beans. Add your favourite coffee house by visiting the new cafe page.

Building Buzz

37signals, who are perhaps best known for Basecamp, have just posted an interesting blog post on how they built buzz in their early days. It’s a great look back at the origins of a company that now inspires a lot of other web design and web application companies. Not just in terms of the work they produce, but also in terms of their approach to running a business.

What the post highlights is how it is not always necessary to focus on what you do provided that the things you are doing are related to your primary activity. Ideas like the E-Commerce Search Report and Design Not Found offer an “in” to prospective customers.

I also subscribe to Seth Godin and one of the ideas he promotes is to always offer content. Seth has a new post on his blog every day (or thereabouts).

It takes a concerted effort to build buzz and drive business. The posts here at captured sparks have always been a little sparse, and mainly related to web development. From now, I will be making a concerted effort to post more.

Receiving emails with Ruby on Rails

I spent the weekend getting a little application to play nicely with emails being sent to it. As receiving emails with Rails is something that is not written about as much as sending emails, I thought I would share my solution.

This tutorial will show you how to receive emails into your application, store them in the database and forward the contents to multiple recipients.

The first problem of course is getting the emails into your application. I have root access to my server, so my solution uses Postfix. If you don’t have root access, you can use POP and there are a number of examples out there. On with the instructions…

As I am hosting a number of domains on the same box, I set up my main.cf file as follows:

virtual_alias_domains = mydomain.com
virtual_alias_maps = hash:/etc/postfix/virtual

I then set up my virtual file (which you may need to create) with a single line:

@mydomain.com rails_mailer

This will intercept any emails sent to mydomain.com and pass them to the rails_mailer alias, which is created in your alias file. Mine is located in /etc/aliases: yours might be in /etc/postfix/aliases. Add to the bottom of your aliases file:

rails_mailer: "|curl -F mail='<-' http://mydomain.com/emails"

This uses curl to post the mail as form data to the given url. The email contents will be stored inside the mail parameter. The pipe character at the start indicates that this is a shell command and not a directory.

To apply all these changes:

sudo postmap /etc/postfix/virtual
sudo newaliases
sudo /etc/init.d/postfix reload

To check that this is working, change into your /var/log directory and use:

tail -f mail.info

Then send an email to any address @mydomain.com and you should see it received in your mail log and passed to your Rails app. If you look in your app’s logs, you should see it spitting out a 500 error as there is no code to handle the email…yet.

On to the Ruby. Create an Emails controller and define a create method:

def create
  if params[:mail]
    Notifier.receive(params[:mail])
  end
end

This receives the contents of params[:mail] and passes it to the receive method of our notifier model.

To deal with Rails’ cross-site scripting protection, you need to add to the top of your controller:

skip_before_filter :verify_authenticity_token

Next, generate a mailer called notifier. In notifier.rb, define a method called receive(email). Using this method name automatically invokes the power of TMail. My receive method is as follows. You will need to change this to make sure you pull the information you need from the email:

def receive(email)
  event_name = email.to
  event_name = event_name.to_s.sub('@mydomain.com', '')
  event = Event.find_by_tidy_name(event_name)
  body = email.body
  address = Array.new
  event.attendees.each do |attendee|
    address << attendee.email.to_s
  end
  from = email.from.to_s
  new_email = event.emails.new
  new_email.from = email.friendly_from
  new_email.body = body
  new_email.save
  Notifier.deliver_event_email(event, from, address, body)
end

Before running through this code, I should explain that when people use the app, they receive a dedicated email address in format myeventname@mydomain.com.

This code does two things. Firstly, it extracts the following data from the email: the name of the event, the body of the email and who the email is from. It then constructs a new email that belongs to the event and saves to the database. It then invokes another method in our notifier.rb to forward the email body to the individuals who are attending the event.

def event_email(event, from, address, body)
  setup_email(from)
  @bcc = address
  @subject += "#{event.name}"
  @body[:body] = body
end

In terms of the application that I wrote this for, I hope to launch it within the next week. If you’ve got any questions or run into any problems, leave a comment and I’ll try and help.

Want Beans

Background

Want Beans is a social network for reviewing and rating coffee shops and discovering great places to hang out when you’re out and about.

Want Beans

I’m happy to announce the launch of Want Beans!

Want Beans is a social network for reviewing and rating coffee shops and finding great places to grab a coffee when you’re out and about.

As I mentioned in an earlier post, the idea was inspired when I had about 5 hours to kill in Hull and just wanted to find somewhere to hang out with my MacBook.

I hope that you’ll register and add your favourite cafe to help other people discover great places to grab a latte. To get started, please visit Want Beans.

The final 10%

The final 10% is always the hardest bit to do. Unfortunately, it’s generally that bit that makes something really work. It stops something being OK and makes it great. It makes you go “Wow”.

On my coffee application (I still don’t have a name apart from wanna coffee?, which I don’t like), the majority of the functionality is there. In its most basic form, the app works. It just doesn’t have that polish and that is what I’m talking about. That is the final 10% and I wouldn’t be happy launching it without that polish. I’m happy if some areas of functionality are not present at launch, provided they are not core to the purpose.

What I don’t want to do is launch at 90% of what I want, and would expect, version 1 to be like. It’s that 10% that I’m working on now.

More on ActiveMerchant and Paypal

I’ve had a few comments asking for some more information setting up AM with Paypal. I won’t profess to be an expert and there may be better ways of doing this.

I am using Paypal UK Website Payments Pro and for this have set up an account that gives me access to Paypal Manager.

As per my previous post, an account is created using the account key as subdomain model:

def create
    @account = Account.new(params[:account])
    @account.initial_plan = params[:plan_id]
    if @account.save
      @account.set_admin
      if @account.initial_plan == "2"
        redirect_to :host => account_host(@account.name), :controller => 'sessions', :action => 'new'
      else
        redirect_to :host => account_host(@account.name), :controller => 'subscriptions', :action => 'new'
      end
    else
      flash[:error] = "Could not create account. Please try again."
      redirect_to :controller => 'accounts', :action => 'new'
    end
  end

If the customer has selected anything other than a free account, they are redirect to the new action of the subscriptions controller. I am using the subscription model to act as a join between an account and a particular plan.

The template for the new action is a simple form with space for credit card information. Creating a subscription calls the following create action in the controller:

def create
    @plan = Plan.find_by_id(@account.initial_plan)
    first_name = params[:cc_name].split(' ')[0]
    surname = params[:cc_name].split(' ')[1]
    name = params[:cc_name]
    number = params[:cc_number]
    amount = @plan.price*100
    credit_card = {
      :number     => "#{number}",
      :first_name => "#{first_name}",
      :last_name  => "#{surname}",
      :name       => "#{name}",
      :month      => "#{params[:cc_month]}",
      :year       => "#{params[:cc_year]}",
      :verification_value => "#{params[:cc_cvv]}",
      :type       => "#{params[:cc_type]}"
    }
    subscription = Subscription.recurring(amount, credit_card, options = {:ip => request.remote_ip})
    if subscription
      subscription.plan_id = @plan.id
      subscription.account_id = @account.id
      subscription.save
      flash[:notice] = "Your account has been setup.  You can now login!"
      redirect_to matters_url
    else
      flash[:error] = "YIKES!"
      redirect_to new_subscription_url
    end
  end

I have no doubt that a lot of this could be refactored into the model. At the moment, I am focussing on getting the app running, not tidying up the code. You will note the class method “recurring”, which is in the subscription.rb file. The code for this is taken straight from the AM pdf mentioned in my earlier post so I cannot repost that here. This method creates a connection through AM to Paypal and creates a recurring subscription. Information that is returned includes a profile id that can be used to uniquely identify a particular subscription in both the app and Paypal manager.

Updating the subscription is fairly similar to creating a new subscription except you pass the profile id through so that Paypal knows which account to change.

One thing to note is that it is important to ensure consistency between Paypal and the subscriptions table in your app. It is very easy to update a subscription in Paypal so that a customer is billed the correct amount but fail to update the internal record in your app. This will result in revenues being either significantly higher or lower than you expect.

One of the questions in the comments to the original post is how much information in the pdf was relevant to Paypal US. I can’t directly answer that but I can say that the code works as a great starting point but some re-coding will necessary to make it work for your app.

A new look

I’ve spent the past few weeks working a redesign for captured sparks and this weekend, as you can see, I have put it live.

I have also taken the opportunity to implement some functionality that has been missing. As you might know, captured sparks is published on my own system coded in Rails and even though I have had the basics running for a few months, there were some key things that I needed but never found the time to implement.

During the course of the redesign, I’ve added the following functionality:

Post Status

I can now classify a post as either a draft or published.

Comment Administration

Up until now, I have had to manage any comments by logging into the server and directly editing the database through the Rails console. I’ve now added the ability to approve or reject comments in the admin area.

I’ve also made the decision to effectively ignore IE6. The site uses PNGs for titles and I’ve not taken any steps to address IE6’s failure in this regard. Nor have I checked to see how the site looks in IE6 generally. I’m using IE conditional comments to present a friendly warning to those users with IE6 that the site may not look great and suggesting an upgrade.

Next Page »