INCLUDE_DATA

Category web development

3 things I’m excited about: Yahoo! Pipes, Code Igniter, and Facebook API 2

Feb9

Stumbled across 3 things this week that have me excited:

I’ve been looking for a quality, light-weight PHP framework for a while now, and Code Igniter seems to be exactly what I’m looking for. I’ve known about CakePHP, but never bothered with it… seemed to be bloated with a bunch of crap that I’m not interested in. A bonus is that tests indicate that Code Igniter is faster than CakePHP.

With regards to the other two (the Facebook API and Yahoo! Pipes), it’s just plain exciting to see companies releasing fun, geeky tools and making their APIs publically accessible.

Wanted: Income tax information for Internet-based businesses in Canada 1

Jan2

Wanted: Income tax information for Internet-based businesses in Canada

I am looking for books, eBooks, or websites.

If you know of any good ones, please let me know! Revenue from my websites is getting to the point where I’d better cover my bases before the Gov’t comes after me.  : )

Two weeks later, Firefox referrals have increased by 1000% 0

Nov24

Just a quick update on my Firefox + Yahoo! Marketting experiment.

When I first started using Yahoo! Marketting 10 days ago, I was only getting a few Mozilla Firefox conversions per day. Adding the revenue from those referrals up, we were looking at just a couple dollars per day– maybe more if I was having a good day.

Now, Yahoo! Marketting is sending about 100 visitors per day my way, at about a dime a visitor. Plus, some of my pages have started to get listed in the various search engines, leading to another 50 or so visitors per day from natural search placement. Total, about 150 page views per day.

With that traffic, I’m getting nearly 1000% more signups than when I first set up the website. Even with the Yahoo! Marketting costs, my figures show that I reap more from those visitors than it costs to get them to my site in the first place. So, although my $50 credit from Yahoo! Marketting is going to expire soon, I’m going to continue with the service.

Wanna start making some money through Firefox referrals on your own homepage? Click on the Google Adsense referral image on the top-right corner of the page. Not only will it take you to the Adsense sign-up page to get started, but you’ll also be helping me earn a few extra bucks through the referral to their service.

Resurrecting this blog and broadening it’s focus 1

Oct28

I started work at TELUS over 10 months ago, and since that time, I’ve barely written a stitch of Ruby, let alone learn anything more about Ruby on Rails. My TextDrive account is no longer active and the experimental websites I launched while actively learning Ruby on Rails have been shut down. Essentially, I’ve lost all connection and interest in RoR and the RoR community.

For that reason, I’m renaming my blog from “Rory on Rails” to simply, “Rory Hansen”, as I don’t foresee myself writing about Rails anytime in the near future. Who knows– maybe somewhere down the line, I’ll regain interest in RoR, but right now, my mind and my time are focused elsewhere.

At work, I program almost exclusively in ASP.NET and C#. For the type of development I do, ASP.NET is fine. I appreciate the power of the framework and, given my experience with it now, I can get new webapps up and running quickly and easily. Do I like ASP.NET? Actually, yes I do.

Outside of work, I’m constantly trying to better myself through learning new skills and improving existing abilities. As my buddy Jeff would say, I’m just trying to ”raise my NPV.” Whether it be by reading great business books like Blue Ocean Strategy or Good To Great, or by practicing my networking skills at various conferences around town, I’m consciously trying to improve myself, thus raising my “market value,” so that when I’m ready to find a great new job somewhere, I’ve positioned myself as best as I can to actually get that job.

So, with all of that said, future posts on my blog will be about many of my current interests, such as learning how to play the acoustic guitar, improving my communication and networking skills, making change happen in business, and futher developing my leadership abilities.

Stay tuned!

Rory

Zebra-striped tables using Rails 6

Nov30

Zebra-striped tables are tables where row colors alternate between a light color and a dark color and can be done both using server-side code (ie. Rails) or client-side code (ie. JavaScript). I posted a question asking for the most convenient way to create zebra-striped tables to the Rails newsgroup some weeks ago and the responses I received were actually quite scathing. I’ve normally done this type of thing using server-side code when working with other programming languages (ASP, PHP, JSP, ColdFusion, etc.), but many people feel that this is an extreme no-no (and aren’t afraid to tell anyone that’ll listen to them), as it muddles up the separation of business logic from presentation.

Anyway, my point is that, regardless of what others think, I want to continue doing this type of design using server-side code and a recent post on the Code Snippets website highlights a Rails helper tag called cycle that makes this very convenient. (The name will be familiar for those that have used the Smarty templating engine for PHP.) The cycle tag is exactly the type of suggestion I was looking for when I posted my initial question to the newsgroup. Before that, I’d been using some nasty combination of if statements and the mod operator to determine the row color and that had completely uglified my code.

This is how you use the cycle helper method:
<tr class="<%= cycle("even", "odd") %>">
... use item ...
</tr>

You can read more about the cycle helper method in the Rails API.

Using JavaScript to validate one or more grouped checkboxes 16

Aug25

It’s a common task to validate a form with JavaScript upon form submission. And validating whether or not at least one checkbox in a checkbox group is checked is often a basic requirement of this task. But, if you’re form is created dynamically and if the number of checkboxes in a checkbox group can vary from 1 to more than 1, then the JavaScript needed to iterate over the checkboxes is slightly different.

Say you have an HTML form like this:

<form name="frm" method="post">
   <input type="checkbox" name="parts" value="1" />Head<br />
</form>

Then, using JavaScript, you can check whether the checkbox is checked like so:

var isChecked = document.frm.parts.checked;

Now, imagine that your form has more than one checkbox in the same checkbox group:

<form name="frm" method="post">
   <input type="checkbox" name="parts" value="1" />Head<br />
   <input type="checkbox" name="parts" value="2" />Neck<br />
   <input type="checkbox" name="parts" value="3" />Arm<br />
   <input type="checkbox" name="parts" value="4" />Leg<br />
</form>

Then, the JavaScript code changes a little bit, as now you have to iterate over each of the checkboxes.

var isChecked = false;

for (var i = 0; i < document.frm.parts.length; i++) {
   if (document.frm.parts[i].checked) {
      isChecked = true;
   }
}

But. if you tried using the 2nd chunk of JavaScript on the first chunk of HTML, you’ll get a JavaScript error. This is because if you only have one checkbox, there’ll be no array to iterate over. So, you need to do a quick check before hand to see if there is more than one checkbox. If so, then iterate; otherwise, don’t.

if (document.frm.parts) {
   if (typeof document.frm.parts.length != 'undefined') {
      for (i = 0; i < document.frm.parts.length; i++) {
         if (document.frm.parts[i].checked) {
            isChecked = true;
         }
      }
   } else {
      isChecked = document.frm.parts.checked;
   }
}

This code first checks to see that there exists at least one checkbox. Then, it checks whether the length attribute of the parts variable is defined or not. If it is defined, then we know there is more than one checkbox. Otherwise, there is only one.

And there ya have it!

Using IFrames in ASP.NET 5

Aug22

So, I’ve basically finished coding the “Google Suggest”-like web user control I was writing for the company I’m doing a co-op work term at. I’m now in the process of integrating it into an existing textbox control that they’ve developed, and that should be finished soon.

One part of the web user control is an iframe, which is used to counteract the much-documented z-index and select box problem in Internet Explorer. By placing the iframe directly below the div that the Google Suggest results are displayed in (as in one z-index less than the z-index of the results div), we can avoid this problem all-together.

But, to make the web user control as reusable as possible, I needed to be able to name this iframe uniquely, incase there are multiple instances of the control on the same aspx page. To do this, I needed to be able to specify the name of the iframe when it is rendered (or guarantee that it would be automagically named uniquely), and I figured out I could accomplish this by using two standard controls: PlaceHolder and HtmlGenericControl.

First, I create the HtmlGenericControl object that will eventually render as an iframe and specify whatever attributes this iframe will have:

// Create new iframe control
HtmlGenericControl searchFrame = new HtmlGenericControl("iframe");
searchFrame.ID = "searchFrame";
searchFrame.Attributes.Add("class", "searchFrame");
searchFrame.Attributes.Add("frameborder", "0");

Then, I can add it to the PlaceHolder’s controls collection:

// Add it to the Controls collection of the PlaceHolder control
searchHolder.Controls.Add(searchFrame);

Finally, I add the PlaceHolder control into my ascx document where I’d like the iframe to eventually be:

<div class="searchContainer">
   <asp:PlaceHolder id="searchHolder" runat="server" />
</div>

Now, an iframe will appear in the outputted HTML code where the placeholder once was. But more than that, since I used an ASP.NET control to actually create the iframe, the iframe will be named uniquely. We even know what it’ll be called: this.UniqueID + “_searchFrame”. This is beneficial to me since I can now reference that iframe by name throughout my JavaScript code and show it or hide it when necessary.

Amazon Web Services on Rails 9

Jul18

If you’re looking to make use of the Amazon Web Services through your Rails app, here’s a tip: avoid trying to communicate with them using the Ruby on Rails ActiveWebServices classes. I spent a couple hours trying to patch together a solution, but nothing would work. I believe what currently exists is geared towards making your Rails app accessible through Soap or XMLRPC, rather than consuming exisiting web services.

Instead, use Ruby/Amazon, a “Ruby language library that allows programmatic access to the popular Amazon Web site via the REST (XML over HTTP) based Amazon Web Services.” Installation of the library on my development box was a breeze (just read the installation document to learn how) and, plus, it’s already preinstalled on the servers at TextDrive, so getting going using the Ruby/Amazon library is not a problem at all. For a quick tutorial on how to use the library, check out the documentation on the top-level Amazon module or read this entry on the GleepGlop blog. Both contain examples that show you how to make a basic connection to Amazon through the web services and how to query for products.

Once you get this far, though, you’ll realize that making calls to the Amazon Web Services with every page view is going to decrease the speed at which your website will render for your users. So what can you do instead? Cache the results in your database, that’s what. On my lyrics website, I want to have links back to Amazon for every artist that I have lyrics for. So, what I did was create an administrative function that will connect to Amazon and return a list of items for a given artist. This process is repeated over and over so that I have a huge archive of products for each of the artists. Then, instead of querying Amazon with each page view, I just need to call this administrative function every month or so, to update the products in my database.

Below, you’ll see a body of code that updates all products for all artists whose names begin with a particular letter (for example, “A”). For each artist, all existing products are deleted from the database. Then, a new list of products is retrieved and each product is added to the database.

amazon_controller.rb
require 'amazon/search'

class AmazonController < AdminController
   include Amazon::Search

   ASSOCIATES_ID = "amazonaffiliateid-20" # Your Amazon Affiliate ID
   DEV_TOKEN = "0222NLPJQD0A7633Q182" # Your Amazon Web Services Key

   def update
      artists = Artist.find_by_first_letter(@params["letter"])

      artists.each do |artist|
         # Delete all existing "out-dated" products
         existing_products = Product.find_all_by_artist_id(artist.id)
         existing_products.each do |existing_product|
            existing_product.destroy
         end

         # Query Amazon
         request = Request.new(DEV_TOKEN, ASSOCIATES_ID)
         response = request.artist_search(artist.artist_name)
         products = response.products

         # Loop over each product and add them to the database, one at a time
         products.each do |product|
            new_product = Product.new

            new_product.artist_id = artist.id
            new_product.product_name = product.product_name
            new_product.url = product.url
            new_product.image_url_small = product.image_url_small
            new_product.image_url_medium = product.image_url_medium
            new_product.image_url_large= product.image_url_large

            new_product.save
            new_product = nil
         end
      end

      redirect_to(:controller =< "admin", :action => "index") # Return to the list page if it suceeds
   end
end

What I’d like to do now is to have a Ruby script run nightly that updates a portion of the products in the database. For example, at midnight on the first day of each month, all artists whose names begin with A would have their products updated from Amazon. At midnight on day two, all B artists would have their products updated. I just have to figure out how to do this… but once I do, I’ll post it here.

Ruby on Rails find_by_sql Example 3

Jul1

Note: Read this post to learn how to implement the same method using the find_all function. - Rory, July 3, 2005

In the lyrics website I’m developing, I’d like to be able to use URLs like this in my administrative back-end:

http://www.website.com/admin/artists/list/A

where, when I visit this URL, a list of artists who’s name begins with the letter A is displayed. This requires the use of the Ruby on Rails find_by_sql method, as there is no way of querying for artists in this manner using the built-in Active Record.

The first thing I did was add a new method to my Artist model that will allow me to search for artists by the first letter of their name.

artist.rb
class Artist < ActiveRecord::Base
   has_many :songs, :order => "song_title", :dependent => true
   has_many :albums, :order => "album_name", :dependent => true

def self.find_by_first_letter(letter = "A")
      find_by_sql ["select * from artists where ucase(left(artist_name, 1)) = ?", letter]
   end
end

As you can see, the method find_by_first_letter takes in an argument called “letter” and uses this argument in the function call to find_by_sql. You’ll notice that a question mark appears in the SQL statement where we would actually like the value associated with “letter” to go. Queries created this way are called Parameterized SQL Queries, and by using them, we avoid the possibility of having someone tamper with our query using SQL injection.

Then, in our action, all we have to do is call our new method.

admin_controller.rb
@artists = Artist.find_by_first_letter(@params["letter"])

Related Drop-down Lists with Ruby and Ajax 50

Jun21

Note: I have been meaning to re-write this post to make better use of Ruby on Rails helpers, etc. When I first wrote this I was extremely new to Rails and my unfamiliarity with the framework showsUntil I have the free time to re-write this post, please bear with what is currently here and leave comments to help others that follow after you.

Finally! I’ve been working on this little bit of Ruby code for hours now, all because of some odd bugs (which, when I learn Ruby better, will probably cease to become odd) and a lack of good Ruby on Rails documentation.

What I’ve been working on is getting two related HTML drop-down lists to update properly using the built-in Ajax support in Ruby on Rails. Specifically, when the user selects an Artist from the first drop-down list, only that artist’s Albums should be listed in the second. I wanted to do this without having to retrieve all of the albums during the initial page load and without having to do a post back when the user selects an artist. So, that’s where Ajax comes in. Ajax uses the JavaScript XMLHTTPRequest routine to retrieve new data from the server without requiring the user to refresh the webpage.

Some gotchas for the new Ruby programmer / web developer:

  • You cannot modify the InnerHTML of a select drop-down list. Instead, you have to modify the InnerHTML of the div that _contains_ the select drop-down list, and when you do you have to recreate the whole drop-down.
  • When you are using instance variables (those that begin with the @-sign), ensure that the instance variable exists before trying to use:
    @variable += “value”
    syntax or else Ruby will throw up an error. For example, before that statement, add a line that reads:
    @variable = “”
  • When concatenating strings that contain instance variables, Ruby is picky in a way that I can’t fully describe. For example, the following does not work:
    @html += “<option value=’” + @album.id + “‘>” + @album.album_name + “</option>”
    But this does work:
    @html += “<option value=’#{@album.id}’>#{@album.album_name}</option>”

Anyway, this is the troubled code that _did not_ work:

admin_controller.rb
@albums = Album.find_all_by_artist_id(@params["artist_id"])
@html = "<select id='album_id' name='album_id'>"
@html += "<option value=''>No Album</option>"
@albums.each do |@album|
   @html += "<option value='" + @album.id + "'>" + @album.album_name + "</option>"
end
@html += "</select>"

After hours I got it working with this code:

admin_controller.rb
@albums = Album.find_all_by_artist_id(@params["artist_id"])
@html = "<select id='album_id' name='album_id'>"
@html += "<option value=''>No Album</option>"
@albums.each do |@album|
   @html += "<option value='#{@album.id}'>#{@album.album_name}</option>"
end
@html += "</select>"

But, this has to be coupled with the RHTML code in the template, as follows.

add_song.rhtml
<%= javascript_include_tag "prototype" %>

Artist
<select name="new_song[artist_id]" id="new_song[artist_id]">
   <option value="">Select Artist</option>
   <% @artists.each do |artist| %>
      <option value="<%= artist.id %>">
         <%= artist.first_name %> <%= artist.last_name %>
      </option>
   <% end %>
</select>

Album
<div id="album_id_container">
   <select name="new_song[album_id]" disabled="disabled">
      <option value="">No Album</option>
   </select>
</div>

<%= observe_field("new_song[artist_id]",
   :frequency => 0.25,
   :update => "album_id_container",
   :url => { :action => :add_song_artist },
   :with => "'artist_id='+value") %>