»
S
I
D
E
B
A
R
«
My X is better than your Y – PHP/Ruby Edition, Part XVI
Jul 12th, 2009 by Bill

This post started as a comment to a recent post on KillerPHP.com entitled, “What happened to Ruby? And why PHP is KING of the Web.” The longer my comment became the more I thought I could use a little Google juice myself and why let someone else have all the fun?!

A Twitter post by the normally well-reasoned Cal Evans, Director of the PHP Center for Expertise for Ibuildings lead to my discovery of the KillerPHP.com post that seems to be only the latest in a long line of PHP versus Ruby/Rails rants. I can’t imagine Cal is trolling near as much as it appears the post’s author, Stefan Mischook, but I digress…

I have been a PHP developer since 2001 and founded OINK-PUG in 2005, a month before I discovered Rails and came to enjoy writing Ruby. I prefer Ruby but cannot escape PHP because there is just so much PHP work out there! I am active in both communities locally and would be remiss not to send a shout out to the folks at CART and CincyRB too.

It has been my experience that there is a vast difference in the two communities of developers. Due to PHP’s popularity and low barrier of entry, many developers find it very inviting, especially those with little or no experience. Without much intellectual investment you can produce some rather impressive results, especially using products like Drupal and Wordpress.

Where Ruby shines is when the job calls for something that falls outside of PHP’s sweet spot. Personally, I think it does an equally good job in PHP’s sweet spot but that’s another post. These more challenging cases require more than parochial knowledge of software development; even seemingly simple concepts like a Web UI for SMS can benefit from the skills of a craftsman. That’s where the Ruby community shines and the PHP community falls a bit short.

I suggest that the primary indicator of this is the Ruby community’s embrace of test driven development (TDD) and its relative absence from the PHP community. I would ask those readers who have inherited someone else’s code for both PHP and Ruby projects which they’ve found more maintainable, PHP or Ruby? I always swallow hard when looking at someone else’s PHP code for the first time whereas I know in a minute whether or not a Ruby/Rails project I’ve inherited is going to be trouble. I just look in the “test” directory in the project’s root directory or run rake, created by fellow Cincinnati Rubyist, Jim Weirich by the way!

TDD is only one example of what differentiates the two communities. I can’t count the number of PHP projects I have inherited that were clearly devoid of source control management, or even simple code convention. Excluding the never ending “Spaces vs. Tabs” debate, I’ve never encountered either of these problems with “legacy” Ruby/Rails code. I invite everyone with more than a couple years experience IN BOTH LANGUAGES to add their thoughts about my claims in the comments below. Everyone else, knock yourselves out. Beat me up. Beat on Stephan. You won’t, nor should you expect to change either of our opinions.

Yes, Twitter could have been written in PHP, Wordpress could have been written in Ruby, and Drupal in Python. If that’s all you’ve taken from this post then you’re not “getting it” or more likely, I’ve poorly stated my argument. Nonetheless, clearly Mischook has a bone to pick with Ruby but I find nothing new in his rant and took the bait anyway. I’m overjoyed that he loves PHP so much. I did too, until I found something that “I” like better. I don’t feel the need to justify my decision to others, although I think I just did. Anyone (including me) can write bad Ruby code. Some can write beautiful PHP. In fact, some of the brightest people I know still write PHP but I say, let them eat CakePHP.

Git configuration setting causing Fixture::FormatError in Rails
May 15th, 2009 by Bill

I just spent a few hours banging my head on this one but it appears that my local git configuration was the source of a Fixture::FormatError occurring while running tests in Rails.

The specific error looked like this:

Fixture::FormatError: a YAML error occurred parsing /dev/current/myapp/test/fixtures/blogs.yml.
Please note that YAML must be consistently indented using spaces. Tabs are not allowed.
Please have a look at http://www.yaml.org/faq.html
The exact error was:
  ArgumentError: Anonymous modules have no name to be referenced by

I have not yet pin pointed (and may never pin point) the exact source of the problem but what appears to have been causing it was my local git configuration (~/.gitconfig) which included the following two lines:

[core]
    whitespace = fix,-indent-with-non-tab,trailing-space,cr-at-eol

The git config file was passed around during a Cincinnati Ruby Brigade meeting and, being a git noob, I installed it dutifully.

Anyway, removing those two lines from the .gitconfig file resolved the issue after I moved the existing clone aside and re-cloned the repository. Feel free to provide details in the comments if you’ve got a clue and/or can shed some light on the exact cause.

Rails on Windows
Mar 15th, 2009 by Bill

During a recent Cincinnati Ruby Brigade meeting a new member who was running Windows would have benefited from a minimalist guide to installing Ruby on Rails on Windows. A few days later I was forced to press my old Windows desktop system into service as an emergency Rails development platform. So I decided to write this post.

Thanks to All About Ruby for providing a starting point for my research for this post.

Nota Bene: These instructions are Windows XP specific. If you’re using another flavor of Windows YMMV. Also, all references to software version numbers are current only at the date of this posting.

Install Ruby

  1. Download the One-Click Ruby Installer for Windows.
  2. Run the installer. I unchecked the option to install the SciTE text editor which saved a whopping 1.5MB of storage.
  3. If you so desire, you can verify that the install succeeded by running ruby -v on the command line:
  4. C:\>ruby -v
    ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]
    
  5. Update RubyGems by running gem update –system on the command line:
  6. C:\>gem update --system
    Updating RubyGems...
    Attempting remote update of rubygems-update
    Successfully update rubygems-update-1.3.1
    Updating version of RubyGems to 1.3.1
    Installing RubyGems 1.3.1
    [...]
    RubyGems system software updated
    
  7. Again, verify the install succeeded by running gem -v on the command line:
  8. C:\>gem -v
    1.3.1
    

Install SQLite

  1. From the Precompiled Binaries For Windows section download the command-line program (sqlite_X_Y_Z.zip) and the SQLite library DLL without the TCL bindings (sqlitedll_X_Y_Z.zip) unless you need the TCL bindings.
  2. Copy the contents of both ZIP files into a directory of your choosing. I chose C:\sqlite. Others have chosen to place them in the bin directory under the base directory chosen during the Ruby installation, typically C:\ruby\bin. I chose a separate directory so that future upgrades of Ruby do not break my SQLite installation.
  3. If you chose a separate directory in the previous step, like C:\sqlite, you will want to add that directory to your PATH environment variable.
    1. To do so, navigate Windows Explorer until you can see My Computer. Right click the My Computer icon and select Properties. Select the Advanced tab and then the
      Environment Variables button.
    2. If you have sufficient privilege, I recommend adding the path to the PATH variable under the System variable section so that SQLite is available to all system users. However, if you do not have sufficient privilege OR are certain that the current user is the only user that will require access to SQLite then you are free to add the path to the PATH variable under the User variables section.
    3. To add the path, select the PATH variable and click the Edit button. Add the appropriate path, in my case C:\sqlite, to either the beginning or end of the existing PATH string then click the OK button.

    WARNING! Be careful that you do not corrupt or delete the existing PATH string.

  4. Install the SQLite gem by running gem install sqlite3-ruby on the command line. Select the mswin32 gem when prompted.
  5. C:\>gem install sqlite3-ruby
    Select which gem to install for your platform (i386-mswin32)
     1. sqlite3-ruby 1.2.4 (ruby)
     2. sqlite3-ruby 1.2.3 (x86-mingw32)
     3. sqlite3-ruby 1.2.3 (mswin32)
     4. sqlite3-ruby 1.2.3 (ruby)
     5. Skip this gem
     6. Cancel installation
    > 3
    Successfully installed sqlite3-ruby-1.2.3-mswin32
    Installing ri documentation for sqlite3-ruby-1.2.3-mswin32...
    Installing RDoc documentation for sqlite3-ruby-1.2.3-mswin32...
    

Install Rails

  1. Install the Rails gem by running gem install rails on the command line:
  2. C:\>gem install rails
    Successfully installed rails-2.2.2
    1 gem installed
    
  3. To verify the install run rails -v on the command line:
  4. C:\>rails -v
    Rails 2.2.2
    

Test Everything

Let’s mimic the first couple of minutes of the famous Creating a weblog in 15 minutes video to test things out.

  1. Change into a directory of your choosing and create a Rails project by running rails blog on the command line:
  2. C:\dev>rails blog
    	create
    	create app/controllers
    	create app/helpers
    	create app/models
    	create app/views/layouts
    [...]
    
  3. Change into the newly created project directory, verify that the server starts, and that the app appears at http://localhost:3000:
  4. C:\dev\blog>ruby script\server
    -> Booting WEBrick...
    -> Rails 2.2.2 application started on http://localhost:3000
    -> Ctrl-C to shutdown server; call with --help for options
    [2009-03-14 13:55:45] INFO  WEBrick 1.3.1
    [2009-03-14 13:55:45] INFO  ruby 1.8.6 (2007-03-13) [i386-mswin32]
    [2009-03-14 13:55:45] INFO  WEBrick::HTTPServer#start pid-192 port-3000
    
  5. Run the scaffold generator script:
  6. C:\dev\blog>ruby script\generate scaffold Post title:string body:text
    	exists app/models
    	exists app/controllers
    	exists app/helpers
    	create app/views/posts
    [...]
     dependency model
    	exists	app/models/
    	exists	test/unit/
    	exists	test/fixtures/
    	create	app/models/post.rb
    	create	test/unit/post_test.rb
    	create	test/fixtures/posts.yml
    	create	db/migrate
    	create	db/migrate/20090315055640_create_posts.rb
    
  7. Run rake db:migrate on the command line:
  8. C:\dev\blog>rake db:migrate
    (in C:\dev\blog)
    ==  CreatePosts: migrating ======================================================
    -- create_table(:posts)
       -> 0.0940s
    ==  CreatePosts: migrated (0.0940s) =============================================
    
  9. Start the server again and visit http://localhost:3000/posts, click the New post link, and create a new post.

There you have it. Go ahead and finish the rest of the Creating a weblog in 15 minutes video and leave me a comment if you encounter any trouble.

Coming Soon! Git on Windows.

Just Missed Me – Chapter Two
Apr 20th, 2007 by Bill

The “Rails” components of the website were completed in about 20 minutes and consist of nothing more than a form which provides the user a means to supply a date and returns an appropriate (some would argue) list of the deceased.

After quite a bit of experimentation and refactoring I have refined the script which parses Wikipedia’s Persondata from the XML dump to the following:

#!/usr/bin/env ruby

require 'ParseDate'

fp = "/Users/sjobs/data/enwiki-20061130-pages-articles.xml"
page_start = /\
/
page_end = /\<\/page\>/
has_persondata = /\{\{Persondata/
regex_name = /\|NAME=(.*)/
regex_page_title = /\(.*)\<\/title\>/
regex_page_id = /\(.*)\<\/id\>/
regex_date_death = /\|DATE OF DEATH=(.*)/

def cleanse data
  wiki_marks = /\[\[|\]\]|\{\{|\}\}/
  clean = data.strip.gsub(wiki_marks, '')
  clean.gsub(/'/, "\\\\'")
end

def process_date date
  if !date.nil?
    date = ParseDate.parsedate(date)
    if !date[0].nil? and !date[1].nil? and !date[2].nil?
      sprintf("%04d-%02d-%02d", date[0], date[1], date[2])
    else
      nil
    end
  end
end

File.exists? fp and File.readable? fp
File.open(fp, "r") do |file|
  i = 0
  concat = false
  page_text = ''
  while line = file.gets
    if !page_start.match(line).nil? or concat
      concat = true
      page_text = page_text + line
      if !page_end.match(line).nil?
        if !has_persondata.match(page_text).nil?
          i = i + 1
          date_death = regex_date_death.match(page_text)[1] unless ↵
              regex_date_death.match(page_text).nil?
          name = regex_name.match(page_text)[1] unless ↵
              regex_name.match(page_text).nil?
          page_title = regex_page_title.match(page_text)[1] unless ↵
              regex_page_title.match(page_text).nil?
          page_id = regex_page_id.match(page_text)[1] unless ↵
              regex_page_id.match(page_text).nil?
          date_of_death = process_date(cleanse(date_death))
          if !date_of_death.nil?
            puts "- !ruby/object:Person"
            puts "  attributes:"
            puts "    date_of_death: " + date_of_death unless date_of_death.nil?
            puts "    name: " + cleanse(name) unless name.nil?
            puts "    page_title: " + cleanse(page_title) unless page_title.nil?
            puts "    page_id: " + cleanse(page_id) unless page_id.nil?
            puts "    id: " + i.to_s
          end
        end
        concat = false
        page_text = ''
      end
    end
  end
end

Much of the data I was parsing is no longer being collected as I am re-evaluating the schema since much of the data within the Wikipedia database is void of any consistent form (as expected).

The keen observer will note that this script generates YaML which I import painlessly via Geoffrey Grosenbach’s ar_fixtures plugin for Rails.

The next problem to solve is the parse the free-form date to be entered by the user. I had this working using Ruby’s ParseDate but I’m unable to reliably create a date that will then be feed to MySQL or generate a nil value. I am passing the output from ParseDate’s sole method, parsedate, to the new method of Ruby’s Date class but after working for a while the method is now returning an “invalid date” error. More later…

Just Missed Me – Chapter One
Apr 17th, 2007 by Bill

OK, need proof that I’m a nuby? How’s this for proof?

#!/usr/bin/env ruby

fp = "/Users/sjobs/data/enwiki-20061130-pages-articles.xml"
page_start = /\
/
page_end = /\<\/page\>/
has_persondata = /\{\{Persondata/
regex_name = /\|NAME=(.*)/
regex_alter_names = /\|ALTERNATIVE NAMES=(.*)/
regex_description = /\|SHORT DESCRIPTION=(.*)/
regex_page_title = /\(.*)\<\/title\>/
regex_page_id = /\(.*)\<\/id\>/
regex_date_birth = /\|DATE OF BIRTH=(.*)/
regex_place_birth = /\|PLACE OF BIRTH=(.*)/
regex_date_death = /\|DATE OF DEATH=(.*)/
regex_place_death = /\|PLACE OF DEATH=(.*)/
regex_revision_timestamp = ↵
   /\.*\(.*)\<\/timestamp\>.*\<\/revision\>/m

File.exists? fp and File.readable? fp
File.open(fp, "r") do |file|
  concat = false
  page_text = ''
  while line = file.gets
    if !page_start.match(line).nil? or concat
      concat = true
      page_text = page_text + line
      if !page_end.match(line).nil?
        if !has_persondata.match(page_text).nil?
          name = regex_name.match(page_text)[1] unless ↵
            regex_name.match(page_text).nil?
          alternative_names = regex_alter_names.match(page_text)[1] unless ↵
            regex_alter_names.match(page_text).nil?
          description = regex_description.match(page_text)[1] unless ↵
            regex_description.match(page_text).nil?
          page_title = regex_page_title.match(page_text)[11] unless ↵
            regex_page_title.match(page_text).nil?
          page_id = regex_page_id.match(page_text)[1] unless ↵
            regex_page_id.match(page_text).nil?
          date_birth = regex_date_birth.match(page_text)[1] unless ↵
            regex_date_birth.match(page_text).nil?
          place_birth = regex_place_birth.match(page_text)[1] unless ↵
            regex_place_birth.match(page_text).nil?
          date_death = regex_date_death.match(page_text)[1] unless ↵
            regex_date_death.match(page_text).nil?
          place_death = regex_place_death.match(page_text)[1] unless ↵
            regex_place_death.match(page_text).nil?
          revision_timestamp = regex_revision_timestamp.match(page_text)[1] unless ↵
            regex_revision_timestamp.match(page_text).nil?
        end
        concat = false
        page_text = ''
      end
    end
  end
end

I decided that STX would require too significant an investment in time and while I may integrate hpricot at some point the solution above seems sufficient for the moment.

I have yet to begin importing any of the data into the database. I’ll want to format the data consistently and remove the wiki specific mark-up. Feel free to rip the code apart and please do make suggestions. I am after all a nuby.

Just Missed Me – Chapter Zero
Apr 12th, 2007 by Bill

I became interested in hpricot while experimenting during the creation of a prospecting system for my employer. Driving home from work one day I hatched an idea for a website that would employ hpricot to pull its data from Wikipedia’s Persondata.

Due to the extremely large size of the associated data file I soon determined that an hpricot-based solution would not scale. Digging a bit on Wikipedia I discovered STX which appears to be a more promising means of proceeding. I’ll keep you posted.

»  Substance: WordPress   »  Style: Ahren Ahimsa