Monday, September 1, 2008
Contributing to Open Source (Substruct)
With engines setup properly, you are capable of extending routes beyond what's provided with the substruct engine. This was not the case beforehand. I was able to track down the bug and submit some patches to mend the problem.
If you are using substruct and want to customize it (adding additional controllers either to the admin or outside the admin) you'll need to get the latest substruct. Check out the issue here.
You can find download links there.
Working on open source projects is a lot of fun. It's interesting to see how other people do things. Contributing gives developers like me a boost of confidence. I plan on finding and fixing more bugs in the future for this project and others.
Labels: hacks, programming, ruby on rails, software
Wednesday, August 20, 2008
Last.fm Cocoa Tagger v1.2
- Ability to refresh the list of playlists
- Reload playlist data functionality
- Status area indicating the current track being updated and overall progress.
Most of these features allow you to keep the app open (as long as it doesn't crash). Check it out!

Download now
Labels: apple, cocoa, last.fm, lastfmtagger, lastfmtaggercocoa, mac, osx, programming, ruby, software
Sunday, July 6, 2008
Last Update for a While... Promise!
As always, I will provide a screenshot and updated download link. Get it now!

Labels: apple, cocoa, geek, last.fm, lastfmtagger, lastfmtaggercocoa, mac, programming
Please Update
Download now
Labels: apple, cocoa, geek, last.fm, lastfmtagger, lastfmtaggercocoa, mac, programming
Quick Update
Download now (10.5.x build)

Labels: apple, cocoa, geek, last.fm, lastfmtagger, lastfmtaggercocoa, mac, programming
Saturday, July 5, 2008
Icon Goodness!

Love it!
Also, I setup a github account for this project.
Labels: apple, cocoa, geek, last.fm, lastfmtagger, lastfmtaggercocoa, mac, programming
Friday, July 4, 2008
An Unexpected Rewrite...
The app will close out properly if no playlist with the name of 'lastfmtagger' exists. I am working on integrating a way to create the playlist on demand so that the app will continue running.

I would also like to be able to refresh the list of artists on demand, or on a timed observe of some sort so that when you add artists to the playlist, the app is updated accordingly. Tons of ideas, tons of time!
Here's an updated screenshot:

And the download link of course.
Labels: cocoa, geek, last.fm, lastfmtagger, lastfmtaggercocoa, programming
New Last.fm Tagger Written in Cocoa
If you plan on trying out this app, create a small playlist with the name 'lastfmtagger' and put a few albums in there.
Problems I am aware of:
- Can't load huge iTunes library/playlist yet without taking forever to load
- App craps out if the file is missing in iTunes when trying to write
- Some more I can't think of right now...
Give it a shot, and let me know what you think. Here's a screenshot.

Labels: cocoa, last.fm, lastfmtagger, lastfmtaggercocoa, osx, programming
Tuesday, March 11, 2008
We Made it to 1.0!
I'm happy to say that build.last.fm accepted my application! So you can now find the tagger on build.last.fm.
If anyone out there would like a feature added, just let me know and I'll see about implementing it.
Get 1.0 now!
Labels: last.fm, lastfmtagger, programming, ruby
Thursday, February 28, 2008
Last.fm Tagger 0.9
As always, you'll need the wonderfully awesome RubyOSA gem installed.
Download it now.
Labels: last.fm, lastfmtagger, music, programming, ruby
Tuesday, October 9, 2007
Last.fm Tagger for RubyOSA Update 3
What's new:
• Nice console messages telling you what's happening.
• Support for skipping over identical genre's.
• Ability to continue or abort tagging process. So if you don't like that tag, type 'n'.
• Use -q to subdue tagging confirmations.
• Full UTF-8 support, as well as proper URL escaping.

Download it now! And have somewhat useful genre's to choose from.
I will tackle cleaning it up later. Add me to your RSS reader if you want script updates.
Remember, you can get RubyOSA with the Last.fm Tagger here.
Labels: computers, last.fm, lastfmtagger, music, nerd, osx, programming, ruby, software
Thursday, August 9, 2007
eMusic.fm Greasemonkey Script

I finished a v0.1 of my eMusic.fm Greasemonkey script. What it does is pretty simple. On an album page, it will pull the 10 most popular tags from last.fm and inject them into the page below the description.
I found myself looking at last.fm for a particular artist to see what the community has labeled it as. This provides a more insightful look into artists you may not be aware of.
Download my eMusic.fm greasemonkey script
Labels: computers, firefox, last.fm, music, nerd, programming, software
Wednesday, June 27, 2007
Simple Rails Refactoring
type = Type.find(1)
Template.find(:all).each { |t| t.types << type }
Pretty simple. Find the first type, which is supposed to be Pages. Iterate through all templates and assign Pages to them.
I needed to do the same for Articles too, so to get it done quickly, I just repeated what I did previously. So the code looks like this now:
type = Type.find(1)
Template.find(:all).each { |t| t.types << type }
type = Type.find(3)
Template.find(:all).each { |t| t.types << type }
Now I'm finding Pages + Articles, then iterating twice over the Templates and inserting on two separate occasions. To foreign users, I thought it may be a little vague, so I decided to add comments:
# Set default template for pages
type = Type.find(1)
Template.find(:all).each { |t| t.types << type }
# Set default template for articles
type = Type.find(3)
Template.find(:all).each { |t| t.types << type }
Now! Whomever reads my code will know what I was thinking and could probably help clean it up a bit. But wait a sec, Rails adds some pretty nice syntactic sugar to make comments completely unnecessary. Take a look at the same code without comments:
type = Type.find_by_name('Page')
Template.find(:all).each { |t| t.types << type }
type = Type.find_by_name('Article')
Template.find(:all).each { |t| t.types << type }
I think the code is self-explanatory without comments now. But is there a way that I can reduce that still to one line? Sure. The `type` variables are not needed anyways. So let's get closer to one line:
Template.find(:all).each { |t| t.types << Type.find_by_name('Page') }
Template.find(:all).each { |t| t.types << Type.find_by_name('Article') }
This looks swell. I removed the variables and just put the finder methods add what's being inserted into the Template association.
This can be refactored one more time. I can append multiple calls to an array insertion, therefore reducing my code to one line.
Template.find(:all).each { |t| t.types << Type.find_by_name('Page') << Type.find_by_name('Article') }
Now it's lean.
I make it a point to do things like this as many times as possible in one day. Something that Dave Thomas at RailsConf stuck with me. It's not an accurate quote, but it goes something like t his:
Always check in code that is better than before. Even if it's a small improvement.
Labels: programming, ruby on rails
Monday, March 19, 2007
New Last.fm Tagger for RubyOSA
Here's the updated code:
begin require 'rubygems'; rescue LoadError; end
require 'rbosa'
require 'net/http'
require 'cgi'
require 'rexml/document'
include REXML
itunes = OSA.app('iTunes')
selection = itunes.selection.get
if selection.empty?
$stderr.puts "Please select some tracks."
exit 1
end
selection.each do |track|
feed = "http://ws.audioscrobbler.com/1.0/album/#{CGI::escape(track.album)}/toptags.xml"
doc = Document.new(Net::HTTP.get(URI(feed)))
track.genre = doc.root[1][1].text
end
Remember, you can get RubyOSA with the Last.fm Tagger here.
Thanks to Laurent for making an awesome library. It makes playing with Ruby even more fun!
Labels: last.fm, lastfmtagger, osx, programming, ruby, software
Wednesday, November 15, 2006
Get Genre's from Last.fm and Tag with Last.fm Using RubyOSA
I’ve always hated genre’s. They always place a constriction on the acceptance of an artist. However, they do come in handy in certain situations. For instance, I like to tag all my ambient stuff so that I may quickly choose an artist to fall asleep to. Now, I’m on a tagging rampage, however there are some artists where I have no idea how to “genrealize” it. Ah, but the ever-growing community on Last.fm tags artists! Most of the time, the genre is agreeable upon a majority and therefore acceptable to me. I was growing sick of searching Last.fm for each artist, then choosing the most popular tag and tagging it in iTunes. If it weren’t for RubyOSA, I could not have accomplished what I wanted to do.
This is a perfect project for me that I hope to evolve into a more interactive process. Currently, the script is very basic in that you run it, it grabs the tag feed from Last.fm and sets the genre of the artist that you’re listening to. Check it out:
require 'rubygems'
require 'rbosa'
require 'net/http'
require 'cgi'
require 'rexml/document'
include REXML
itunes = OSA.app('iTunes')
track = itunes.current_track
feed = "http://ws.audioscrobbler.com/1.0/artist/#{CGI::escape(track.artist)}/toptags.xml"
doc = Document.new(Net::HTTP.get(URI(feed)))
track.genre = doc.root[1][1].text
In the future, I would like to provide a list of the top 10 tags in which you choose which to tag this song with and ultimately, I’d like to tag the whole artist with the genre. Maybe I could also provide album tagging, since some artists deviate in style across multiple albums.
Labels: last.fm, lastfmtagger, programming, ruby
Monday, October 23, 2006
Ruby on Rails: My ACL Needs Testing! (RUM ACL)
Hello. I have built an ACL (user-management) system with Rails and I need you to test it. Please download the zip, extract it, create your database and set it up, then run rake db:migrate.
Some pluses of this system
- Uses some AJAX features to handle trivial tasks such as adding, removing to speed up those boring tasks.
- It’s stripped down to allow for you to style it as you see fit.
- It’s very basic and easy to understand what’s going on.
Some minuses
- Uses HABTM without :through. Don’t need a full model for my relationships?
- No tests…
Could/should it be developed as a plugin? Engine?
I’d really appreciate some feedback! Send me an email: 
Download the RUM ACL: rum-1.0.zip
Labels: programming, ruby on rails
Friday, October 20, 2006
Rails, meet the Yahoo! Geocoding API
One thing’s for sure: consuming web services in Rails is not very well documented. There are a few ways of going about it, but the easiest way uses REST.
Problem: provide a way to look up a zip code to find a city. With the returned city, search the local database for a match. Then output accordingly.
Solution: Ruby on Rails with the REXML library.
Forget SOAP and XML-RPC, get REST’ed! I will show you how I went about pulling a city by zip code, then using the returned city in a query on my local database.
- Get a Yahoo! Developer Application ID.
- Open up the Yahoo! Geocoding API docs for reference.
- Use the following code in your
controller.rb
file.
# welcome_controller.rb
def city
appid = "myYahooDeveloperAppID"
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=#{appid}&location=90210"
@results = REXML::Document.new(Net::HTTP.get(URI(url)))
end
# views/welcome/city.rhtml
@results.root.each_element { |city| "#{city[3].text}" }
There you go. Can you believe it’s that easy?
Labels: programming, ruby on rails, yui
Tuesday, October 10, 2006
Code Highlighter Plugin!
Finally! Oh, how I’ve longed for your sweet caress…
Thanks to this how-to, I was able to get syntax highlighting working. It’s super-easy to setup, however I had to do some light digging to get the proper CSS. The one I found was similar to the RubyBlue TextMate theme that I adore.
Here’s a small excerpt (for testing) of the lib/codehighlighter plugin.rb file:
require 'behavior'
require 'syntax/convertors/html'
Behavior::Base.define_tags do
tag 'code' do |tag|
lang = tag.attr['lang'] || "ruby"
convertor = Syntax::Convertors::HTML.for_syntax(lang)
code = convertor.convert(tag.expand.to_s.strip, false)
%{#{lang}-code">#{code}}
end
end And of course, the CSS:
pre.ruby-code {
background-color: #0D151E;
color: #fff;
padding: 10px 10px 10px 10px;
margin: 4px 0px;
font-size: 1.1em;
overflow: auto;
}
/* Syntax highlighting */
pre.ruby-code .normal {}
pre.ruby-code .comment { color: #428BDD; font-style: italic; }
pre.ruby-code .keyword { color: #F8BB00; }
pre.ruby-code .method { color: #077; }
pre.ruby-code .class { color: #fff; }
pre.ruby-code .module { color: #050; }
pre.ruby-code .punct { color: #FFF; }
pre.ruby-code .symbol { color: #B53B3C; }
pre.ruby-code .string { color: #1DC116; }
pre.ruby-code .char { color: #F07; }
pre.ruby-code .ident { color: #fff; }
pre.ruby-code .constant { color: #8AA6C1; }
pre.ruby-code .regex { color: #CA4344; }
pre.ruby-code .number { color: #EDDD3D; }
pre.ruby-code .attribute { color: #5bb; }
pre.ruby-code .global { color: #7FB; }
pre.ruby-code .expr { color: #227; }
pre.ruby-code .escape { color: #1C6A21; } Labels: programming
Monday, September 4, 2006
Using Rails and a stand-alone script
A challenge was presented to me with my most recent project. Setup a script to run nightly (by a cronjob) to retrieve records for a past days orders. With these orders, generate an Excel spreadsheet followed by an email with this spreadsheet attached. I accomplished this with a lot of trial and error and I’m going to present the code for which you can do the same when/if you need to. Info was scarce on the web on how to do exactly what I nedeed to do, so hopefully this will enlighten some lucky folks out there. Ha! As always, this probably can be improved quite a bit, I’m just glad to have it done and working! (Client happy..)
Keep in mind that you need the spreadsheet-excel gem. Install it via:
gem install spreadsheet-excel
Here goes:
#!/usr/bin/env ruby
# ABSTRACT
# This file is to be executed by a cron script that is setup on a local server
# PROCESS
# 1. Load Rails environment and make connection to database
# 2. Get list of operators, get orders which have an agent that belongs to that partner to operator
# 3. With that list of orders, create the Excel spreadsheet
# 4. Mail spreadsheet to operator (CC to mycablehome)
# 5. Create record in Leads table with a reference to the spreadsheet
RAILS_ENV = 'production'
require File.dirname(__FILE__) + '/../config/environment'
require "spreadsheet/excel"
@operators = Operator.find(:all, :select => 'id, site, name, system_city, report_email_address_to, report_email_address_cc')
@operators.each do |operator|
@orders = Order.find(:all,
:conditions => [ "operator_id = ? AND created_at #{(1.day.ago.to_date..Date.today).to_s(:db)}", operator.id ])
file = "#{1.day.ago.to_date}_#{operator.site}_#{operator.system_city.underscore.downcase}_sales_leads.xls"
workbook = Spreadsheet::Excel.new("#{RAILS_ROOT}/public/reports/#{file}")
worksheet = workbook.add_worksheet("#{operator.site} Sales Leads for #{1.day.ago.to_date}")
worksheet.write(0, 0, "Customer name")
worksheet.write(0, 1, "Email")
worksheet.write(0, 2, "Service street address")
worksheet.write(0, 3, "City")
worksheet.write(0, 4, "State")
worksheet.write(0, 5, "Zip")
worksheet.write(0, 6, "Home phone")
worksheet.write(0, 7, "Daytime phone")
worksheet.write(0, 8, "Cable Package")
worksheet.write(0, 9, "Services")
worksheet.write(0, 10, "Num. of TV's")
worksheet.write(0, 11, "Num. dig A/O")
worksheet.write(0, 12, "Num. HD/DVR")
worksheet.write(0, 13, "HD only")
worksheet.write(0, 14, "Installation date")
worksheet.write(0, 15, "Installation time")
worksheet.write(0, 16, "Alternate installation date")
worksheet.write(0, 17, "Alternate installation time")
worksheet.write(0, 18, "Order num")
worksheet.write(0, 19, "Comments")
row = 1
@orders.each do |order|
worksheet.write(row, 0, "#{order.customer.first_name} #{order.customer.last_name}")
worksheet.write(row, 1, "#{order.customer.email}")
worksheet.write(row, 2, "#{order.customer.addresses.first.address}")
worksheet.write(row, 3, "#{order.customer.addresses.first.city}")
worksheet.write(row, 4, "#{order.customer.addresses.first.state}")
worksheet.write(row, 5, "#{order.customer.addresses.first.zip}")
worksheet.write(row, 6, "#{order.customer.home_phone}")
worksheet.write(row, 7, "#{order.customer.daytime_phone}")
unless order.package.nil?
worksheet.write(row, 8, "#{order.package.name}")
worksheet.write(row, 9, "#{order.package.services.collect { |s| "#{s.name} " } }")
worksheet.write(row, 10, "#{order.tv_sets}")
worksheet.write(row, 11, "#{order.digital_boxes}")
worksheet.write(row, 12, "#{order.dvr_boxes}")
worksheet.write(row, 13, "#{order.own_hdtv_set}")
worksheet.write(row, 14, "#{order.operator_order.installation_date}")
worksheet.write(row, 15, "#{order.operator_order.installation_time}")
worksheet.write(row, 16, "#{order.operator_order.alternate_installation_date}")
worksheet.write(row, 17, "#{order.operator_order.alternate_installation_time}")
end
worksheet.write(row, 18, "#{order.id}")
worksheet.write(row, 19, "#{order.operator_order.special_instructions}") unless order.package.nil?
row += 1
end
workbook.close
OrderMailer.deliver_sales_leads(operator.report_email_address_to, operator.report_email_address_cc, operator.site, operator.system_city)
end
Hopefully this will get you started.
Labels: programming, ruby on rails
Thursday, June 29, 2006
Adventures with Ruby (part 1)
These are notes I’m taking while reading the Programming Ruby book. It’s excellent.
General Ruby
- use parens in all but the simplest cases
- single quotes for non-escaped strings, double quotes induce more work
- escaped strings replace with binary val
- double quotes also used with expression interpolation #{name}
- the last expression evaluated by a method is the return value; no need for return unless being of utmost verbose
Classes
- classes are never closed. you can always add methods to an existing class by opening the class like you would a folder or file
Cool and unforgettable features
- statement modifiers: ** expression followed by if or while and the condition ** (ex. puts “danger!” if radiation > 3000)
I AM WHAT I DO NOT UNDERSTAND. I AM ARBITARY!
Labels: programming, ruby
Friday, March 3, 2006
About the Blog and its Guts
Wow.
What can I say? Other than, “I adore Ruby on Rails”. If you are a struggling Rails would-be developer, have no fear! I was in your shoes at one time, in fact, I’ve only taken off one shoe.
You may ask, what it is that got me so thrilled about Rails? This pretty much sums it up.
Here’s a break-down of my process over the past few days:
- Stumbled upon this wonderful, amazing, enlightening article published by Apple.
- Work was slow, so I decided to buckle down and get a development process in order.
- Eventually got a process in order using SVN for keeping up-to-date on progress at work and at home. This was a huge step.
- Progressed my blog into what it is today. I’m very happy with it.
I’m very obsessive about order. So much that for the longest time, I could never accomplish anything because I didn’t have a process. Rails provides this process almost transparently. It’s an amazing framework, and I applaud David for frontiering the future of web development.
Bless the Sterkens Dubbel Ale. Mmmf…
Labels: programming, ruby on rails
Monday, November 14, 2005
A Reanimated CollectorNerd.com
I’ve always wanted to setup my own CVS repository. Sure, I could set one up at home, but it kind of defeats the purpose of it. I want a remote location for storing my files that is accessibly (safely and securely) from anywheres. Our previous host LiquidWeb did not support hosting CVS for individual accounts. Dreamhost does, though. My main reason to switch to Dreamhost was that they had Rails installed. They sealed the deal with their awesome prices. CVS is so nice, especially when coupled with RadRails a well-made IDE for developing with Ruby on Rails.
Now, onto the topic of this article. A Reanimated Collector Nerd. Some of you may be familiar with a project that I’ve been working on (on and off for a few years now). I haven’t worked on it in about a year until yesterday, where I quickly implemented item comments. So that when a user leaves a comment on someone’s collected item, they receive an email letting them know.
Thanks to Basecamp we now have the most resourceful collaboration software ever. This is going to help everyone compile their ideas into one big “basecamp” Too bad the free version allows on two writeboards (sigh). I’m going to try my hardest on making Collector Nerd (on Rails) a reality! I want this to happen. Bad.
Labels: programming, projects
Subscribe to Posts [Atom]