Monday, August 22, 2011

Translate This WordPress Plugin

I have finally released my first public WordPress plugin. It's fairly straightforward, but I wanted to go through a couple things I hadn't done before, namely creating a project on Google Code and also submitting a plugin for the WordPress plugin hosting.

It's basically an easy way to add the Google Translate Web Element to a page or a post on your website. You just wrap the content you want to translate with the a [translate_this] shortcode.

Here is the plugin on Google Code.

Friday, February 11, 2011

Early Morning At The Airport

I just arrived in Washington Dulles airport at 5:30 am, actually getting in almost 45 minutes early - and it was a United flight! There is something wonderful about being at an airport early in the morning. So much so that it was making me feel almost poetic. It was still dark outside and there weren't very many people in the airport. Just a few people roaming around that were in a similar situation as me, connecting from an early arriving flight. The nice thing was how quiet it is. No announcements yet, and hushed tones from passengers that were talking to each other.

As the sun came up, and the sky outside turned from black to the pre-dawn pink, I just felt an overwhelming since of joy. Perhaps a little because I am looking forward to being home with my family after two weeks abroad, but I sensed that it was something else as well.

Upon reflection, I think the reason why I love the airport so much, but perhaps why on this morning it filled me with a sense of joy, is, as the sun came up and slowly illuminated the aircraft parked at the gates, it struck me that the rows of airplanes awaiting passengers represent freedom. Hundreds of airplanes all waiting to take passengers wherever in the world they want to go. And it is at this time, that short window prior to the start of the hustle and bustle of the the day, that it feels as though you have limitless potential. The world is waiting. Pick your destination and go!

Wednesday, July 22, 2009

IE6 Transparent PNG Fix for Blackbaud NetCommunity

This was a tough one! Mostly because of having to work around the way Blackbaud's CMS, NetCommunity works.

Since we still receive a surprisingly significant amount of traffic from people browsing with IE6, we had to make sure that our nice, slick semi-transparent PNGs were not showing up with the lovely gray-blue background that IE6 likes to put on there.

One nice thing about NetCommunity is it has jQuery built-in, and so I've been really trying to use it for all things Javascript, (which really isn't a hardship since jQuery is so nice and easy to use - up until this point I had been using Prototype mostly).

So, cut to the chase, I was having a problem using Angus Turnbull's great solution, and searching around for a jQuery solution lead me to Supersleight. I uploaded it to a document library in our NetCommunity installation and then also uploaded a 1x1 transparent gif to the image library in NetCommunity.

Finding out the Document ID and the Image ID, I then added the following lines to each layout for our site:

Notice the shim... line points to the image id for the transparent gif. You could change the supersleight plugin, but this is easier and leaves the plugin intact.

But here is the most important part!
The plugin is looking for images with the class "tpng" and with a extension of .png. Since the images on NetCommunity are dynamically generated (i.e. view.image?id=1844) you have to drop down to the HTML in the editor and add &.png to the end of each image. For example:

Of course, the HTML editor will convert the & to & amp;, but that is okay. Still works.

Yes, this is a rather crazy hack, but until that glorious day where IE6 is no longer used, it'll have to do.

Wednesday, July 1, 2009

Adding acts_as_reportable to environment.rb

We're trying to make sure that our Rails app as a reproduce-able install process with required gems, and in doing so, adding the config.gem line into our environment.rb code.

For some reason, I kept getting a "gem does not exist - acts_as_reportable" error when I would then run rake gems:install.

I had the following line in my environment.rb

config.gem 'acts_as_reportable'

But no luck.

Turns out to be an easy fix, if you're really familiar with the syntax for environment.rb, which evidently I'm not. :)
Here is the proper line:

config.gem 'ruport'
config.gem 'acts_as_reportable', :lib => 'ruport'

Notice, that ruport is mentioned before it.

Wednesday, June 24, 2009

Scheduled Encrypt, Back-up mySQL database and send to Secure FTP

I needed a way to backup our mySQL database, encrypt it and send it via Secure FTP to a server that was not our webserver (to have it in a different location).

Turns out that this isn't as straight-forward as it may seem if you want to use a cron job to schedule it on a regular basis.  The reason being, SSH provides ways to make things secure, and thus, hard to automate.

So you end up giving up some of the security to automate it.  I thought that this would be okay, as if an attacker got onto my webserver, my security is compromised anyway, and seeing the Secure FTP settings in the script would be a moot point.  I basically just didn't want to be passing the data in an non-secure pipe.

So here it is, a hybrid bash shell, with some expect scripting built in:
#! /bin/bash # MySQL server name SERVER= # server directory to backup to BACKDIR= # date format that is appended to filename DATE=`date +'%m-%d-%Y'` #----------------------MySQL Settings--------------------# # MySQL server location HOST=localhost # MySQL username USER= # MySQL password PASS= # List all of the MySQL databases that you want to backup in here, # each separated by a space DBS="" # set to 'y' if you want to backup all your databases. this will override # the database selection above. DUMPALL=n #----------------------FTP Settings--------------------# # set "FTP=y" if you want to enable FTP backups FTP=y # FTP server settings; should be self-explanatory FTPHOST="" FTPUSER="" FTPPASS="" # directory to backup to. if it doesn't exist, file will be uploaded to # first logged-in directory FTPDIR="" #-------------------Deletion Settings-------------------# # delete old files? DELETE=y # how many days of backups do you want to keep? DAYS=7 #----------------------End of Settings------------------# # check of the backup directory exists # if not, create it if [ -e $BACKDIR ] then echo "Backups directory already exists" else mkdir $BACKDIR fi if [ $DUMPALL = "y" ] then echo "Creating list of all your databases..." mysql -h $HOST --user=$USER --password=$PASS -e "show databases;" > dbs_on_$SERVER.txt # redefine list of databases to be backed up DBS=`sed -e ':a;N;$!ba;s/\n/ /g' -e 's/Database //g' dbs_on_$SERVER.txt` fi echo "Backing up MySQL databases..." for database in $DBS do mysqldump -h $HOST --user=$USER --password=$PASS $database > \ $BACKDIR/$SERVER-mysqlbackup-$database-$DATE.sql # Encrypt DB Dump using GPG gpg --symmetric --batch --passphrase-fd 0 < --output $BACKDIR/$SERVER-mysqlbackup-$database-$DATE.sql.gpg $BACKDIR/$SERVER-mysqlbackup-$database-$DATE.sql gzip -f -9 $BACKDIR/$SERVER-mysqlbackup-$database-$DATE.sql.gpg done if [ $FTP = "y" ] then echo "Initiating Secure FTP connection..." cd $BACKDIR ATTACH=`for file in *$DATE.sql.gpg.gz; do echo -n -e "put ${file}\n"; done` # Uses sftp expect - <spawn sftp $FTPUSER@$FTPHOST # expect "Are you sure you want to continue connecting (yes/no)?" # send "yes\r" expect "$FTPUSER@$FTPHOST's password:" send "$FTPPASS\r" expect "sftp>" send "cd backups\r" expect "sftp>" send "$ATTACH\r" expect "sftp>" send "quit\r" EOF echo -e "Secure FTP transfer complete! \n" fi if [ $DELETE = "y" ] then find $BACKDIR -name "*.sql.gpg.gz" -mtime $DAYS -exec rm {} \; find $BACKDIR -name "*.sql" -mtime $DAYS -exec rm {} \; if [ $DAYS = "1" ] then echo "Yesterday's backup has been deleted." else echo "The backup from $DAYS days ago has been deleted." fi fi echo Database backup complete!# expect "Are you sure you want to continue connecting (yes/no)?"# send "yes\r"expect "$FTPUSER@$FTPHOST's password:"send "$FTPPASS\r"expect "sftp>"send "cd backups\r"expect "sftp>"send "$ATTACH\r"expect "sftp>"send "quit\r"EOFecho -e "Secure FTP transfer complete! \n"fi if [ $DELETE = "y" ]thenfind $BACKDIR -name "*.sql.gpg.gz" -mtime $DAYS -exec rm {} \;find $BACKDIR -name "*.sql" -mtime $DAYS -exec rm {} \; if [ $DAYS = "1" ]thenecho "Yesterday's backup has been deleted."elseecho "The backup from $DAYS days ago has been deleted."fifi echo Database backup complete!

Tuesday, September 16, 2008

Google Analytics Campaign URL Encoding with Ruby on Rails

So we're launching a couple pages that we wanted to enrich the links and encode them with the Google Analytics campaign tracking data. (If you're not familiar with it, you can take a look at the url builder here).

Basically, you create a campaign source (email, ad, or whatever) a medium and a name and it will build a url for you.

All of the links on the page we were building had the same source and campaign name, but different medium names.

So at the top of the page in the view (I thought about doing this in the controller, but for our purposes it is a per page kind of thing) I added a little erb code:
<% source_link = 'blah' medium_link1 = 'link1' medium_link2 = 'link2' campaign_link = 'nameofcampaign' %>

Now, when you have a link_to helper in your page, add the following parameters after the :action

:utm_source => source_link, :utm_medium => medium_link1, :utm_campaign => campaign_link

This way, if you want to update the URL encoding for Google Analytics for a different campaign down the line, it's a matter of just changing the variables at the top of the page, rather than going down through the whole view to change every source and every campaign link.

Anyways, I felt proud of myself to be a little bit more DRY in my view with Google Analytics Campaign URL encoding.

Using before_save in the model

I was doing some refactoring of our email subscription functionality and I added a table column to include a hash of the email address which I would use in the unsubscribe process.

So I created a new migration that added the column and calculated the hashes for the existing email addresses in the table, however, it was not automatically creating the hashes using the current functionality.

So, it's a pretty simple call in the model, a function called before_save.

My model file ends up looking like this, which creates the hash right before it saves the email address when someone subscribes.
before_save :add_email_hash

def add_email_hash
self.email_hash = Digest::SHA1.hexdigest( + "addsometexttomakeithardtorecreate")

And that's it! An addition to the model file which is supposed to handle this sort of thing, rather than the controller.