Validating email addresses with Regular Expressions

Posted Jan 23, 2007 12:23:49 AM

Wrote a quick function today also to verify that the syntax of an email address is valid, using regular expressions.

^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$

This will match a userid containing letters, numbers, underscores, dots and hyphens, followed by an at sign, then a domain name containing letters, numbers, hyphens and dots, followed by a suffix of 2-to-4 characters.

Using this regex, I can ensure that the user has entered a potentially valid email address before attempting to send out a confirmation email.

Generating Random Hex Codes in Ruby

Posted Jan 23, 2007 12:08:47 AM

Part of my new comment system for Blosxonomy includes an email verification system that requests the user to confirm their email before their comments will be displayed on the blog. To do this, I wrote a simple random-hex-code generator to build unique url's. When a comment is posted by a user with an unconfirmed email address, a random URL is generated using the random hex code, and emailed to that user.

Generating such codes in ruby is very simple, and often useful, so I thought I'd post the method I wrote to do it:

def generateUniqueHexCode( codeLength )
    validChars = ("A".."F").to_a + ("0".."9").to_a
    length = validChars.size

    hexCode = ""
    1.upto(codeLength) { |i| hexCode << validChars[rand(length-1)] }

    hexCode
end

validChars is initialized to be an array containing characters 'A' through 'F', and '0' through '9'. I then append codeLength random characters from that array to the hexCode string and return it.

While a more robust implementation would validate uniqueness against the list of already generated IDs, the assumption is that these ID's are short lived, and the likelihood of generating repeats IDs given a sufficient length (I use 64) is miniscule.

Blosxonomy Comments

Posted Jan 22, 2007 9:09:34 PM

Well after a months-long hiatus from doing anything even remotely related to Blosxonomy, I finally got around to implementing a simple user-confirmation system for the comments system.

Now, when you post comments to an entry, your email is verified against a list of authorized emails. If your email isn't in my list, a verification email is automatically generated and sent to you, containing a link. All you need to do is click the link to confirm your email, and voiala, your comment appears, and you're free to comment as much as you like.

Hopefully this simple step will significantly reduce the amount of comment spam I recieve on this site.

In other sad news, a simple typo in a bash script resulted in the accidental deletion of all comments in my database. *Oops*. Guess I should have made a backup.

Blosxonomy and Databases - a Perfect Pair

Posted Dec 2, 2005 6:20:26 PM

Blosxonomy 0.7 will be up momentarily at Blosxonomy.com - I just finished upgrading timfanelli dot com to make use of it's new database support. Blosxonomy now has the option of storing entries in either the traditional Blosxom style files, or in its own database format.

The database offers significant performance improvements over the file system; especially when you're working with folksonomies. There was previously no way for me to generate my tag cloud and related links without parsing parts of entry entry file on my site; and with about 200 entries right now, my response times for a typical page request were very near 2.5 seconds.

With the new database schema in place, and a complete rewrite of the underlying folksonomy engine to make use of it, I'm looking at about 1 second response times, which is a significant improvement. I'd recommend that anyone who decides to switch to Blosxonomy start using it, but the Blosxom style entry support will always be there too :).

To facilitate the migration, Blosxonomy also now has a utility to convert your entries between the two formats, so you can move back and forth as you like. For now, it's also the easiest way to get new entries into the database - just make a Blosxom style post and import it. Similary, updating old entries can be achieved by exporting the entry, editing it as you would any Blosxom post, and then reimporting it -- a process which does not affect your timestamps :).

I have one or two more things to clean up, and then it'll be available for download over at Blosxonomy. Stay tuned!

Installing Ruby DBI with PostgreSQL on OS X 10.4

Posted Dec 2, 2005 12:10:09 AM

I spent a little while tonight getting ramped up to finally implement a database layer for Blosxonomy, and discovered that getting Ruby DBI working was more difficult that I expected. In particular, it turns out my Mac had multiple versions of Ruby installed, resulting in mis-linked binaries that cause abnormal terminations when I tried to use DBI. The specific error I got was:

/usr/lib/ruby/site_ruby/1.8/powerpc-darwin8.3.0/postgres.bundle: [BUG] Bus Error

Here's what I did to resolve this error and get DBI working:

Cleanup your Rubies

OS X 10.4 ships with Ruby 1.8.2. I had also installed Fink, which installed Ruby 1.8.1. I don't recall if I caused it to do that, or if it was a dependency of something else. This was my first problem. You can check to see if you have them both installed by doing:

/sw/bin/ruby --version
/usr/bin/ruby --version

Ideally, only /usr/bin/ruby will work, and /sw/bin/ruby won't exist. If this is not the case, you should remove the Fink installation. The latest version of Ruby DBI wouldn't link against Ruby 1.8.1, it would only link against 1.8.2 or 1.8.3. To remove Fink's Ruby, I did:

fink remove ruby18-dev ruby

This removed Ruby 1.8.1 and the development header files from your system.

Next, we'll upgrade to Ruby 1.8.3 - Download 1.8.3 Here, extract the tar bundle, and perform the following steps:

configure --prefix=/usr
make
sudo make install

I have XCode 2.2 installed, and use GCC 4.0 by default and did not have any problems. You shouldn't either. This will install the new Ruby over the old one, and also install the new development headers. Confirm that the installation was successful:

ruby --version

Should now show version 1.8.3

Install Ruby PostgreSQL

Download the latest snapshot PostgreSQL Ruby bindings from http://ruby.scripting.ca/postgres/. At the time of this writing, the latest snapshot is 20051127, which is compatible with PostgreSQL 6, 7 and 8. The installation is simple:

ruby extconf.rb \
	--with-pgsql-include-dir=/path/to/postgres/includes \
	--with-pgsql-lib-dir=/path/to/postgres/libs

make
sudo make install

You can omit the --with-pgsql... options if you have PostgreSQL installed in a standard location. I installed PostgreSQL 8.1 using Fink, and did not need to specify these options.

Ruby DBI

Finally, we'll install the DBI library. You can download it from their Rubyforge project page. At the time of this writing, version 0.0.23 is the latest, released on May 20, 2004

Again, installation is very easy, just do:

ruby setup.rb config --with=dbi,dbd_pg
ruby setup.rb setup
ruby setup.rb install

--with=dbi,dbd_pg tells the config to prepare the DBI library, and the PostgreSQL driver. You can specify as many plugin drivers as you like in that. Popular ones will include dbd_mysql, dbd_odbc and dbd_db2. Once this step is complete, you'll be able to connect to your PostgreSQL databases using DBI.

A very very very short sample

Here's the quick sample I was using to test that DBI was properly installed. It's very simple and doesn't do anything at all, but it makes calls to DBI enough to have caused the error earlier.

require 'dbi'
dbh = DBI.connect('DBI:pg:databasename')

dbh.disconnect
Delicious Link: Intro to Ruby: A Developer's Quick Start

Posted Nov 19, 2005 5:30:10 PM

http://www.timfanelli.com/item/ruby_quick_start?flav=html

Intro to Ruby: A Developer's Quick Start

Posted Nov 19, 2005 11:44:11 AM

Ruby is a very powerful, fun, and expressive language - I thought instead of continuing my sometimes long winded Intro To XXX series this morning, I'd post a cheat sheet of sorts to get you started writing Ruby code quickly.

Numbers

Ruby has three built-in types to support numeric values: Fixnum, Bignum, and Float. The names are pretty indicative of what they're used for, Fixnum for fixed length integers, Bignum for infinite length integers, and Float for floating point numbers.

12345                           # Fixnum (decimal)
0x45DF				# Fixnum (hexadecimal)
04577				# Fixnum (octal)
0b11010010			# Fixnum (binary)
12345678901234567890		# Bignum

Fixnum stores values in a native machine word minus 1 bit. Values that can not be represented in this size are automatically converted to a Bignum instance.

Strings

Strings in Ruby may be either single or double quoted. Single quoted strings will not be evaluated in Ruby, other than two special back-slash notation expressions: \\ and '. Double quoted strings will be evaluated for expression subsitution, and will obey back-slash notation the way most C, C++, and Java developers would expect.

puts 'This is my string.\n It does not look the way I think.\n'
puts "This is my string.\nIt looks just fine to me!\n"

Yields the following output:

This is my string.\n It does not look the way I think.\n
This is my string.
It looks just fine to me!

Expressions substitution in double quoted strings allows you to insert arbitrary values inline, instead of using string formatting syntax:

myname = "Timothy Fanelli"
myage = 25

intro1 = "Hello, my name is #{myname} and I am #{myage}."
intro2 = "Hello, my name is " + myname + " and I am " + myage.to_s + "."
intro3 = "Hello, my name is %s and I am %d." % [ myname, myage ]

intro1, intro2 and intro3 are all identical strings.

The third string is a general case of using Ruby's builtin sprintf or format function, which look like this:

sprintf( formatstring, *args )
format( formatstring, *args )

Where you can pass any number of arguments in (they'll be converted to an array called args), and formatstring can use the following conversion specifiers:

%b  Binary integer
%c  Single character
%d  Decimal integer
%e  Decimal integer displayed in exponential form
%f  Floating point number
%g  Same as %e if exponent is less than -4, %f otherwise
%o  Octal integer
%s  String
%u  Unsigned decimal integer
%x  Hexadecimal integer

You can substitute %E, %G and %X for %e, %g and %x respectively if you prefer capital letters in your notation.

Regular Expressions

Ruby has powerful builtin regular expression support. A regular expresion is expressed either as a pattern between delimiting forward-slashes, a pattern between an arbitrary delimiter preceded by a %r, or can be declared explicitly as a Regexp class instance, like so:

/pattern/
/pattern/im	# Regex with modifiers.
%r!pattern!
Regexp::new( "pattern", modifiers )

Any of these declarations can be treated as a Regexp instance. Calling Regexp::match( string ) will return a Match object or nil if the string does not match the pattern. Match objects can be indexed into if you used match groups in your regular expression.

Where ! in this instance could be replaced by either a matching pair of parenthesis, square or angle brackets or simpy two of any character of your choosing.

The following regular expression modifiers are supported:

i  Regexp::IGNORECASE  Case insensitive
x  Regexp::EXTENDED   Ignore whitespace and allow comments in regular expressions
m  Regexp::MULTILINE  Treat new lines as regular characters instead of whitespace
o                     Substitute only once

Methods

The general form for all Ruby method declarations is as follows:

def methodname ( parameterlist )
	method body
end

The parameter list can contain any number reference names, and can optionally have two special arguments indicated by an asterisk and ampersand respectively: *var and &block. Any excess parameters passed into a method beyond those explicity declared in the method's parameter list will be converted to an array and passed in as var (or whatever you chose to name it). &block will be a Proc instance if a code block was specified, or nil otherwise.

Methods that support code blocks, such as List::sort, are called like so:

mylist = [ 'a', 'c', 'x', 'b' ]
mylist.sort { |a,b| a <=> b }

Where the sort method takes no explicit arguments, and only a Proc instance. This mechanism allows you to pass arbitrary code blocks into a method that can be executed repeatedly. This is comparable to C's function pointers or C#'s delegate type. The arguments a and b between the vertical bars are the arguments to the Proc instance that will passed in when it is executed.

The return value of a method can be explicitly stated using a return statement. If return is omitted, then the method returns the value of the last expression evaluated.

Classes

You can define a class using the class keyword, and there's built in support for your standard public, private and protected access control mechanisms:

class Fruit
public 
  def initialize( color )
      setColor color
  end

  def getColor
    @color
  end

protected
  def setColor( color )
    @color = color
  end

private
  def doSomething

  end
end

class Lemon < Fruit
  def initialize
    super 'yellow'
  end
end

mylemon = Lemon::new

In this case Lemon extends Fruit. Lemon::initialize is public by default because it's not under any other access modifier. initialize is a special method that gets triggered when an object is instantiated using the built in new. super, when used in a method calls the parent class method of the same name. If no arguments are specified to super then the calling method's arguments are passed in the same order to the parent class' method. Finally, the @ prefix on a variable declares it as an instance variable of the class. An @@ prefix would declare it as a class variable, which is comparable to static variables in C++ objects and Java.

Modules

Modules are very similar to classes, except that they have no base class and can not be instantiated. Use the module keyword to declare a module, like so:

module Colors
  def convertToRGB( colorname )
    ...
  end
end

A class can include a module using a mechanism knowns as "Mix-ins":

class Fruit
  include Colors

  initialize( color )
    @color = convertToRGB( color )
  end
end

Including a module makes its methods and properties available to your class.

Conclusion

So that's where I'll leave off for now. This is still just the very basics, but it should be more than enough to get you on your way to becoming a Ruby developer!

Intro to Ruby: Hello, World!

Posted Nov 17, 2005 9:50:27 PM

I recently decided I was going to take up Ruby programming as a hobby. Prior to that I had taken on Python, which has quickly become one of my favorite languages. Ruby is coming in a close second, and could easily take it over as soon as they have built in XML support - so I thought I'd follow up my Intro To Python series with some Intro To Ruby posts.

I've found Ruby very easy to learn and use - I decided to learn Ruby about 2 weeks ago now, and have since released Blosxonomy, a Ruby implementation of a Blosxom like blogging system that powers this site. Its syntax is simple and intuitive, and the grammar is expressive and easy to learn.

Ruby carries the tag line "Programmers' Best Friend." I don't know if I'd go quite this far, but it's certainly a very developer friendly language - most comparable to Python in my experience. Its syntax, according to ruby-lang.org is inspired by Eiffel and Ada, neither of which I've had the pleasure of working with - but as both a Python and Ruby newby (relatively speaking), I find them quite dissimilar. The language's nuances are also very Pythonesque - as we'll see in this post, and my Ruby copy of Building Strings using Lists, which will come in a day or two.

Having compared Ruby to Python thus far, I'd like to start by pointing out that Ruby, unlike Python, uses delimited code blocks. Python determines code blocks based on their indentation level in the source, which can cause issues when editors convert between tabs and spaces. Ruby doesn't use an explicit statement-delimeter though, just a programmer-friendly newline. This combination eases development and allows developers use thier own coding style, which for seasoned developers is a solid positive, and for newbies a potential negative (for those of us that have to read your code, that is.)

Ruby, like Python, is both dynamically and strictly typed; meaning that a variable's datatype is determined at runtime by its value; and that an objects type can not be changed.

So in any event, after a long winded birds eye view of my opinion of Ruby, I'll show you a hello-world:

def sayHi( name )
	puts "Hello, %s!" % String( name ) 
end

sayHi( "Derf" )

def sayHi declares a function called sayHi. The parameter list is not required, but in this case, we pass a single parameter called name. Notice that the type of the name variable is not declared, that's because it's dynamically typed - meaning I could pass any object I want into the method.

To account for that fact, I use the built-in String( x ) function to create a string from the given instance, no matter what its type.

The body of the method uses the puts method, which simply writes a string to standard-out followed by a new line. The string is formatted using syntax identical to Python's, using %s inside the string to represent some arbitrary string variable, and passing in the arguments following a % symbol after the string. If you had more than one argument, you'd pass them in a list by encapsulating the comma separated arguments in square-brackes [ ].

The code outside of the method declarations is the "main" part of the program. This is analogous to writing the "main" method of a C or C++ program - and identical to "global" code in a Python application.

So that's the extreme basics and birds eye view of Ruby. My next post will be about Ruby's built-in Arrays and Hashes (practically identical to Pthon's), and I'll also cover CGI support.

If you're anxious to get started on your own though, I would recommend reading Programming Ruby: The Progmatic Programmer's Guide online. If you're very comfortable with programming languages in general, O'Reilly's Ruby In A Nutshell provides a very thorough and technical reference - but it's not a great book to learn from (a must have once you're comfortable with the basics of the syntax and grammar though).

Homepage Summaries in Blosxonomy

Posted Nov 15, 2005 11:09:22 PM

Whipped out a quick plugin tonight along the lines of optimizing my fold at timfanelli.com. It trims my entries down to 20 words summaries when you're viewing my home page. When you visit my homepage then, you only see the first 2 lines of text for recent entries, and you can follow the title link to view the full story.

When you browse by tags, the ReadMore plugin takes effect showing you potentially more content than you'd see on my home page, but still not the entire story (unless, of course, I neglected to add a <!-- BREAK --> to my post.). The home page summary plugin strips any markup from the summary to prevent bastardizing otherwise valid markup, and also to prevent my other plugins (such as ReadMore) from taking effect.

Home page summaries will be released when I post Blosxonomy 0.6 - but if you're curious to see how it works, here's the method I use to generate an entry's summary:

def generateSummary( body )
	# Remove markup from the body
	body = body.gsub( /<[^>]+>/, '' )

	# Split the body into words (consecutive blocks of non-whitespace)
	words = body.scan( /[^\s]+/ )

	# Take the first 20 words
	words = words.slice( 0, [20, words.length].min )
	
	# Join them back together in a paragraph.
	return "<p>%s...</p>" % words.join( " " )
end

I use this same method now to generate <atom:description> content in my Atom 1.0 renderer plugin.

Trackback for Blosxonomy

Posted Nov 13, 2005 12:40:58 PM

I ported the pyBlosxom trackback plugin this morning, so I now have trackback support re-enabled! Very exciting.

Now that Blosxonomy has comments and trackback support, I'm going to release version 0.5 at Blosxonomy.com

Powered by Me

Posted Nov 10, 2005 5:35:40 PM

I recently decided it'd be fun to learn the Ruby language, and that a worthy undertaking to do so would be to port pyBlosxom - which I've been using for a little over a year now. The result is something I'm quite proud of, and am still actively working on -- Blosxonomy.

"What a name!", you say? Blosxonomy is a Blosxom-like blogging system implemented with Folksonomy in mind. Basically I've written it from the ground up to incorporate the work I've been doing in pyBlosxom to support tags, tag clouds, and external relations (specifically to Amazon products).

So now I'm proud to say that timfanelli dot com is:

Powered by me.

If you're interested, I have a guide at Blosxonomy.com that covers installing Blosxonomy in parallel with pyBlosxom, so you can try it out with out modifying your existing pyBlosxom site. In fact, timfanelli dot com still has pyBlosxom running, I use it for the Portico gallery plugin, which I haven't gotten to port yet.

Popular Tags

Recent Stories

${recent.title}

About

My name is Tim Fanelli, I am a software engineer in Northern NY. I spend most of my time working, and when I can, I try to post interesting things here.

Cigar Dossiers