<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5575882483986490924</id><updated>2012-01-27T12:04:19.184-08:00</updated><category term='ruby'/><category term='ASP.NET .NET'/><category term='podcast'/><category term='javascript'/><category term='s3'/><category term='ActiveRecord'/><category term='Hibernate'/><category term='apt-get'/><category term='tomcat'/><category term='accordion'/><category term='osx'/><category term='RMagick MacOSX'/><category term='DOM'/><category term='Audio'/><category term='pdocast'/><category term='git'/><category term='screencasts'/><category term='plugin'/><category term='gem'/><category term='nginx'/><category term='iBATIS'/><category term='aws'/><category term='bdd'/><category term='jsspec'/><category term='RubyGems Merb'/><category term='jQuery'/><category term='MySQL'/><category term='php'/><category term='REST'/><category term='ajax'/><category term='Merb'/><category term='Music'/><category term='GridView'/><category term='openssl'/><category term='ASP'/><category term='scriptaculous'/><category term='Perl'/><category term='Java'/><category term='WebSphere'/><category term='Gems'/><category term='APT'/><category term='testing erlang tsung'/><category term='C#'/><category term='will_paginate'/><category term='rspec'/><category term='mdb2'/><category term='ruby on rails'/><category term='Firefox'/><category term='cache_fu'/><category term='scriptrunner ruby rails erlang'/><category term='DocBook'/><category term='mongrel'/><category term='Eclipse'/><category term='Sortable'/><category term='javascript css'/><category term='pear'/><category term='mp3'/><category term='Bash'/><category term='testing'/><category term='ubuntu'/><category term='caching'/><category term='prototype'/><category term='subversion'/><category term='.NET'/><category term='Excel'/><title type='text'>dougsparling.org (kl93)</title><subtitle type='html'>Tech Tidbits - Ruby, Ruby On Rails, Merb, .Net, Javascript, jQuery, Ajax, CSS...and other random bits and pieces.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>83</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8964926765706219656</id><published>2009-08-14T12:08:00.000-07:00</published><updated>2009-08-14T15:21:10.527-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testing erlang tsung'/><title type='text'>HTTP Load Testing/Tsung</title><content type='html'>I'm reviewing a few open source tools for load testing for a project at work. We selected Tsung, an open-source multi-protocol distributed load testing tool written in Erlang. I'll go into Tsung in more depth in a later post, but for now I'll list several resources that I've found helpful.&lt;br /&gt;&lt;h2&gt;Tsung&lt;/h2&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://tsung.erlang-projects.org/"&gt;Tsung&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://video.google.com/videoplay?docid=4970190663681048083"&gt;Google Video: Erlang eXchange 2008: Tsung Tutorial - Mickael Remond&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://lists.process-one.net/pipermail/tsung-users/"&gt;The Tsung-users Archives&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://beebole.com/en/blog/erlang/test-performance-and-scalability-of-your-web-applications-with-tsung/"&gt;Test the Performance and Scalability of Your Web Applications With Tsung&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://austinmills.name/?p=40"&gt;Using Tsung for Load Testing Rails or Web Apps&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;Load Testing&lt;/h2&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/06/23/episode-15-load-testing-part-1"&gt;RailsLab: Scaling Rails - Episode #15 - Load Testing - Part 1&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/06/23/episode-16-load-testing-part-2"&gt;RailsLab: Scaling Rails - Episode #16 - Load Testing - Part 2&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://linux.com/archive/feature/143896"&gt;Linux.com - Using free software for HTTP load testing (2006)&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.linux.com/archive/feature/34432"&gt;Linux.com - Stress testing an application with JMeter (2004)&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://serverfault.com/questions/2107/tools-for-load-testing-http-servers"&gt;Server Fault - Tools for load-testing HTTP servers?&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.opensourcetesting.org/"&gt;Open Source Testing Tools&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://googletesting.blogspot.com/2007/10/performance-testing.html"&gt;Google Testing Blog - Performance Testing (Goranka Bjedov)&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://video.google.com/videoplay?docid=-6891978643577501895"&gt;Google Video: Using open source tools for performance testing (Google Tech Talk - Goranka Bjedov)&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/magazine/cc188783.aspx"&gt;Real-World Load Testing Tips to Avoid Bottlenecks When Your Web App Goes Live&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.codeplex.com/PerfTesting"&gt;patterns &amp; practices: Performance Testing Guidance&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8964926765706219656?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8964926765706219656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8964926765706219656' title='49 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8964926765706219656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8964926765706219656'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2009/08/http-load-testingtsung.html' title='HTTP Load Testing/Tsung'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>49</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4986623143658475672</id><published>2009-05-21T17:05:00.000-07:00</published><updated>2009-05-21T17:13:37.986-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scriptrunner ruby rails erlang'/><title type='text'>New Blogs - scriptrunner.com, Learning Erlang</title><content type='html'>I'll be posting all Ruby, Rails, and related topics at my new blog, &lt;a href="http://www.scriptrunner.com/"&gt;http://www.scriptrunner.com/&lt;/a&gt; (and I'll probably move over my old posts as well)&lt;br /&gt;&lt;br /&gt;I'm also getting ready to start another new blog, "Learning Erlang," currently located at &lt;a href="http://learningerlang.blogspot.com/"&gt;http://learningerlang.blogspot.com/&lt;/a&gt; which I may move it to its own domain once I get started.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4986623143658475672?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4986623143658475672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4986623143658475672' title='94 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4986623143658475672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4986623143658475672'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2009/05/new-blogs-scriptrunnercom-learning.html' title='New Blogs - scriptrunner.com, Learning Erlang'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>94</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3998463523068044966</id><published>2009-02-06T10:07:00.000-08:00</published><updated>2009-02-21T09:21:52.644-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Rails &amp; Testing - Resources</title><content type='html'>This is an in-progress set of testing resources aimed at the Ruby/Rails developer...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Rails Guides&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://guides.rubyonrails.org/testing_rails_applications.html"&gt;http://guides.rubyonrails.org/testing_rails_applications.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;nullislove.com&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://www.nullislove.com/2007/11/14/testing-in-rails-part-1-unit-testing-in-ruby/"&gt;http://www.nullislove.com/2007/11/14/testing-in-rails-part-1-unit-testing-in-ruby&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nullislove.com/2007/11/17/testing-in-rails-part-2-unit-testing-ruby-classes/"&gt;http://www.nullislove.com/2007/11/17/testing-in-rails-part-2-unit-testing-ruby-classes/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nullislove.com/2007/11/20/testing-in-rails-part-3-unit-testing-ruby-classes-cont/"&gt;http://www.nullislove.com/2007/11/20/testing-in-rails-part-3-unit-testing-ruby-classes-cont/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nullislove.com/2007/11/29/testing-in-rails-part-4-unit-testing-in-rails/"&gt;http://www.nullislove.com/2007/11/29/testing-in-rails-part-4-unit-testing-in-rails/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nullislove.com/2007/12/07/testing-in-rails-part-5-unit-testing-activerecord-models/"&gt;http://www.nullislove.com/2007/12/07/testing-in-rails-part-5-unit-testing-activerecord-models/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nullislove.com/2007/12/21/testing-in-rails-part-6-fixtures/"&gt;http://www.nullislove.com/2007/12/21/testing-in-rails-part-6-fixtures/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nullislove.com/2008/01/08/testing-in-rails-part-7-activerecord-relationships/"&gt;http://www.nullislove.com/2008/01/08/testing-in-rails-part-7-activerecord-relationships/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nullislove.com/2008/01/23/testing-in-rails-part-8-validations/"&gt;http://www.nullislove.com/2008/01/23/testing-in-rails-part-8-validations/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;railstips.org&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://railstips.org/2008/12/12/when-you-dont-know-test"&gt;http://railstips.org/2008/12/12/when-you-dont-know-test&lt;/a&gt;&lt;br /&gt;&lt;a href="http://railstips.org/2009/1/6/test-or-die"&gt;http://railstips.org/2009/1/6/test-or-die&lt;/a&gt;&lt;br /&gt;&lt;a href="http://railstips.org/2009/1/7/my-testing-theory"&gt;http://railstips.org/2009/1/7/my-testing-theory&lt;/a&gt;&lt;br /&gt;&lt;a href="http://railstips.org/2009/1/8/test-or-die-validates-uniqueness-of"&gt;http://railstips.org/2009/1/8/test-or-die-validates-uniqueness-of&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;andrzejonsoftware.blogspot.com&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://andrzejonsoftware.blogspot.com/2007/05/15-tdd-steps-to-create-rails.html"&gt;http://andrzejonsoftware.blogspot.com/2007/05/15-tdd-steps-to-create-rails.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://andrzejonsoftware.blogspot.com/2007/05/and-some-more-tdd-steps-with-rails.html"&gt;http://andrzejonsoftware.blogspot.com/2007/05/and-some-more-tdd-steps-with-rails.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://andrzejonsoftware.blogspot.com/2008/01/what-do-i-gain-from-tdd-or-bdd.html"&gt;http://andrzejonsoftware.blogspot.com/2008/01/what-do-i-gain-from-tdd-or-bdd.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Behavior Driven Development (BDD)&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://behaviour-driven.org/"&gt;http://behaviour-driven.org&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.jamievandyke.com/blog/2009/01/09/building-a-gem-using-bdd.html"&gt;http://www.jamievandyke.com/blog/2009/01/09/building-a-gem-using-bdd.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.oreillynet.com/pub/a/ruby/2007/08/09/behavior-driven-development-using-ruby-part-1.html"&gt;http://www.oreillynet.com/pub/a/ruby/2007/08/09/behavior-driven-development-using-ruby-part-1.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.oreillynet.com/pub/a/ruby/2007/08/30/behavior-driven-development-using-ruby-part-2.html"&gt;http://www.oreillynet.com/pub/a/ruby/2007/08/30/behavior-driven-development-using-ruby-part-2.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Misc&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://giantrobots.thoughtbot.com/2008/11/7/a-critical-look-at-the-current-state-of-ruby-testing"&gt;http://giantrobots.thoughtbot.com/2008/11/7/a-critical-look-at-the-current-state-of-ruby-testing&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.cis.upenn.edu/~matuszek/cit597-2008/Lectures/40-unit-testing-in-rails.ppt"&gt;http://www.cis.upenn.edu/~matuszek/cit597-2008/Lectures/40-unit-testing-in-rails.ppt&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.tutorialspoint.com/ruby-on-rails-2.1/rails-unit-testing.htm"&gt;http://www.tutorialspoint.com/ruby-on-rails-2.1/rails-unit-testing.htm&lt;/a&gt;&lt;br /&gt;&lt;a href="http://technicalpickles.com/posts/test-or-die-validates-uniqueness-of-shoulda-and-factory-girl-edition"&gt;http://technicalpickles.com/posts/test-or-die-validates-uniqueness-of-shoulda-and-factory-girl-edition&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Blogs&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://blog.jayfields.com/"&gt;http://blog.jayfields.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Books&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530/"&gt;http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.railsprescriptions.com/"&gt;http://www.railsprescriptions.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Videos&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://peepcode.com/products/test-first-development"&gt;http://peepcode.com/products/test-first-development&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Tools&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://rspec.info/"&gt;http://rspec.info&lt;/a&gt;&lt;br /&gt;&lt;a href="http://technicalpickles.com/posts/adding-cucumber-to-a-ruby-project"&gt;http://technicalpickles.com/posts/adding-cucumber-to-a-ruby-project&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ultrasaurus.com/sarahblog/2008/12/rails-2-day-3-behavior-driven-development/"&gt;http://www.ultrasaurus.com/sarahblog/2008/12/rails-2-day-3-behavior-driven-development/&lt;/a&gt; (BDD &amp; Cucumber)&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3998463523068044966?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3998463523068044966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3998463523068044966' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3998463523068044966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3998463523068044966'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2009/02/rails-testing.html' title='Rails &amp; Testing - Resources'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1295985431908527564</id><published>2008-11-18T16:10:00.000-08:00</published><updated>2008-11-18T16:32:39.914-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nginx'/><category scheme='http://www.blogger.com/atom/ns#' term='mongrel'/><category scheme='http://www.blogger.com/atom/ns#' term='Merb'/><title type='text'>Nginx, Mongrel, Merb</title><content type='html'>Quick notes on installing and configuring nginx and running with existing mongrel and Merb app on my MacBookPro.&lt;br /&gt;&lt;br /&gt;1) Download and install PCRE (if needed)&lt;br /&gt;http://www.pcre.org/&lt;br /&gt;ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/&lt;br /&gt;ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.8.tar.gz&lt;br /&gt;&lt;br /&gt;$ ./configure&lt;br /&gt;$ ./make&lt;br /&gt;$ ./make install&lt;br /&gt;&lt;br /&gt;2) Download and install nginx:&lt;br /&gt;http://nginx.net/&lt;br /&gt;The latest stable version is nginx-0.6.32, the change log.&lt;br /&gt;http://sysoev.ru/nginx/nginx-0.6.32.tar.gz&lt;br /&gt;&lt;br /&gt;$ ./configure&lt;br /&gt;$ ./make&lt;br /&gt;$ ./make install&lt;br /&gt;&lt;br /&gt;# Edit nginx.conf file (/usr/local/nginx/conf/nginx.conf)&lt;br /&gt;# Note - based on Ezra's blog post (see notes below)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;user  nobody;&lt;br /&gt;worker_processes  2;&lt;br /&gt;&lt;br /&gt;error_log  logs/error.log notice;&lt;br /&gt;pid        logs/nginx.pid;&lt;br /&gt;&lt;br /&gt;events {&lt;br /&gt;    worker_connections  1024;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;http {&lt;br /&gt;    include       mime.types;&lt;br /&gt;    #include       conf/mime.types;&lt;br /&gt;    default_type  application/octet-stream;&lt;br /&gt;&lt;br /&gt;    # no sendfile on OSX uncomment &lt;br /&gt;    #this if your on linux or bsd&lt;br /&gt;    #sendfile        on;&lt;br /&gt;    tcp_nopush     on;&lt;br /&gt;&lt;br /&gt;    keepalive_timeout  65;&lt;br /&gt;    tcp_nodelay        on;&lt;br /&gt;&lt;br /&gt;    upstream mongrel {&lt;br /&gt;        server 127.0.0.1:4000;&lt;br /&gt;        server 127.0.0.1:4001;&lt;br /&gt;        server 127.0.0.1:4002;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    gzip on;&lt;br /&gt;    gzip_min_length  1100;&lt;br /&gt;    gzip_buffers     4 8k;&lt;br /&gt;    gzip_types       text/plain;&lt;br /&gt;&lt;br /&gt;    server {&lt;br /&gt;        listen       80;&lt;br /&gt;        #server_name  localhost;&lt;br /&gt;        root /Users/dsparlingimbp/git/dougsparlingdotcom/public;&lt;br /&gt;&lt;br /&gt;        access_log  off;&lt;br /&gt;        rewrite_log on;&lt;br /&gt;&lt;br /&gt;        location ~ ^/$ {&lt;br /&gt;          if (-f /index.html){&lt;br /&gt;            rewrite (.*) /index.html last;&lt;br /&gt;          }&lt;br /&gt;           proxy_pass  http://mongrel;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        location / {&lt;br /&gt;          if (!-f $request_filename.html) {&lt;br /&gt;            proxy_pass  http://mongrel;&lt;br /&gt;          }&lt;br /&gt;          rewrite (.*) $1.html last;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        location ~ .html {&lt;br /&gt;           root /Users/dsparlingimbp/git/dougsparlingdotcom/public;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;           location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov)$ {&lt;br /&gt;          root /Users/dsparlingimbp/git/dougsparlingdotcom/public;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        location / {&lt;br /&gt;            proxy_pass  http://mongrel;&lt;br /&gt;            proxy_redirect     off;&lt;br /&gt;            proxy_set_header   Host             $host;&lt;br /&gt;            proxy_set_header   X-Real-IP        $remote_addr;&lt;br /&gt;            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4) Commands for starting and stopping nginx&lt;br /&gt;start: sudo /usr/local/nginx/sbin/nginx &lt;br /&gt;stop: sudo kill `cat /usr/local/nginx/logs/nginx.pid`&lt;br /&gt;&lt;br /&gt;5) Start Mongrel cluster (I'm using 3 Mongrels):&lt;br /&gt;$ merb -c 3&lt;br /&gt;or&lt;br /&gt;$ merb -p 4000 -c 3&lt;br /&gt;&lt;br /&gt;6) Resources&lt;br /&gt;http://brainspl.at/articles/2006/08/23/nginx-my-new-favorite-front-end-for-mongrel-cluster&lt;br /&gt;http://articles.slicehost.com/2008/5/13/ubuntu-hardy-installing-nginx-from-source&lt;br /&gt;http://articles.slicehost.com/2008/5/13/ubuntu-hardy-adding-an-nginx-init-script&lt;br /&gt;http://articles.slicehost.com/2008/4/25/ubuntu-hardy-setup-page-1&lt;br /&gt;http://articles.slicehost.com/2008/4/25/ubuntu-hardy-setup-page-2&lt;br /&gt;http://forum.slicehost.com/comments.php?DiscussionID=2179&lt;br /&gt;http://merb.rubyforge.org/files/README.html&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1295985431908527564?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1295985431908527564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1295985431908527564' title='30 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1295985431908527564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1295985431908527564'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/11/nginx-mongrel-merb.html' title='Nginx, Mongrel, Merb'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>30</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-6902065705409480086</id><published>2008-11-09T05:42:00.000-08:00</published><updated>2008-11-09T11:55:54.385-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Ruby - Randomize arrays and strings</title><content type='html'>&lt;p&gt;&lt;br /&gt;Randomize the elements of an array:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;random_array = my_array.sort_by{rand}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Randomize a string (jumble a given word):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;jumbled_word = word.split("").sort_by{rand}.join&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-6902065705409480086?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/6902065705409480086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=6902065705409480086' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6902065705409480086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6902065705409480086'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/11/ruby-randomize-array.html' title='Ruby - Randomize arrays and strings'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1532065808680462827</id><published>2008-11-08T04:33:00.000-08:00</published><updated>2008-11-08T04:42:41.547-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RubyGems Merb'/><title type='text'>Updating to RubyGems 1.3.0 on Mac OS X Leopard 10.5.4</title><content type='html'>When attempting to stall final release of Merb 1.0, I got an error message that I needed RubyGems version &gt;=1.3.0:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ERROR:  Error installing merb:&lt;br /&gt; merb-core requires RubyGems version &gt;= 1.3.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So I did the usual "gem update --system" but got an error:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ sudo gem update --system&lt;br /&gt;Password:&lt;br /&gt;Updating RubyGems&lt;br /&gt;Updating rubygems-update&lt;br /&gt;Successfully installed rubygems-update-1.3.0&lt;br /&gt;ERROR:  While executing gem ... (NameError)&lt;br /&gt;    undefined local variable or method `remote_gemspecs' for #&lt;Gem::Commands::UpdateCommand:0x116e15c&gt;&lt;br /&gt;$ gem --version&lt;br /&gt;1.2.0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I found that you have to run a second set of instructions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ sudo gem install rubygems-update&lt;br /&gt;Successfully installed rubygems-update-1.3.0&lt;br /&gt;1 gem installed&lt;br /&gt;$ sudo update_rubygems &lt;br /&gt;Installing RubyGems 1.3.0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;More info here:&lt;br /&gt;&lt;a href="http://rails.wincent.com/wiki/Updating_to_RubyGems_1.3.0_on_Mac_OS_X_Leopard_10.5.4" target="_blank"&gt;http://rails.wincent.com/wiki/Updating_to_RubyGems_1.3.0_on_Mac_OS_X_Leopard_10.5.4&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1532065808680462827?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1532065808680462827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1532065808680462827' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1532065808680462827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1532065808680462827'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/11/updating-to-rubygems-130-on-mac-os-x.html' title='Updating to RubyGems 1.3.0 on Mac OS X Leopard 10.5.4'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8919220756897861535</id><published>2008-08-27T10:18:00.000-07:00</published><updated>2008-08-27T10:24:40.908-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET .NET'/><category scheme='http://www.blogger.com/atom/ns#' term='GridView'/><title type='text'>Dynamic Details Row in GridView</title><content type='html'>&lt;pre&gt;&lt;br /&gt;&amp;lt;%@ Page Language="C#" %&gt;&lt;br /&gt;&amp;lt;%@ Import Namespace="System.Web.Configuration" %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;script runat="server"&gt;&lt;br /&gt;    &lt;br /&gt;    void GridView1_PreRender(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        if (GridView1.SelectedRow != null)&lt;br /&gt;        {&lt;br /&gt;            Table table = GridView1.SelectedRow.Parent as Table;&lt;br /&gt;&lt;br /&gt;            if (table != null)&lt;br /&gt;                CreateRow(table, GridView1.SelectedIndex);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void CreateRow(Table table, int index)&lt;br /&gt;    {&lt;br /&gt;        GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);&lt;br /&gt;        row.Cells.Add(CreateColumn());&lt;br /&gt;        table.Rows.AddAt(index + 2, row);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private TableCell CreateColumn()&lt;br /&gt;    {&lt;br /&gt;        TableCell cell = new TableCell();&lt;br /&gt;        cell.ColumnSpan = GridView1.Columns.Count;&lt;br /&gt;        cell.Width = Unit.Percentage(100);&lt;br /&gt;&lt;br /&gt;        DataSourceControl ds = CreateDataSourceControl();&lt;br /&gt;        &lt;br /&gt;        cell.Controls.Add(ds);&lt;br /&gt;        cell.Controls.Add(CreateDetailsView(ds));    &lt;br /&gt;        return cell;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static DetailsView CreateDetailsView(DataSourceControl ds)&lt;br /&gt;    {&lt;br /&gt;        DetailsView dv = new DetailsView();&lt;br /&gt;        dv.AutoGenerateRows = true;&lt;br /&gt;        dv.DataSourceID = ds.ID;&lt;br /&gt;        return dv;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private DataSourceControl CreateDataSourceControl()&lt;br /&gt;&lt;br /&gt;    {&lt;br /&gt;        SqlDataSource ds = new SqlDataSource();&lt;br /&gt;        ds.ConnectionString = WebConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;&lt;br /&gt;        ds.SelectCommand = "SELECT * FROM [Users] WHERE [UserID] = @UserID";&lt;br /&gt;        ds.ID = "SqlDataSource2";&lt;br /&gt;        &lt;br /&gt;        Parameter cp = new Parameter("UserID", TypeCode.String, GridView1.SelectedValue.ToString());&lt;br /&gt;        ds.SelectParameters.Add(cp);&lt;br /&gt;        return ds;&lt;br /&gt;    }   &lt;br /&gt;    &lt;br /&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" &gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;head id="Head1" runat="server"&gt;&lt;br /&gt;    &amp;lt;title&gt;Untitled Page&amp;lt;/title&gt;&lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;body&gt;&lt;br /&gt;    &amp;lt;form id="form1" runat="server"&gt;&lt;br /&gt;    &amp;lt;div&gt;&lt;br /&gt;&lt;br /&gt;        &amp;nbsp;&amp;lt;asp:GridView ID="GridView1" Runat="server" DataSourceID="SqlDataSource1" DataKeyNames="UserID"&lt;br /&gt;            AutoGenerateColumns="False" OnPreRender="GridView1_PreRender" EnableViewState="False"&gt;&lt;br /&gt;            &amp;lt;Columns&gt;&lt;br /&gt;                &amp;lt;asp:CommandField ShowSelectButton="True"&gt;&lt;/asp:CommandField&gt;&lt;br /&gt;                &amp;lt;asp:BoundField ReadOnly="True" HeaderText="UserID" DataField="UserID" SortExpression="UserID"&gt;&lt;/asp:BoundField&gt;&lt;br /&gt;                &amp;lt;asp:BoundField HeaderText="UserName" DataField="UserName" SortExpression="UserName"&gt;&amp;lt;/asp:BoundField&gt;&lt;br /&gt;            &amp;lt;/Columns&gt;&lt;br /&gt;        &amp;lt;/asp:GridView&gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT [UserID], [UserName] FROM [Users]"&lt;br /&gt;            ConnectionString="&amp;lt;%$ ConnectionStrings:MyConnectionString %&gt;"&gt;&lt;br /&gt;        &amp;lt;/asp:SqlDataSource&gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;/div&gt;&lt;br /&gt;    &amp;lt;/form&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&gt;&lt;br /&gt;&amp;lt;/html&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8919220756897861535?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8919220756897861535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8919220756897861535' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8919220756897861535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8919220756897861535'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/08/dynamic-details-row-in-gridview.html' title='Dynamic Details Row in GridView'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-304143868238441767</id><published>2008-08-23T17:58:00.000-07:00</published><updated>2008-08-23T18:29:41.122-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Music'/><category scheme='http://www.blogger.com/atom/ns#' term='mp3'/><category scheme='http://www.blogger.com/atom/ns#' term='s3'/><category scheme='http://www.blogger.com/atom/ns#' term='aws'/><title type='text'>Amazon S3 with Ruby aws-s3 gem</title><content type='html'>I stated using Amazon S3 to store and backup the music I've written and recorded. I'm using the Ruby aws-s3 gem. Note that I check for some basic audio file types so I don't have to manually type the bucket or mime-type.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;aws-s3.rb&lt;br /&gt;---------&lt;br /&gt;#!/usr/bin/env ruby&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'aws/s3'&lt;br /&gt;&lt;br /&gt;# File to upload&lt;br /&gt;local_file = ARGV[0]&lt;br /&gt;&lt;br /&gt;# bucket &amp; mime-type&lt;br /&gt;if local_file =~ /mp3$/&lt;br /&gt;  bucket = 'doug_mp3'&lt;br /&gt;  mime_type = 'audio/mpeg'&lt;br /&gt;elsif local_file =~ /wav$/&lt;br /&gt;  bucket = 'doug_wav'&lt;br /&gt;  mime_type = 'audio/x-wav'&lt;br /&gt;elsif local_file =~ /aif[c|f]?$/&lt;br /&gt;  bucket = 'doug_aiff'&lt;br /&gt;  mime_type = 'audio/x-aiff'&lt;br /&gt;else&lt;br /&gt;  bucket = ARGV[1]&lt;br /&gt;  mime_type = ARGV[2] || "application/octet-stream"&lt;br /&gt;end &lt;br /&gt;&lt;br /&gt;if bucket.nil?&lt;br /&gt;  puts "need a bucket"&lt;br /&gt;  exit&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;puts "file: #{local_file}"&lt;br /&gt;puts "bucket: #{bucket}"&lt;br /&gt;puts "mime_type: #{mime_type}"&lt;br /&gt;&lt;br /&gt;AWS::S3::Base.establish_connection!(&lt;br /&gt;  :access_key_id     =&gt; 'REPLACE_ME',&lt;br /&gt;  :secret_access_key =&gt; 'REPLACE_ME'&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;base_name = File.basename(local_file)&lt;br /&gt; &lt;br /&gt;puts "Uploading #{local_file} as '#{base_name}' to '#{bucket}'"&lt;br /&gt;&lt;br /&gt;AWS::S3::S3Object.store(&lt;br /&gt;  base_name,&lt;br /&gt;  File.open(local_file),&lt;br /&gt;  bucket,&lt;br /&gt;  :content_type =&gt; mime_type&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;puts "Uploaded!"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I can call the script a couple ways:&lt;br /&gt;&lt;br /&gt;# with defaults based on extension&lt;br /&gt;$ ruby aws-s3.rb mysong.mp3&lt;br /&gt;&lt;br /&gt;# or explicitly (file, bucket, mime-type)&lt;br /&gt;$ ruby aws-s3.rb mysong.mp3 doug_mp3 'audio/mp3'&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-304143868238441767?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/304143868238441767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=304143868238441767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/304143868238441767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/304143868238441767'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/08/i-stated-using-amazon-s3-to-store-and.html' title='Amazon S3 with Ruby aws-s3 gem'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-5773701408005645079</id><published>2008-08-23T16:33:00.000-07:00</published><updated>2008-08-23T18:06:11.971-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gems'/><category scheme='http://www.blogger.com/atom/ns#' term='Merb'/><title type='text'>Add and remove a remote source from gem 'remote sources''</title><content type='html'>I was attempting to add a gem and ran into an error I hadn't seen before:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Macintosh:aws-s3 dsparlingimbp$ sudo gem i aws-s3&lt;br /&gt;WARNING:  RubyGems 1.2+ index not found for:&lt;br /&gt;        http://merbivore.com&lt;br /&gt;&lt;br /&gt;RubyGems will revert to legacy indexes degrading performance.&lt;br /&gt;Updating metadata for 63 gems from http://gems.rubyforge.org/&lt;br /&gt;...............................................................&lt;br /&gt;complete&lt;br /&gt;ERROR:  could not find gem aws-s3 locally or in a repository&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So I tried to update gems:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Macintosh:aws-s3 dsparlingimbp$ sudo gem update --system&lt;br /&gt;Updating RubyGems&lt;br /&gt;WARNING:  RubyGems 1.2+ index not found for:&lt;br /&gt; http://merbivore.com&lt;br /&gt;&lt;br /&gt;RubyGems will revert to legacy indexes degrading performance.&lt;br /&gt;Updating metadata for 63 gems from http://gems.rubyforge.org/&lt;br /&gt;...............................................................&lt;br /&gt;complete&lt;br /&gt;ERROR:  While executing gem ... (Gem::RemoteFetcher::FetchError)&lt;br /&gt;    bad response Not Found 404 (http://merbivore.com/Marshal.4.8)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next I looked the gems environment:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Macintosh:rubygems-1.2.0 dsparlingimbp$ gem env&lt;br /&gt;RubyGems Environment:&lt;br /&gt;  - RUBYGEMS VERSION: 1.2.0&lt;br /&gt;  - RUBY VERSION: 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.8.5]&lt;br /&gt;  - INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8&lt;br /&gt;  - RUBY EXECUTABLE: /usr/local/bin/ruby&lt;br /&gt;  - EXECUTABLE DIRECTORY: /usr/local/bin&lt;br /&gt;  - RUBYGEMS PLATFORMS:&lt;br /&gt;    - ruby&lt;br /&gt;    - x86-darwin-8&lt;br /&gt;  - GEM PATHS:&lt;br /&gt;     - /usr/local/lib/ruby/gems/1.8&lt;br /&gt;  - GEM CONFIGURATION:&lt;br /&gt;     - :update_sources =&gt; true&lt;br /&gt;     - :verbose =&gt; true&lt;br /&gt;     - :benchmark =&gt; false&lt;br /&gt;     - :backtrace =&gt; false&lt;br /&gt;     - :bulk_threshold =&gt; 1000&lt;br /&gt;     - :sources =&gt; ["http://gems.rubyforge.org", "http://merbivore.com"]&lt;br /&gt;  - REMOTE SOURCES:&lt;br /&gt;     - http://gems.rubyforge.org&lt;br /&gt;     - http://merbivore.com&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Noticing the issues with Merb (which I recently installed), I removed http://merbivore.com from the list of remote sources:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sudo gem sources -r http://merbivore.com&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I went ahead and added github while I was at it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sudo gem sources -a http://gems.github.com&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Checked my gems environment:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Macintosh:rubygems-1.2.0 dsparlingimbp$ gem env&lt;br /&gt;RubyGems Environment:&lt;br /&gt;  - RUBYGEMS VERSION: 1.2.0&lt;br /&gt;  - RUBY VERSION: 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.8.5]&lt;br /&gt;  - INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8&lt;br /&gt;  - RUBY EXECUTABLE: /usr/local/bin/ruby&lt;br /&gt;  - EXECUTABLE DIRECTORY: /usr/local/bin&lt;br /&gt;  - RUBYGEMS PLATFORMS:&lt;br /&gt;    - ruby&lt;br /&gt;    - x86-darwin-8&lt;br /&gt;  - GEM PATHS:&lt;br /&gt;     - /usr/local/lib/ruby/gems/1.8&lt;br /&gt;  - GEM CONFIGURATION:&lt;br /&gt;     - :update_sources =&gt; true&lt;br /&gt;     - :verbose =&gt; true&lt;br /&gt;     - :benchmark =&gt; false&lt;br /&gt;     - :backtrace =&gt; false&lt;br /&gt;     - :bulk_threshold =&gt; 1000&lt;br /&gt;     - :sources =&gt; ["http://gems.rubyforge.org", "http://gems.github.com"]&lt;br /&gt;  - REMOTE SOURCES:&lt;br /&gt;     - http://gems.rubyforge.org&lt;br /&gt;     - http://gems.github.com&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Everything looked good, so I tried to install aws-s3 gem again:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Macintosh:rubygems-1.2.0 dsparlingimbp$ sudo gem install aws-s3&lt;br /&gt;Successfully installed aws-s3-0.5.1&lt;br /&gt;1 gem installed&lt;br /&gt;Installing ri documentation for aws-s3-0.5.1...&lt;br /&gt;Installing RDoc documentation for aws-s3-0.5.1...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Et Voilà! C'est si bon...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-5773701408005645079?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/5773701408005645079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=5773701408005645079' title='83 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5773701408005645079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5773701408005645079'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/08/add-and-remove-remote-source-from-gem.html' title='Add and remove a remote source from gem &apos;remote sources&apos;&apos;'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>83</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-921230595576921815</id><published>2008-07-26T18:21:00.000-07:00</published><updated>2008-07-26T18:55:53.774-07:00</updated><title type='text'>authentication token</title><content type='html'>I had a need to both validate the source of data sent to a web service and to only accept the data if it was sent within a limited time period. One thing I didn't need, (but I imagine would be necessary in most cases) was to only allow the request once, in which case you would probably want to store the token in a database and flag it once it had been "redeemed." &lt;br /&gt;&lt;br /&gt;To create the token, first concatenate current time in epoch seconds (or whatever time format you like, but stick with UTC since the end user may be any where in the world), username, and a password, then m5d and base64 that concatenated string and prepend it with the same timestamp, separated by a colon (':').&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;require 'digest/md5'&lt;br /&gt;require 'base64'&lt;br /&gt;&lt;br /&gt;# Username/password&lt;br /&gt;UID = 'marypoppins'&lt;br /&gt;PWD = "supercalifragilisticexpialidocious"&lt;br /&gt;&lt;br /&gt;# create token using utc secconds, uid, and pwd&lt;br /&gt;def create_token(t=nil)&lt;br /&gt;  timestamp = t || Time.now.utc.to_i.to_s&lt;br /&gt;  plaintext = timestamp + UID + PWD&lt;br /&gt;  md5 = Digest::MD5.digest(plaintext)&lt;br /&gt;  return timestamp + ':' + Base64.encode64(md5).strip&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;# validate token&lt;br /&gt;def validate_token(token)&lt;br /&gt;  token_timestamp = token.split(':')[0]&lt;br /&gt;  token2 = create_token(token_timestamp)&lt;br /&gt;  return token == token2 ? true : false&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;# validate timestamp and token&lt;br /&gt;def validate_token_and_timestamp(token,num_secs=60)&lt;br /&gt;  token_timestamp = token.split(':')[0]&lt;br /&gt;  return nil if Time.now.to_i - token_timestamp.to_i &gt; num_secs&lt;br /&gt;  token2 = create_token(token_timestamp)&lt;br /&gt;  return token == token2 ? true : false&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The most basic example: create a token and validate it by creating a new token using the timestamp in the original token with the known user id and password. If the two tokens match, the original token is valid (which it will be in this contrived example):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# create a token and validate&lt;br /&gt;if (validate_token(create_token))&lt;br /&gt;  puts "Valid token"&lt;br /&gt;else&lt;br /&gt;  puts "Invalid token"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To check if the token was passed within a certain time period, just compare the timestamp on the original token with current time.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# create a token and validate timestamp and token&lt;br /&gt;if (validate_token_and_timestamp(create_token,10))&lt;br /&gt;  puts "Valid token"&lt;br /&gt;else&lt;br /&gt;  puts "Invalid token"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For demonstration only, use sleep to timeout a token:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# create a token, but let token timeout before trying to validate&lt;br /&gt;timeout_token = create_token&lt;br /&gt;sleep 15&lt;br /&gt;if (validate_token_and_timestamp(timeout_token,10))&lt;br /&gt;  puts "Valid token"&lt;br /&gt;else&lt;br /&gt;  puts "Invalid token"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-921230595576921815?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/921230595576921815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=921230595576921815' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/921230595576921815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/921230595576921815'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/07/authentication-token.html' title='authentication token'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4167296262171566049</id><published>2008-07-21T14:04:00.000-07:00</published><updated>2008-07-21T15:01:20.216-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Self Referential Associations with has_many :through</title><content type='html'>&lt;pre&gt;&lt;br /&gt;&lt;b&gt;db/migrate/001_create_teletubbies.rb&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;class CreateTeletubbies &lt; ActiveRecord::Migration&lt;br /&gt;  def self.up&lt;br /&gt;    create_table :teletubbies do |t|&lt;br /&gt;      t.string :name&lt;br /&gt;      t.timestamps&lt;br /&gt;    end&lt;br /&gt;    Teletubby.create(:name =&gt; 'Tinky Winky')&lt;br /&gt;    Teletubby.create(:name =&gt; 'Dipsy')&lt;br /&gt;    Teletubby.create(:name =&gt; 'Laa Laa')&lt;br /&gt;    Teletubby.create(:name =&gt; 'Po')&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.down&lt;br /&gt;    drop_table :teletubbies&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;b&gt;db/migrate/002_create_friendships.rb&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;class CreateFriendships &lt; ActiveRecord::Migration&lt;br /&gt;  def self.up&lt;br /&gt;    create_table :friendships do |t|&lt;br /&gt;      t.integer :teletubby_id&lt;br /&gt;      t.integer :friend_id&lt;br /&gt;      t.timestamps&lt;br /&gt;    end&lt;br /&gt;    # Tinky Winky loves all the other Teletubbies very much&lt;br /&gt;    Friendship.create(:teletubby_id =&gt; 1, :friend_id =&gt; 2)&lt;br /&gt;    Friendship.create(:teletubby_id =&gt; 1, :friend_id =&gt; 3)&lt;br /&gt;    Friendship.create(:teletubby_id =&gt; 1, :friend_id =&gt; 4)&lt;br /&gt;    # Dipsy loves all the other Teletubbies very much&lt;br /&gt;    Friendship.create(:teletubby_id =&gt; 2, :friend_id =&gt; 1)&lt;br /&gt;    Friendship.create(:teletubby_id =&gt; 2, :friend_id =&gt; 3)&lt;br /&gt;    Friendship.create(:teletubby_id =&gt; 2, :friend_id =&gt; 4)&lt;br /&gt;    # Laa Laa loves Po very much&lt;br /&gt;    Friendship.create(:teletubby_id =&gt; 3, :friend_id =&gt; 4)&lt;br /&gt;    # Po loves Laa Laa very much&lt;br /&gt;    Friendship.create(:teletubby_id =&gt; 4, :friend_id =&gt; 3)&lt;br /&gt;    # Big Hug&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.down&lt;br /&gt;    drop_table :friendships&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;b&gt;app/models/teletubby.rb&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;class Teletubby &lt; ActiveRecord::Base&lt;br /&gt;  # a teletubby 'has_many' friendships (teletubbies love each other very much)&lt;br /&gt;  has_many :friendships&lt;br /&gt;&lt;br /&gt;  # a teletubby 'has_many' friends ':through' friendships relationship&lt;br /&gt;  has_many :friends, :through =&gt; :friendships&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;b&gt;app/models/friendship.rb&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;class Friendship &lt; ActiveRecord::Base&lt;br /&gt;  # ActiveRecord already knows what a teletubby is (reflection)&lt;br /&gt;  belongs_to :teletubby&lt;br /&gt;&lt;br /&gt;  # No actual friendship model, so add :class_name and :foreign_key&lt;br /&gt;  belongs_to :friend, :class_name =&gt; "Teletubby", :foreign_key =&gt; "friend_id"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The database should look a little something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mysql&gt; select * from teletubbies;&lt;br /&gt;+----+-------------+---------------------+---------------------+&lt;br /&gt;| id | name        | created_at          | updated_at          |&lt;br /&gt;+----+-------------+---------------------+---------------------+&lt;br /&gt;|  1 | Tinky Winky | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  2 | Dipsy       | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  3 | Laa Laa     | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  4 | Po          | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;+----+-------------+---------------------+---------------------+&lt;br /&gt;4 rows in set (0.00 sec)&lt;br /&gt;&lt;br /&gt;mysql&gt; select * from friendships;&lt;br /&gt;+----+--------------+-----------+---------------------+---------------------+&lt;br /&gt;| id | teletubby_id | friend_id | created_at          | updated_at          |&lt;br /&gt;+----+--------------+-----------+---------------------+---------------------+&lt;br /&gt;|  1 |            1 |         2 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  2 |            1 |         3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  3 |            1 |         4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  4 |            2 |         1 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  5 |            2 |         3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  6 |            2 |         4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  7 |            3 |         4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;|  8 |            4 |         3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 | &lt;br /&gt;+----+--------------+-----------+---------------------+---------------------+&lt;br /&gt;8 rows in set (0.00 sec)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Use script/console to check the relationships:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;dsparling-imbps-computer:~/Sites/teletubbies dsparlingimbp$ script/console &lt;br /&gt;Loading development environment (Rails 2.0.2)&lt;br /&gt;&gt;&gt; t1 = Teletubby.find(1)&lt;br /&gt;=&gt; #&amp;lt;Teletubby id: 1, name: "Tinky Winky", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42"&gt;&lt;br /&gt;&gt;&gt; t1.friends.each { |f| puts "#{t1.name} loves #{f.name} very much." }; false&lt;br /&gt;Tinky Winky loves Dipsy very much.&lt;br /&gt;Tinky Winky loves Laa Laa very much.&lt;br /&gt;Tinky Winky loves Po very much.&lt;br /&gt;=&gt; false&lt;br /&gt;&gt;&gt; t2 = Teletubby.find(2)&lt;br /&gt;=&gt; #&amp;lt;Teletubby id: 2, name: "Dipsy", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42"&gt;&lt;br /&gt;&gt;&gt; t2.friends.each { |f| puts "#{t2.name} loves #{f.name} very much." }; false&lt;br /&gt;Dipsy loves Tinky Winky very much.&lt;br /&gt;Dipsy loves Laa Laa very much.&lt;br /&gt;Dipsy loves Po very much.&lt;br /&gt;=&gt; false&lt;br /&gt;&gt;&gt; t3 = Teletubby.find(3)&lt;br /&gt;=&gt; #&amp;lt;Teletubby id: 3, name: "Laa Laa", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42"&gt;&lt;br /&gt;&gt;&gt; t3.friends.each { |f| puts "#{t3.name} loves #{f.name} very much." }; false&lt;br /&gt;Laa Laa loves Po very much.&lt;br /&gt;=&gt; false&lt;br /&gt;&gt;&gt; t4 = Teletubby.find(4)&lt;br /&gt;=&gt; #&amp;lt;Teletubby id: 4, name: "Po", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42"&gt;&lt;br /&gt;&gt;&gt; t4.friends.each { |f| puts "#{t4.name} loves #{f.name} very much." }; false&lt;br /&gt;Po loves Laa Laa very much.&lt;br /&gt;=&gt; false&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4167296262171566049?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4167296262171566049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4167296262171566049' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4167296262171566049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4167296262171566049'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/07/self-referential-associations-with.html' title='Self Referential Associations with has_many :through'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-6871864813524125817</id><published>2008-07-12T21:02:00.000-07:00</published><updated>2008-09-22T14:58:37.381-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='screencasts'/><title type='text'>Screencast Addiction</title><content type='html'>&lt;strong&gt;Ruby/RoR&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://www.railsenvy.com/speaking" target="_blank"&gt;http://www.railsenvy.com/speaking&lt;/a&gt;&lt;br /&gt;&lt;a href="http://railscasts.com/" target="_blank"&gt;http://railscasts.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.rubyplus.org/" target="_blank"&gt;http://www.rubyplus.org&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.buildingwebapps.com/podcasts" target="_blank"&gt;http://www.buildingwebapps.com/podcasts&lt;/a&gt;&lt;br /&gt;&lt;a href="http://peepcode.com/" target="_blank"&gt;http://peepcode.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.pragprog.com/screencasts" target="_blank"&gt;http://www.pragprog.com/screencasts&lt;/a&gt;&lt;br /&gt;&lt;a href="http://envycasts.com" target="_blank"&gt;http://envycasts.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Rails Conf(s)&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://www.railsenvy.com/tags/conferences" target="_blank"&gt;http://www.railsenvy.com/tags/conferences&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.railsenvy.com/2008/6/2/Railsconf-videos" target="_blank"&gt;http://www.railsenvy.com/2008/6/2/Railsconf-videos&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blip.tv/search?q=rails+conf&amp;x=0&amp;y=0" target="_blank"&gt; http://blip.tv/search?q=rails+conf&amp;x=0&amp;y=0&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.confreaks.com" target="_blank"&gt;http://www.confreaks.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://mwrc2008.confreaks.com" target="_blank"&gt;http://mwrc2008.confreaks.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.rubyinside.com/the-rubyfringe-videos-vids-from-the-summers-hottest-conference-1214.html" target="_blank"&gt;The RubyFringe Videos&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;OSCON&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://www.railsenvy.com/2008/7/29/oscon-videos" target="_blank"&gt; http://www.railsenvy.com/2008/7/29/oscon-videos&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blip.tv/search?q=oscon&amp;x=0&amp;y=0" target="_blank"&gt;http://blip.tv/search?q=oscon&amp;x=0&amp;y=0&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Other&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://www.thoughtworks.com/what-we-say/podcasts.html" target="_blank"&gt;ThoughtWorks IT Matters and ThoughtWorks Talks&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.justin.tv/signals37/archive" target="_blank"&gt;http://www.justin.tv/signals37/archive&lt;/a&gt;&lt;br /&gt;&lt;a href="http://developer.yahoo.com/yui/theater/" target="_blank"&gt;http://developer.yahoo.com/yui/theater/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.theflexshow.com/blog/" target="_blank"&gt;http://www.theflexshow.com/blog/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/search?hl=en&amp;client=firefox-a&amp;rls=org.mozilla:en-US:official&amp;hs=Qxg&amp;sa=X&amp;oi=spell&amp;resnum=0&amp;ct=result&amp;cd=1&amp;q=railsconf+video&amp;spell=1" target="_blank"&gt;Gooogle search railsconf&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/search?hl=en&amp;client=firefox-a&amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;hs=3d1&amp;q=oscon+video&amp;btnG=Search" target="_blank"&gt;Google search oscon&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.infoq.com/" target="_blank"&gt;InfoQ Presentations&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-6871864813524125817?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/6871864813524125817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=6871864813524125817' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6871864813524125817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6871864813524125817'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/07/screencast-addiction.html' title='Screencast Addiction'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-2842867612979829174</id><published>2008-07-12T06:55:00.000-07:00</published><updated>2008-07-12T07:13:26.366-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Gems'/><category scheme='http://www.blogger.com/atom/ns#' term='mp3'/><category scheme='http://www.blogger.com/atom/ns#' term='pdocast'/><title type='text'>ruby-mp3info</title><content type='html'>I have an old SanDisk mp3 player that I use to listen to music and podcasts. Though it's a rather small card (512M), it's still annoying to have to scroll through my single playlist to get to a specific file. &lt;br /&gt;&lt;br /&gt;The SanDisk sorts by the mp3 info title tag, so I wrote a small script that I run on my podcast files before I load them on my player so that they will show up first in the playlist by prepending '01_' to the mp3 title tag (and using the mp3 filename if the title is nil).&lt;br /&gt;&lt;br /&gt;First, install the ruby-mp3info gem  if you don't have it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;gem install ruby-mp3info&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;edit_mp3info_title.rb&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;require 'rubygems'&lt;br /&gt;require "mp3info"&lt;br /&gt;&lt;br /&gt;dir = Dir.open('/Users/dsparlingimbp/PODCAST/mp3')&lt;br /&gt;puts "mp3 directory: #{dir.path}"&lt;br /&gt;&lt;br /&gt;dir.each do |file|&lt;br /&gt;  next unless /\.mp3$/ =~ file&lt;br /&gt;  puts "mp3: #{file}"&lt;br /&gt;&lt;br /&gt;  mp3file = "#{dir.path}/#{file}"&lt;br /&gt;&lt;br /&gt;  Mp3Info.open(mp3file) do |mp3|&lt;br /&gt;    puts "original title: #{mp3.tag.title}"&lt;br /&gt;    title = '01_' + (mp3.tag.title || file)&lt;br /&gt;    mp3.tag.title = title&lt;br /&gt;    puts "new title: #{mp3.tag.title}"&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-2842867612979829174?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/2842867612979829174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=2842867612979829174' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2842867612979829174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2842867612979829174'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/07/ruby-mp3info.html' title='ruby-mp3info'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-610763617922118462</id><published>2008-07-11T14:25:00.000-07:00</published><updated>2008-09-23T16:47:05.969-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='podcast'/><title type='text'>Podcast Addiction</title><content type='html'>It's bad enough that I subscribe to more RSS feeds than I can possibly read in a day, but I've also become addicted to podcasts...many are tech podcasts, but I listen to a wide variety...&lt;br /&gt;&lt;br /&gt;From my current iTunes podcasts directory:&lt;br /&gt;&lt;br /&gt;Andy Jordan's Tech Diary&lt;br /&gt;Audible Ajax&lt;br /&gt;boagworld&lt;br /&gt;The Bugle&lt;br /&gt;The Christian Science Monitor - News&lt;br /&gt;Digital Media Insider&lt;br /&gt;The Flex Show (podcast and screencast)&lt;br /&gt;FOO Casts&lt;br /&gt;The French Pod Class&lt;br /&gt;Hanselminutes&lt;br /&gt;IT Conversations&lt;br /&gt;L33t Tech News&lt;br /&gt;Learning Rails (now a screencast)&lt;br /&gt;.NET Rocks!&lt;br /&gt;php_abstract&lt;br /&gt;php|architecht&lt;br /&gt;podcasts - Channel 9&lt;br /&gt;Pragmatic Programmers&lt;br /&gt;Radio Allegro&lt;br /&gt;Rails Envy Podcast&lt;br /&gt;Railscasts (screencast)&lt;br /&gt;Rubyology&lt;br /&gt;Ruby on Rails Podcast&lt;br /&gt;StackOverflow&lt;br /&gt;TalkCrunch&lt;br /&gt;The Thirsty Developer&lt;br /&gt;This American Life&lt;br /&gt;Wall Street Journal Tech News Briefings&lt;br /&gt;Wall Street Journal on Small Business&lt;br /&gt;Wall Street Journal's Your Money Matters&lt;br /&gt;The Washington Institute Podcast&lt;br /&gt;The Web 2.0 Show&lt;br /&gt;Web Design TV&lt;br /&gt;WebDevRadio.com&lt;br /&gt;&lt;br /&gt;A few others:&lt;br /&gt;&lt;a href="http://www.mobilom.net/fv/index.php" target="_blank"&gt;French Vibes&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And a couple of "top tech podcasts" links:&lt;br /&gt;&lt;a href="http://www.netmag.co.uk/zine/discover-culture/the-top-40-tech-podcasts" target="_blank"&gt;The top 40 tech podcasts - .net magazine&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.impactlab.com/2008/02/25/top-10-best-technology-podcasts/" target="_blank"&gt;Top 10 Best Technology Podcasts&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-610763617922118462?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/610763617922118462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=610763617922118462' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/610763617922118462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/610763617922118462'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/07/podcast-addiction.html' title='Podcast Addiction'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1211098854195114998</id><published>2008-07-10T08:51:00.000-07:00</published><updated>2008-07-10T13:17:08.688-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='subversion'/><title type='text'>Ignore exisiting directory in subverion Rails repo</title><content type='html'>I needed to ignore the log directory of an existing Rails app I had checked out:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;svn up&lt;br /&gt;svn delete log&lt;br /&gt;svn commit -m 'removed log dir'&lt;br /&gt;mkdir log&lt;br /&gt;svn add --non-recursive log&lt;br /&gt;svn propset svn:ignore "*" log/&lt;br /&gt;svn commit -m "Add log dir, ignore contents"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With a little help from:&lt;br /&gt; &lt;a href="http://rails.wincent.com/wiki/Checking_a_new_Rails_application_into_an_existing_Subversion_repository"  target="_blank"&gt;http://rails.wincent.com/wiki/Checking_a_new_Rails_application_into_an_existing_Subversion_repository&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1211098854195114998?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1211098854195114998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1211098854195114998' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1211098854195114998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1211098854195114998'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/07/ignore-exisiting-directory-in-subverion.html' title='Ignore exisiting directory in subverion Rails repo'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-507460592412466718</id><published>2008-06-21T10:04:00.000-07:00</published><updated>2008-06-21T10:16:04.203-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rspec'/><category scheme='http://www.blogger.com/atom/ns#' term='bdd'/><category scheme='http://www.blogger.com/atom/ns#' term='jsspec'/><title type='text'>BDD - Behaviour Driven Development, RSpec, JSSpec</title><content type='html'>&lt;a href="http://en.wikipedia.org/wiki/Behavior_driven_development" target="_blank"&gt;Behavior Driven Development - Wikipedia, the free encyclopedia&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.oreillynet.com/pub/a/ruby/2007/08/09/behavior-driven-development-using-ruby-part-1.html" target="_blank"&gt;O'Reilly Network -- Behavior Driven Development Using Ruby (Part 1)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.oreillynet.com/pub/a/ruby/2007/08/30/behavior-driven-development-using-ruby-part-2.html" target="_blank"&gt;O'Reilly Network -- Behavior Driven Development Using Ruby (Part 2)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.oreillynet.com/pub/a/ruby/2007/09/20/behavior-driven-development-using-ruby-part-3.html" target="_blank"&gt;O'Reilly Network -- Behavior Driven Development Using Ruby (Part 3)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ibm.com/developerworks/web/library/wa-rspec/" target="_blank"&gt;Behavior-driven testing with RSpec&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://peepcode.com/" target="_blank"&gt;PeepCode - RSpec Screencast Tutorials&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/jsspec/" target="_blank"&gt;JSSpec - Javascript BDD(Behavior Driven Development) framework&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jania.pe.kr/aw/moin.cgi/JSSpec" target="_blank"&gt;JSSpec - Official Homepage&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-507460592412466718?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/507460592412466718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=507460592412466718' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/507460592412466718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/507460592412466718'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/06/bdd-behaviour-driven-development-rspec.html' title='BDD - Behaviour Driven Development, RSpec, JSSpec'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3873476082238237520</id><published>2008-06-03T18:58:00.000-07:00</published><updated>2008-06-03T19:04:33.672-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>CocoaMySQL - MySQL GUI for Mac OS X</title><content type='html'>I had to restore a MySQL database dump to a server at new host with no shell access. The host recommended SQLyog, but I'm working on this project on my Mac, and SQLyog is Windows only.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cocoamysql.sourceforge.net/" target="_blank"&gt;CocoaMySQL&lt;/a&gt; was a quick and easy install and did exactly what I needed. &lt;br /&gt;&lt;br /&gt;Of course, on my Mac itself, it was the standard MySQL command:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ mysql -h localhost -u root myshinynewdb &lt; mydatabasedump.sql&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3873476082238237520?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3873476082238237520/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3873476082238237520' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3873476082238237520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3873476082238237520'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/06/cocoamysql-mysql-gui-for-mac-os-x.html' title='CocoaMySQL - MySQL GUI for Mac OS X'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-2546208752999758843</id><published>2008-06-01T16:49:00.000-07:00</published><updated>2008-06-01T16:51:08.113-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript css'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>CSS, Firefox - font-family, form intput and textarea</title><content type='html'>I'll do my own write up at some point, but ran across this, which solved a problem I was having with FF:&lt;br /&gt;&lt;br /&gt;http://cakebaker.42dh.com/2006/02/02/some-css-trouble-with-input-and-textarea-in-firefox/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-2546208752999758843?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/2546208752999758843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=2546208752999758843' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2546208752999758843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2546208752999758843'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/06/css-firefox-font-family-form-intput-and.html' title='CSS, Firefox - font-family, form intput and textarea'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1935742652644713495</id><published>2008-05-22T08:52:00.000-07:00</published><updated>2008-05-22T09:00:29.083-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='caching'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='cache_fu'/><title type='text'>cache_fu: Conditional action-caching stops after a period of time</title><content type='html'>&lt;a href="http://groups.google.com/group/acts_as_cached/browse_thread/thread/eff6287664362f66" target="_blank"&gt;http://groups.google.com/group/acts_as_cached/browse_thread/thread/eff6287664362f66&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;fragment_cache.rb&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;module ActsAsCached&lt;br /&gt;  module FragmentCache&lt;br /&gt;    def self.setup!&lt;br /&gt;      class &amp;lt;&amp;lt; CACHE&lt;br /&gt;        include Extensions&lt;br /&gt;      end&lt;br /&gt;      &lt;br /&gt;      setup_fragment_cache_cache&lt;br /&gt;      setup_rails_for_memcache_fragments&lt;br /&gt;      setup_rails_for_action_cache_options&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    # add :ttl option to cache helper and set cache store memcache object&lt;br /&gt;    def self.setup_rails_for_memcache_fragments&lt;br /&gt;      if ::ActionView.const_defined?(:Template)&lt;br /&gt;        # Rails 2.1+&lt;br /&gt;        ::ActionController::Base.cache_store = CACHE&lt;br /&gt;      else&lt;br /&gt;        # Rails &amp;lt; svn r8619&lt;br /&gt;        ::ActionView::Helpers::CacheHelper.class_eval do&lt;br /&gt;          def cache(name = {}, options = nil, &amp;block)&lt;br /&gt;            @controller.cache_erb_fragment(block, name, options)&lt;br /&gt;          end&lt;br /&gt;        end&lt;br /&gt;        ::ActionController::Base.fragment_cache_store = CACHE&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def self.setup_fragment_cache_cache&lt;br /&gt;      Object.const_set(:FragmentCacheCache, Class.new { acts_as_cached :store =&gt; CACHE })&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    # add :ttl option to caches_action on the per action level by passing in a hash instead of an array&lt;br /&gt;    # &lt;br /&gt;    # Examples:&lt;br /&gt;    #  caches_action :index                                       # will use the default ttl from your memcache.yml, or 25 minutes&lt;br /&gt;    #  caches_action :index =&gt; { :ttl =&gt; 5.minutes }              # cache index action with 5 minute ttl&lt;br /&gt;    #  caches_action :page, :feed, :index =&gt; { :ttl =&gt; 2.hours }  # cache index action with 2 hours ttl, all others use default&lt;br /&gt;    #&lt;br /&gt;    def self.setup_rails_for_action_cache_options&lt;br /&gt;      ::ActionController::Caching::Actions::ActionCacheFilter.class_eval do&lt;br /&gt;        # convert all actions into a hash keyed by action named, with a value of a ttl hash (to match other cache APIs)&lt;br /&gt;        def initialize(*actions, &amp;block)&lt;br /&gt;          if [].respond_to?(:extract_options!)&lt;br /&gt;            #edge&lt;br /&gt;            @options = actions.extract_options!&lt;br /&gt;            @actions = actions.inject(@options.except(:cache_path)) do |hsh, action|&lt;br /&gt;              action.is_a?(Hash) ? hsh.merge(action) : hsh.merge(action =&gt; { :ttl =&gt; nil })&lt;br /&gt;            end&lt;br /&gt;            @options.slice!(:cache_path)&lt;br /&gt;          else&lt;br /&gt;            #1.2.5&lt;br /&gt;            @actions = actions.inject({}) do |hsh, action|&lt;br /&gt;              action.is_a?(Hash) ? hsh.merge(action) : hsh.merge(action =&gt; { :ttl =&gt; nil })&lt;br /&gt;            end&lt;br /&gt;          end&lt;br /&gt;        end&lt;br /&gt;&lt;br /&gt;        # override to skip caching/rendering on evaluated if option&lt;br /&gt;        def before(controller)&lt;br /&gt;          return unless @actions.include?(controller.action_name.intern)&lt;br /&gt;&lt;br /&gt;          # maintaining edge and 1.2.x compatibility with this branch&lt;br /&gt;          # Jan Prill - added &amp;&amp; false&lt;br /&gt;          #if @options &amp;&amp; false&lt;br /&gt;          # DSS - removed false - false causing else to always run - this may be &lt;br /&gt;          # because Jan was using Rails 1.2...&lt;br /&gt;          if @options&lt;br /&gt;            action_cache_path = ActionController::Caching::Actions::ActionCachePath.new(controller, path_options_for(controller, @options))&lt;br /&gt;          else&lt;br /&gt;            action_cache_path = ActionController::Caching::Actions::ActionCachePath.new(controller)&lt;br /&gt;          end&lt;br /&gt;          &lt;br /&gt;          # should probably be like ActiveRecord::Validations.evaluate_condition.  color me lazy.&lt;br /&gt;          if conditional = @actions[controller.action_name.intern][:if]&lt;br /&gt;            conditional = conditional.respond_to?(:call) ? conditional.call(controller) : controller.send(conditional)&lt;br /&gt;          end&lt;br /&gt;          # Jan Prill - causing caching to stop after a period of time?&lt;br /&gt;          #@actions.delete(controller.action_name.intern) if conditional == false&lt;br /&gt;&lt;br /&gt;          # Jan Prill - added if clause&lt;br /&gt;          cache = controller.read_fragment(action_cache_path.path) if conditional != false&lt;br /&gt;          if cache &amp;&amp; (conditional || conditional.nil?)&lt;br /&gt;            controller.rendered_action_cache = true&lt;br /&gt;            if method(:set_content_type!).arity == 2&lt;br /&gt;              set_content_type!(controller, action_cache_path.extension)&lt;br /&gt;            else&lt;br /&gt;              set_content_type!(action_cache_path)&lt;br /&gt;            end&lt;br /&gt;            controller.send(:render, :text =&gt; cache)&lt;br /&gt;            false&lt;br /&gt;          else&lt;br /&gt;            # 1.2.x compatibility&lt;br /&gt;            # Jan Prill added &amp;&amp;&lt;br /&gt;            controller.action_cache_path = action_cache_path if (controller.respond_to?(:action_cache_path) &amp;&amp; conditional != false)&lt;br /&gt;          end&lt;br /&gt;        end&lt;br /&gt;        &lt;br /&gt;        # override to pass along the ttl hash&lt;br /&gt;        def after(controller)&lt;br /&gt;          # Jan Prill - added || controller.action_cache_path.nil? &lt;br /&gt;          return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache || controller.action_cache_path.nil? &lt;br /&gt;          # 1.2.x compatibility&lt;br /&gt;          path = controller.respond_to?(:action_cache_path) ? controller.action_cache_path.path : ActionController::Caching::Actions::ActionCachePath.path_for(controller)&lt;br /&gt;          controller.write_fragment(path, controller.response.body, action_ttl(controller))&lt;br /&gt;        end&lt;br /&gt;&lt;br /&gt;        private&lt;br /&gt;        def action_ttl(controller)&lt;br /&gt;          @actions[controller.action_name.intern]&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    module Extensions&lt;br /&gt;      def read(*args)&lt;br /&gt;        return if ActsAsCached.config[:skip_gets]&lt;br /&gt;        FragmentCacheCache.cache_store(:get, args.first)&lt;br /&gt;      end&lt;br /&gt;      &lt;br /&gt;      def write(name, content, options = {}) &lt;br /&gt;        ttl = (options.is_a?(Hash) ? options[:ttl] : nil) || ActsAsCached.config[:ttl] || 25.minutes&lt;br /&gt;        FragmentCacheCache.cache_store(:set, name, content, ttl)&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    module DisabledExtensions&lt;br /&gt;      def read(*args) nil end&lt;br /&gt;      def write(*args) "" end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1935742652644713495?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1935742652644713495/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1935742652644713495' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1935742652644713495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1935742652644713495'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/05/cachefu-conditional-action-caching.html' title='cache_fu: Conditional action-caching stops after a period of time'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4050855711559549843</id><published>2008-05-20T19:59:00.000-07:00</published><updated>2008-05-20T20:09:36.720-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>git</title><content type='html'>I've been wanting to play with &lt;a href="http://git.or.cz/" target="_blank"&gt;git&lt;/a&gt;, so I created repositories for all my jquery plugins at &lt;a href="http://github.com/" target="_blank"&gt;github.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://github.com/dsparling" target="_blank"&gt;http://github.com/dsparling&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For now, that would be:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://github.com/dsparling/jclock" target="_blank"&gt;jClock&lt;/a&gt;&lt;br /&gt;&lt;a href="http://github.com/dsparling/datemaker" target="_blank"&gt;datemaker&lt;/a&gt;&lt;br /&gt;&lt;a href="http://github.com/dsparling/regexpcommon" target="_blank"&gt;regexpCommon&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;git documentation:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://git.or.cz/#documentation" target="_blank"&gt;http://git.or.cz/#documentation&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.sourcemage.org/Git_Guide" target="_blank"&gt;http://www.sourcemage.org/Git_Guide&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.gitcasts.com/" target="_blank"&gt;http://www.gitcasts.com/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4050855711559549843?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4050855711559549843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4050855711559549843' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4050855711559549843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4050855711559549843'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/05/git.html' title='git'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-52114152503255655</id><published>2008-05-06T18:30:00.000-07:00</published><updated>2008-05-06T18:40:59.568-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Excel'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET .NET'/><title type='text'>ASP.NET - Import and display Excel spreadsheet</title><content type='html'>I needed to upload and parse an Excel spreadsheet and display it in a GridView. For the most part, pretty straight forward. I ran into an issue "Could not find installable ISAM" once I added "IMEX=1" to my connection string. This was solved by adding (char)34 as shown in my working example: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;string filePath = "~/somedirectory/somespreadsheet.xls";&lt;br /&gt;&lt;br /&gt;string strConn = @"Provider=Microsoft.Jet.OLEDB.4.0;"&lt;br /&gt;+ "Data Source=" +  MapPath(filePath) + ";" &lt;br /&gt;+ "Extended Properties=" + (char)34&lt;br /&gt;+ "Excel 8.0;IMEX=1;" + (char)34;&lt;br /&gt;&lt;br /&gt;DataSet dsRecords = new DataSet();&lt;br /&gt;// "Sheet" is name of sheet being opened, must add $ after the name&lt;br /&gt;OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", strConn);&lt;br /&gt;      &lt;br /&gt;//da.TableMappings.Add("Table", "ExcelText");&lt;br /&gt;da.Fill(dsRecords);&lt;br /&gt;scheduleGridView.DataSource = dsRecords.Tables[0].DefaultView;&lt;br /&gt;scheduleGridView.DataBind();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As a note, you can also access the spreadsheet directly using the file path:     &lt;br /&gt;&lt;pre&gt;    &lt;br /&gt;string strConn = @"Provider=Microsoft.Jet.OLEDB.4.0;" &lt;br /&gt;+ "Data Source=c:/somedirectory/somespreadsheet.xls;" &lt;br /&gt;+ "Extended Properties=Excel 8.0;";&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-52114152503255655?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/52114152503255655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=52114152503255655' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/52114152503255655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/52114152503255655'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/05/aspnet-import-and-display-excel.html' title='ASP.NET - Import and display Excel spreadsheet'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-465955945159654617</id><published>2008-04-26T07:07:00.000-07:00</published><updated>2008-04-26T07:47:02.558-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='will_paginate'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><title type='text'>will_paginate gem</title><content type='html'>While upgrading an old project to Rails 2.0.2 (and having trouble getting the will_paginate plugin to install), I &lt;a href="http://groups.google.com/group/will_paginate/browse_thread/thread/4cacdeab9aa7d83a#" target="_blank"&gt;discovered&lt;/a&gt; that there is a will_paginate gem:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mislav.caboo.se/rails/will_paginate-love/" target="_blank"&gt;http://mislav.caboo.se/rails/will_paginate-love/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://railscasts.com/episodes/51" target="_blank"&gt;Railscasts - will_paginate&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-465955945159654617?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/465955945159654617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=465955945159654617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/465955945159654617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/465955945159654617'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/04/willpaginate-gem.html' title='will_paginate gem'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-5633861263968238517</id><published>2008-04-24T20:35:00.000-07:00</published><updated>2008-04-24T20:44:52.815-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Rails - ActionController::InvalidAuthenticityToken</title><content type='html'>&lt;pre&gt;&lt;br /&gt;ActionController::InvalidAuthenticityToken in User#login&lt;br /&gt;&lt;br /&gt;Showing user/login.html.erb where line #2 raised:&lt;br /&gt;&lt;br /&gt;No :secret given to the #protect_from_forgery call.  &lt;br /&gt;Set that or use a session store capable of generating its &lt;br /&gt;own keys (Cookie Session Store).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This happened after I switched from using the file system to a database for storing sessions (after uncommenting the line "&lt;code&gt;config.action_controller.session_store = :active_record_store&lt;/code&gt;" in &lt;code&gt;config/environment.rb&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Once you switch to database store, you'll need to comment the "&lt;code&gt;protect_from_forgery&lt;/code&gt;" line in &lt;code&gt;app/controllers/application.rb&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# See ActionController::RequestForgeryProtection for details&lt;br /&gt;# Uncomment the :secret if you're not using the cookie session store&lt;br /&gt;#protect_from_forgery # :secret =&gt; 'b3e36f40312f075ea2697fb85180e312'&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-5633861263968238517?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/5633861263968238517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=5633861263968238517' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5633861263968238517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5633861263968238517'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/04/actioncontrollerinvalidauthenticitytoke.html' title='Rails - ActionController::InvalidAuthenticityToken'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-5429869520059971155</id><published>2008-04-24T20:09:00.000-07:00</published><updated>2008-04-24T20:42:27.866-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Rails 2.0.2 - setup with functional tests</title><content type='html'>If you want to use &lt;code&gt;setup&lt;/code&gt; with functional tests in Rails 2.0.2, you'll need to rename the &lt;code&gt;setup&lt;/code&gt; method to &lt;code&gt;setup_with_fixtures&lt;/code&gt; and call &lt;code&gt;super&lt;/code&gt; before running your setup code:&lt;br /&gt;&lt;pre&gt;  &lt;br /&gt;def setup_with_fixtures&lt;br /&gt;  super&lt;br /&gt;  # Set up code here&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-5429869520059971155?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/5429869520059971155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=5429869520059971155' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5429869520059971155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5429869520059971155'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/04/rails-202-setup-with-functional-tests.html' title='Rails 2.0.2 - setup with functional tests'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3922577254271039759</id><published>2008-03-29T05:58:00.000-07:00</published><updated>2008-03-29T06:01:11.009-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>mod_rails</title><content type='html'>&lt;a href="http://www.modrails.com/" target="_blank"&gt;Phusion Passenger (a.k.a. mod_rails for Apache) Preview&lt;/a&gt;&lt;br /&gt;&lt;a href="http://weblog.rubyonrails.com/2008/3/26/mod_rails-is-on-the-way" target="_blank"&gt;Riding Rails: mod_rails is on the way&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3922577254271039759?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3922577254271039759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3922577254271039759' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3922577254271039759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3922577254271039759'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/03/modrails.html' title='mod_rails'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-2900286795293468869</id><published>2008-03-23T19:18:00.000-07:00</published><updated>2008-03-23T20:19:38.781-07:00</updated><title type='text'>Ruby on Rails - Using External Asset Hosts</title><content type='html'>Rails uses the "public" directory on the current host as the default location for static assets (images, CSS, Javascript, etc). Setting up your Rails app to use an external assets server is as simple as adding a single line to a configuration file.&lt;br /&gt;&lt;br /&gt;Add the following line to your config/environment.rb file:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ActionController::Base.asset_host = 'http://assets.yourdomain.com'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's also possible to set a single environment to use an external asset host:&lt;br /&gt;&lt;br /&gt;Add the following line to config/environments/production.rb (the most likely spot - this line should already be in this file, but commented out):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;config.action_controller.asset_host = 'http://assets.yourdomain.com'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now this line in my layout&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;%= stylesheet_link_tag 'scaffold/base' %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;will translate to http://assets.yourdomain.com/stylesheets/scaffold/base.css&lt;br /&gt;&lt;br /&gt;Additional information on setting up multiple asset hosts can be found at:&lt;br /&gt;&lt;br /&gt; &lt;a href="http://api.rubyonrails.com/classes/ActionView/Helpers/AssetTagHelper.html" target="_blank"&gt;http://api.rubyonrails.com/classes/ActionView/Helpers/AssetTagHelper.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-2900286795293468869?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/2900286795293468869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=2900286795293468869' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2900286795293468869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2900286795293468869'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/03/ruby-on-rails-using-external-asset.html' title='Ruby on Rails - Using External Asset Hosts'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-7807561421756363108</id><published>2008-03-12T09:23:00.000-07:00</published><updated>2008-03-12T09:24:17.196-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Gems'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><title type='text'>Ruby Gem - Highline</title><content type='html'>I was looking for a way to prompt a user for input on the console and ran across the RubyGem HighLine. It does a lot more than this, but here's how to capture STDIN from the console:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/local/bin/ruby&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'highline/import'&lt;br /&gt;&lt;br /&gt;username = ask("Enter your username:  ") { |q| q.echo = true }&lt;br /&gt;password = ask("Enter your password:  ") { |q| q.echo = "*" }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here's the output on the console:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ ruby highline.rb &lt;br /&gt;Enter your username:  doug&lt;br /&gt;Enter your password:  ******&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Get it here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://highline.rubyforge.org/" target="_blank"&gt;HighLine&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;or simply install the gem the normal way:&lt;br /&gt;&lt;br /&gt;$ sudo gem install highline&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-7807561421756363108?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/7807561421756363108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=7807561421756363108' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/7807561421756363108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/7807561421756363108'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/03/ruby-gem-highline.html' title='Ruby Gem - Highline'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8300537141462650093</id><published>2008-03-12T09:22:00.001-07:00</published><updated>2008-03-12T09:22:25.160-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Autotesting Javascript in Rails</title><content type='html'>From &lt;a href="http://drnicwilliams.com" target="_blank"&gt;Dr. Nic's Blog&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/" target="_blank"&gt;Autotesting Javascript in Rails&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8300537141462650093?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8300537141462650093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8300537141462650093' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8300537141462650093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8300537141462650093'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/03/autotesting-javascript-in-rails.html' title='Autotesting Javascript in Rails'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3323565836569833064</id><published>2008-03-12T09:19:00.001-07:00</published><updated>2008-03-12T09:19:59.673-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='openssl'/><title type='text'>Installing Ruby without openssl</title><content type='html'>When installing Ruby on an old machine, I got this error:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ruby make[1]: *** [ossl_ssl.o] Error 1&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Other than installing openssl, which wasn't option, install ruby without openssl:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$ ./configure prefix=/home/doug/bin/ruby --without-openssl&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3323565836569833064?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3323565836569833064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3323565836569833064' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3323565836569833064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3323565836569833064'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/03/installing-ruby-without-openssl.html' title='Installing Ruby without openssl'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-6731029009703443843</id><published>2008-03-10T22:15:00.001-07:00</published><updated>2008-03-10T22:20:52.063-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='DOM'/><title type='text'>Javascript - insertAfter(), formatCurrency, DOM Scripting</title><content type='html'>insertAfter() &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function insertAfter(newElement,targetElement) {&lt;br /&gt;    var parent = targetElement.parentNode;&lt;br /&gt;    if (parent.lastChild == targetElement) {&lt;br /&gt;        parent.appendChild(newElement);&lt;br /&gt;    } else {&lt;br /&gt;        parent.insertBefore(newElement,targetElement.nextSibling);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;formatCurrency()&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function formatCurrency(amount) {&lt;br /&gt;    var i = parseFloat(amount);&lt;br /&gt;    if(isNaN(i)) { i = 0.00; }&lt;br /&gt;    var minus = '';&lt;br /&gt;    if(i &lt; 0) { minus = '-'; }&lt;br /&gt;    i = Math.abs(i);&lt;br /&gt;    i = parseInt((i + .005) * 100);&lt;br /&gt;    i = i / 100;&lt;br /&gt;    s = new String(i);&lt;br /&gt;    if(s.indexOf('.') &lt; 0) { s += '.00'; }&lt;br /&gt;    if(s.indexOf('.') == (s.length - 2)) { s += '0'; }&lt;br /&gt;    s = minus + s;&lt;br /&gt;    return s;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;DOM scripting - create text node with value of &amp;amp;nbsp;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var textEl = document.createTextNode('\u00a0');&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-6731029009703443843?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/6731029009703443843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=6731029009703443843' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6731029009703443843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6731029009703443843'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/03/javascript-misc-functions.html' title='Javascript - insertAfter(), formatCurrency, DOM Scripting'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-282908543867718880</id><published>2008-03-10T12:16:00.000-07:00</published><updated>2008-03-10T12:48:08.767-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='scriptaculous'/><category scheme='http://www.blogger.com/atom/ns#' term='accordion'/><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Accordion Effects with Scriptaculous</title><content type='html'>I had a couple recent projects that required an accordion effect. I normally use jQuery, but found a couple nice Prototype/Scriptaculous accordions (one is for a Rails project, so we're already using Scriptaculous).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.stickmanlabs.com/accordion/" target="_blank"&gt;stickman labs&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.grf-design.com/archives/2006/04/accordion_effec.html" target="_blank"&gt;grf-design&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note - The stickman labs accordion doesn't appear to work with the latest Prototype (1.6.1). I'm using the combined js file from the stickman site.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-282908543867718880?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/282908543867718880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=282908543867718880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/282908543867718880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/282908543867718880'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/03/accordion-effects-with-scriptaculous.html' title='Accordion Effects with Scriptaculous'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-5510943659549906201</id><published>2008-02-27T17:19:00.000-08:00</published><updated>2008-02-27T17:50:52.860-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Sortable'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>jQuery Sortable with Ajax, PHP, and MySQL</title><content type='html'>I needed to create a sortable list that would save the order position of data items. I've been using jQuery more and more and decided to go with the &lt;a href="http://interface.eyecon.ro/" target="_blank"&gt;Interface Elements&lt;/a&gt; for jQuery.&lt;br /&gt;&lt;br /&gt;I found a blog entry titled &lt;a href="http://snipplr.com/view/4301/jquery-sortable-ajax-php-integration/" target="_blank"&gt;jQuery Sortable Ajax PHP Integration&lt;/a&gt; that was a good start. However, it didn't actually use MySQL to store the sorted data so I've gone ahead and added the database queries and updates.&lt;br /&gt;&lt;br /&gt;First I created a simple table to store links (I'd like my client to order the links they enter through an admin interface).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TABLE links ( &lt;br /&gt;id int(10) NOT NULL auto_increment, &lt;br /&gt;link_url varchar(50) NOT NULL, &lt;br /&gt;link_text varchar(50) NOT NULL, &lt;br /&gt;order_position int(2), &lt;br /&gt;primary key(id) &lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next is the PHP page that reads the link data from the table and displays the links based on the order_position column of the table.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;index.php&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" &lt;br /&gt;                    "http://www.w3.org/TR/html4/loose.dtd"&gt;&lt;br /&gt;&amp;lt;html&gt;&lt;br /&gt;&amp;lt;head&gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="/js/jquery/jquery-1.2.3.min.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="interface.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;  &lt;br /&gt;&amp;lt;script&gt;&lt;br /&gt;$(document).ready(&lt;br /&gt;  function() {&lt;br /&gt;    $("#sortme").Sortable({&lt;br /&gt;      accept : 'sortitem',&lt;br /&gt;      onchange : function (sorted) {&lt;br /&gt;        serial = $.SortSerialize('sortme');&lt;br /&gt;&lt;br /&gt;        $.ajax({&lt;br /&gt;                  url: "sortdata.php",&lt;br /&gt;                  type: "POST",&lt;br /&gt;                  data: serial.hash,&lt;br /&gt;                  // complete: function(){},&lt;br /&gt;                  //success: function(feedback){ $('#data').html(feedback); }&lt;br /&gt;                  // error: function(){}&lt;br /&gt;        });&lt;br /&gt;      }&lt;br /&gt;    });&lt;br /&gt;  }&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;  &amp;lt;/script&gt;&lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&amp;lt;body&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;ul id="sortme"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;  // Connect to the database as necessary&lt;br /&gt;  $dbh = mysql_connect('127.0.0.1','username','password')&lt;br /&gt;    or die ("Unaable to connnect to MySQL");&lt;br /&gt;&lt;br /&gt;  $selected = mysql_select_db("sort_test",$dbh)&lt;br /&gt;    or die("Could not select sort_test");&lt;br /&gt;&lt;br /&gt;  $result = mysql_query('SELECT * FROM links ORDER BY order_position');&lt;br /&gt;  while ($row = mysql_fetch_array($result)) {&lt;br /&gt;    print '&amp;lt;li id="' . $row{'id'} . '" class="sortitem"&gt;' . $row{'link_text'} . "&lt;/li&gt;\n";&lt;br /&gt;  }&lt;br /&gt;  mysql_close($dbh);&lt;br /&gt;?&gt;&lt;br /&gt;&amp;lt;/ul&gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;/body&gt;&lt;br /&gt;&amp;lt;/html&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will make an Ajax call back to the server where PHP will update the database as you drag and sort the list data:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;sortdata.php&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;$sortme = $_POST['sortme'];&lt;br /&gt;// Connect to the database as necessary&lt;br /&gt;$dbh = mysql_connect('127.0.0.1','username','password')&lt;br /&gt;  or die ("Unaable to connnect to MySQL");&lt;br /&gt;&lt;br /&gt;$selected = mysql_select_db("sort_test",$dbh)&lt;br /&gt;  or die("Could not select sort_test");&lt;br /&gt;&lt;br /&gt;for ($i = 0; $i &lt; count($sortme); $i++) {&lt;br /&gt;  mysql_query("UPDATE links SET order_position=$i WHERE id=$sortme[$i]");&lt;br /&gt;}&lt;br /&gt;mysql_close($dbh);&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A little CSS certainly wouldn't hurt things. Here's some I found on another tutorial:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;style&gt;&lt;br /&gt;ul {&lt;br /&gt;  list-style: none;&lt;br /&gt;}&lt;br /&gt;li {&lt;br /&gt;  background: #727EA3;&lt;br /&gt;  color: #FFF;&lt;br /&gt;  width: 100px;&lt;br /&gt;  margin: 5px;&lt;br /&gt;  font-size: 10px;&lt;br /&gt;  font-family: Arial;&lt;br /&gt;  padding: 3px;&lt;br /&gt;}&lt;br /&gt;&amp;lt;/style&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I wouldn't call this production ready code, but all the pieces are in place if you'd like to use jQuery with Ajax, PHP, and MySQL for a sortable list. Don't forget, you'll need to get jQuery itself and the interface.js file as well. Another thing to consider is alerting the user if the update fails or takes a long time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-5510943659549906201?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/5510943659549906201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=5510943659549906201' title='30 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5510943659549906201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5510943659549906201'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/02/jquery-sortable-with-ajax-php-and-mysql.html' title='jQuery Sortable with Ajax, PHP, and MySQL'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>30</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3822778021309396532</id><published>2008-02-21T12:42:00.000-08:00</published><updated>2008-03-09T18:53:59.454-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Ruby on Rails - Testing with Multiple Databases</title><content type='html'>I ran into errors when running tests for a Rails app using multiple databases. When testing, fixtures are automatically inserted into the primary database, and I was getting an error on an unused default fixture that was created when I built the model tied to the second database. Removing that fixture got my tests to pass...&lt;br /&gt;&lt;br /&gt;More info here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.elctech.com/2007/3/8/using-and-testing-rails-with-multiple-databases" target="_blank"&gt;http://www.elctech.com/2007/3/8/using-and-testing-rails-with-multiple-databases&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.elctech.com/2007/5/30/using-and-testing-multiple-databases-in-rails-part-2" target="_blank"&gt;http://www.elctech.com/2007/5/30/using-and-testing-multiple-databases-in-rails-part-2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;and on multiple databases in general:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wiki.rubyonrails.org/rails/pages/HowtoUseMultipleDatabases" target="_blank"&gt;http://wiki.rubyonrails.org/rails/pages/HowtoUseMultipleDatabases&lt;/a&gt;&lt;br /&gt;&lt;a href="http://wiki.rubyonrails.org/rails/pages/HowtoUseMultipleDatabasesWithFixtures" target="_blank"&gt;http://wiki.rubyonrails.org/rails/pages/HowtoUseMultipleDatabasesWithFixtures&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3822778021309396532?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3822778021309396532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3822778021309396532' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3822778021309396532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3822778021309396532'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/02/ruby-on-rails-testting-with-multiple.html' title='Ruby on Rails - Testing with Multiple Databases'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1421657122981173386</id><published>2008-02-19T17:41:00.000-08:00</published><updated>2008-02-19T17:57:55.075-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>jQuery</title><content type='html'>I've been using the jQuery Javascript library a lot lately and it's definitely become my favorite library. (I've written four plugins in the last couple months to boot) &lt;br /&gt;&lt;br /&gt;Here are a few links to useful jQuery resources.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jquery.com/" target="_blank"&gt;jQuery: The Write Less, Do More, JavaScript Library&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ui.jquery.com/" target="_blank"&gt;jQuery UI: Widgets, Components, and Interaction&lt;/a&gt;&lt;br /&gt;&lt;a href="http://docs.jquery.com/Plugins" target="_blank"&gt;Plugins - jQuery JavaScript Library&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jquery.com/blog/" target="_blank"&gt;jQuery Blog&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.learningjquery.com/" target="_blank"&gt;Learning jQuery&lt;/a&gt;&lt;br /&gt;&lt;a href="http://visualjquery.com/" target="_blank"&gt;Visual jQuery&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ibm.com/developerworks/library/x-ajaxjquery.html" target="_blank"&gt;IBM developerWorks: Simplify Ajax development with jQuery&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1421657122981173386?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1421657122981173386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1421657122981173386' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1421657122981173386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1421657122981173386'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/02/jquery.html' title='jQuery'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3066842615083128298</id><published>2008-02-19T17:35:00.000-08:00</published><updated>2008-02-19T17:40:51.572-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='Gems'/><title type='text'>composite_primary_keys.gem</title><content type='html'>Ruby on Rails does not support composite primary keys and a legacy database I'm working with has lots of them...after a quick search I found this useful Gem:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://compositekeys.rubyforge.org/" targget="_blank"&gt;composite_primary_keys&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3066842615083128298?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3066842615083128298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3066842615083128298' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3066842615083128298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3066842615083128298'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/02/compositeprimarykeysgem.html' title='composite_primary_keys.gem'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-5374609301058113203</id><published>2008-01-31T18:21:00.000-08:00</published><updated>2008-01-31T18:24:35.231-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Easy Restful Rails Screencast</title><content type='html'>&lt;a href="http://www.akitaonrails.com/2008/1/25/easy-restful-rails-screencast" target="_blank"&gt;http://www.akitaonrails.com/2008/1/25/easy-restful-rails-screencast&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-5374609301058113203?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/5374609301058113203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=5374609301058113203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5374609301058113203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5374609301058113203'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/01/easy-restful-rails-screencast.html' title='Easy Restful Rails Screencast'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4105797010087060478</id><published>2008-01-23T14:31:00.000-08:00</published><updated>2008-01-23T14:35:02.423-08:00</updated><title type='text'>10 Ruby on Rails Plugins You Should Be Using</title><content type='html'>&lt;a href="http://hosting.media72.co.uk/blog/2007/12/09/10-ruby-on-rails-plugins-you-should-be-using/" target="_blank"&gt;Media72: 10 Ruby on Rails Plugins You Should Be Using&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4105797010087060478?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4105797010087060478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4105797010087060478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4105797010087060478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4105797010087060478'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/01/10-ruby-on-rails-plugins-you-should-be.html' title='10 Ruby on Rails Plugins You Should Be Using'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-9013052532932735004</id><published>2008-01-23T08:09:00.000-08:00</published><updated>2008-01-23T17:34:15.282-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>jQuery: Cookie Plugin</title><content type='html'>I've become a big fan of jQuery and have contributed two small plugins &lt;a href="http://plugins.jquery.com/user/1780" target="_blank"&gt;myself&lt;/a&gt;, so when it came time to switch to a library for cookie manipulation with Javascript (time to replace all that nasty inline JS code) my first choice was jQuery. &lt;br /&gt;&lt;br /&gt;Not to be disappointed, I found that &lt;a href="http://stilbuero.de/" target="_blank"&gt;Klaus Hartl&lt;/a&gt; has written a very slim and useful &lt;a href="http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/" target="_blank"&gt;Cookie Plugin&lt;/a&gt; for jQuery.&lt;br /&gt;&lt;br /&gt;Here's a small page test using the jQuery Cookie plugin:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;html&gt;&lt;br /&gt;&amp;lt;head&gt;&lt;br /&gt;  &amp;lt;title&gt;jquery cookie&amp;lt;/title&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;script type="text/javascript" src="jquery-1.2.1.min.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;  &amp;lt;script type="text/javascript" src="jquery.cookie.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;script type="text/javascript"&gt;&lt;br /&gt;&lt;br /&gt;    $(function($) {&lt;br /&gt;&lt;br /&gt;      function displayMessage(msg) {&lt;br /&gt;        $('#message').html(msg).css({color: 'green'});&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      displayMessage('jQuery cookie plugin test');&lt;br /&gt;&lt;br /&gt;      $('#setSessionCookie').click(function() { &lt;br /&gt;        $.cookie('test', 'Hmmm, cookie');&lt;br /&gt;        displayMessage("Cookie 'test' has been set.");&lt;br /&gt;      });&lt;br /&gt;&lt;br /&gt;      $('#setCookie').click(function() {&lt;br /&gt;        $.cookie('test', 'Hmmm, cookie', { expires: 7 });&lt;br /&gt;        displayMessage("Cookie 'test' has been set and will expire in 7 days.");&lt;br /&gt;      });&lt;br /&gt;&lt;br /&gt;      $('#getCookie').click(function() {&lt;br /&gt;        displayMessage("The value of the cookie named 'test' is: " + $.cookie('test'));&lt;br /&gt;      });&lt;br /&gt;&lt;br /&gt;      $('#deleteCookie').click(function() {&lt;br /&gt;        $.cookie('test', null);&lt;br /&gt;        displayMessage("Cookie 'test' has been deleted.");&lt;br /&gt;      });&lt;br /&gt;&lt;br /&gt;      $('#testCookiesEnabled').click(function() {&lt;br /&gt;        $.cookie('testcookiesenabled', null);&lt;br /&gt;        $.cookie('testcookiesenabled', 'enabled');&lt;br /&gt;        if ($.cookie('testcookiesenabled')) {&lt;br /&gt;          displayMessage("Cookie: "+ $.cookie('testcookiesenabled'));&lt;br /&gt;        } else {&lt;br /&gt;          displayMessage("Cookies disabled");&lt;br /&gt;          $.cookie('testcookiesenabled', null);&lt;br /&gt;        }&lt;br /&gt;      });&lt;br /&gt;&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;  &amp;lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;body&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&gt;&amp;lt;span id="message" style="forecolor: red;"&gt;&amp;lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&gt;&amp;lt;input type="button" id="testCookiesEnabled" value="Cookies enabled?"/&gt;&amp;lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&gt;&amp;lt;input type="button" id="setSessionCookie" value="Set session cookie"/&gt;&amp;lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&gt;&amp;lt;input type="button" id="setCookie" value="Set cookie expires in  7 days"/&gt;&amp;lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&gt;&amp;lt;input type="button" id="getCookie" value="Show cookie value"/&gt;&amp;lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&gt;&amp;lt;input type="button" id="deleteCookie" value="Delete the cookie"/&gt;&amp;lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&gt;&lt;br /&gt;&amp;lt;/html&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;My jQuery cookie &lt;a href="http://doug.sparling.googlepages.com/jquery-cookie.html" target="_blank"&gt;demo&lt;/a&gt; using jquery.cookie.js&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-9013052532932735004?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/9013052532932735004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=9013052532932735004' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/9013052532932735004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/9013052532932735004'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/01/jquery-cookie-plugin.html' title='jQuery: Cookie Plugin'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-5765573479620009344</id><published>2008-01-21T16:17:00.000-08:00</published><updated>2008-01-21T16:26:00.438-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET .NET'/><category scheme='http://www.blogger.com/atom/ns#' term='GridView'/><title type='text'>ASP.NET GridView - Header always bold</title><content type='html'>GridView uses a table and creates a &amp;lt;th&gt; tag for the header, which will bold all the text generated by the GridView. Here's a simple solution:&lt;br /&gt;&lt;br /&gt;Set a style:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;style&gt;&lt;br /&gt;.GridViewHeaderStyle th {&lt;br /&gt;  font-weight: normal;  &lt;br /&gt;}&lt;br /&gt;&amp;lt;/style&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And apply it to your GridView:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:GridView ID="grdSomeGrid" runat="server" CssClass="GridViewHeaderStyle"&gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;/asp:GridView&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-5765573479620009344?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/5765573479620009344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=5765573479620009344' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5765573479620009344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5765573479620009344'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/01/aspnet-gridview-header-always-bold.html' title='ASP.NET GridView - Header always bold'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8708391569849860585</id><published>2008-01-19T11:06:00.000-08:00</published><updated>2008-01-19T11:15:26.071-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET .NET'/><title type='text'>ASP.NET GridView "ShowFooter"</title><content type='html'>Sometimes it's the small things that get you...&lt;br /&gt;&lt;br /&gt;Uh, not that it ever happened to me, but in case you can't get your GridView template footer to show up...don't forget 'ShowFoooter="true"' :)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:GridView ID="grdListings" runat="server" AutoGenerateColumns="false" BorderWidth="0" &lt;br /&gt;AllowPaging="true" PageSize="5" OnPageIndexChanging="grdListings_PageIndexChanging" ShowFooter="true"&gt;&lt;br /&gt;                   &lt;br /&gt;&amp;lt;Columns&gt;&lt;br /&gt;&amp;lt;asp:TemplateField&gt;&lt;br /&gt;                                    &lt;br /&gt;&amp;lt;HeaderTemplate&gt;&lt;br /&gt;Header         &lt;br /&gt;&amp;lt;/HeaderTemplate&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;ItemTemplate&gt;&lt;br /&gt;Item&lt;br /&gt;&amp;lt;/ItemTemplate&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;FooterTemplate&gt;&lt;br /&gt;Footer&lt;br /&gt;&amp;lt;/FooterTemplate&gt;&lt;br /&gt;                                    &lt;br /&gt;&amp;lt;/asp:TemplateField&gt;&lt;br /&gt;&amp;lt;/Columns&gt;&lt;br /&gt;&amp;lt;/asp:GridView&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8708391569849860585?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8708391569849860585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8708391569849860585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8708391569849860585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8708391569849860585'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/01/aspnet-gridview-showfooter.html' title='ASP.NET GridView &quot;ShowFooter&quot;'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4096238011311547748</id><published>2008-01-05T07:29:00.000-08:00</published><updated>2008-01-05T07:33:04.729-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Install Ruby without openssl</title><content type='html'>When installing Ruby on an old machine, I got this error:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ruby make[1]: *** [ossl_ssl.o] Error 1&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Other than installing openssl, which wasn't option, install ruby without openssl:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$ ./configure prefix=/home/doug/bin/ruby --without-openssl&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4096238011311547748?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4096238011311547748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4096238011311547748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4096238011311547748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4096238011311547748'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/01/install-ruby-without-openssl.html' title='Install Ruby without openssl'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1133707921851862742</id><published>2008-01-05T07:26:00.000-08:00</published><updated>2008-01-05T07:29:32.988-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Autotesting Javascript in Rails</title><content type='html'>From &lt;a href="http://drnicwilliams.com" target="_blank"&gt;Dr. Nic's Blog&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://drnicwilliams.com/2008/01/04/autotesting-javascript-in-rails/" target="_blank"&gt;Autotesting Javascript in Rails&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1133707921851862742?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1133707921851862742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1133707921851862742' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1133707921851862742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1133707921851862742'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/01/autotesting-javascript-in-rails.html' title='Autotesting Javascript in Rails'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-2746935316973866932</id><published>2008-01-03T12:20:00.000-08:00</published><updated>2008-01-03T12:21:32.893-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><title type='text'>Upgrading to specific version of Rails</title><content type='html'>&lt;pre&gt;&lt;br /&gt;sudo gem install -v=2.0.1 rails --include-dependencies&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-2746935316973866932?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/2746935316973866932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=2746935316973866932' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2746935316973866932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2746935316973866932'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2008/01/upgrading-to-specific-version-of-rails.html' title='Upgrading to specific version of Rails'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4667333271266158479</id><published>2007-12-30T17:19:00.000-08:00</published><updated>2007-12-30T17:26:42.763-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET .NET'/><title type='text'>How to pass variables thru a DataGrid hyperlink column</title><content type='html'>&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:HyperLink NavigateUrl='&amp;lt;%# "SomePage.aspx?someparam=" + DataBinder.Eval(Container, "DataItem.PropertyID") %&gt;' runat="server" /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4667333271266158479?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4667333271266158479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4667333271266158479' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4667333271266158479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4667333271266158479'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/12/how-to-pass-variables-thru-datagrid.html' title='How to pass variables thru a DataGrid hyperlink column'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-2629854169767655433</id><published>2007-12-19T19:19:00.000-08:00</published><updated>2007-12-19T19:24:18.446-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Ruby Blog</title><content type='html'>I've decided to create a Ruby only blog, though I'll keep cross posting here for now...who knows, I may change my mind and just keep the one blog here...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://spariamsgems.blogspot.com" target="_blank"&gt;spariamsgems&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-2629854169767655433?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/2629854169767655433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=2629854169767655433' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2629854169767655433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2629854169767655433'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/12/ruby-blog.html' title='Ruby Blog'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-7551922162089643170</id><published>2007-12-19T19:09:00.000-08:00</published><updated>2007-12-19T19:18:12.946-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>Viewing .CHM files on Mac OS X - Chmox</title><content type='html'>I tried several Mac options and had no luck (xchm froze, libchmxx has a utility called chmdissect - it worked, but no images)...finally, I struck gold with Chmox.&lt;br /&gt;&lt;br /&gt;1) Install CHMLIB - &lt;a href="http://www.jedrea.com/chmlib/" target="_blank"&gt;http://www.jedrea.com/chmlib/&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;% ./configure&lt;br /&gt;% make&lt;br /&gt;% sudo make install&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;2) Install Chmox - &lt;a href="http://chmox.sourceforge.net/" target="_blank"&gt;http://chmox.sourceforge.net/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The binary is a standard dmg file...click on the dmg file and move the application over to your application directory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-7551922162089643170?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/7551922162089643170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=7551922162089643170' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/7551922162089643170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/7551922162089643170'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/12/viewing-chm-files-on-mac-os-x-chmox.html' title='Viewing .CHM files on Mac OS X - Chmox'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8802498911597365136</id><published>2007-12-10T14:21:00.001-08:00</published><updated>2007-12-10T14:33:46.874-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Sending E-mail with Ruby Net::SMTP</title><content type='html'>All you need to know is here:&lt;br /&gt;&lt;a href="http://www.ruby-doc.org/stdlib/libdoc/net/smtp/rdoc/classes/Net/SMTP.html" target="_blank"&gt;http://www.ruby-doc.org/stdlib/libdoc/net/smtp/rdoc/classes/Net/SMTP.html&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def send_email(from, from_alias, to, to_alias, subject, message)&lt;br /&gt;&lt;br /&gt;  msg = &amp;lt;&amp;lt;EOF&lt;br /&gt;From: #{from_alias} &amp;lt;#{from}&gt;&lt;br /&gt;To: #{to_alias} &amp;lt;#{to}&gt;&lt;br /&gt;Subject: #{subject}&lt;br /&gt; &lt;br /&gt;#{message}&lt;br /&gt;EOF&lt;br /&gt;&lt;br /&gt;  Net::SMTP.start('localhost') do |smtp|&lt;br /&gt;    smtp.send_message(msg, from, to)&lt;br /&gt;  end&lt;br /&gt; &lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Or if your mail server is on another machine:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  Net::SMTP.start(mail_server, port, helo_domain) do |smtp|&lt;br /&gt;    smtp.send_message msg, from, to&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;smtp.send_message('your.smtp.server', 25, 'mail.from.domain')&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8802498911597365136?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8802498911597365136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8802498911597365136' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8802498911597365136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8802498911597365136'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/12/sending-e-mail-with-ruby-netsmtp.html' title='Sending E-mail with Ruby Net::SMTP'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8236962725238445049</id><published>2007-11-21T11:02:00.000-08:00</published><updated>2007-11-21T11:10:36.911-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>ASP.NET Calendar Control - Misc</title><content type='html'>&lt;a href="http://msdn2.microsoft.com/en-us/library/ms228044(VS.80).aspx" target="_blank"&gt;How to: Display Selected Dates from a Database in the Calendar Control&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hide days that aren't in current month:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)&lt;br /&gt;{&lt;br /&gt;    if (e.Day.Date.Month != Calendar1.VisibleDate.Month)&lt;br /&gt;    e.Cell.Text = "";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Disable link for particular day (the 23rd, in this case):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;protected void cal_DayRender(object source, DayRenderEventArgs e)&lt;br /&gt;{&lt;br /&gt;    if (e.Day.Date.Day == 23)&lt;br /&gt;    {&lt;br /&gt;        e.Cell.Controls.Clear();&lt;br /&gt;        e.Cell.Text = e.Day.DayNumberText; &lt;br /&gt;        e.Cell.BackColor = System.Drawing.Color.Gainsboro;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8236962725238445049?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8236962725238445049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8236962725238445049' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8236962725238445049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8236962725238445049'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/11/aspnet-calendar-control-misc.html' title='ASP.NET Calendar Control - Misc'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3925138683120020778</id><published>2007-11-20T11:12:00.000-08:00</published><updated>2007-11-20T11:16:07.237-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>ASP.NET HyperLink Control: mailto link</title><content type='html'>&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:HyperLink ID="EmailLink" text='&lt;%# Eval("UserEmail") %&gt;' NavigateUrl='&lt;%# Eval("UserEmail","mailto:{0}")%&gt;' runat="server" target="_blank" /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With a "Subject"&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:HyperLink ID="EmailLink" text='&lt;%# Eval("UserEmail") %&gt;' NavigateUrl='&lt;%# Eval("UserEmail","mailto:{0}?Subject=YourQuestion")%&gt;' runat="server" target="_blank" /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3925138683120020778?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3925138683120020778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3925138683120020778' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3925138683120020778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3925138683120020778'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/11/aspnet-hyperlink-control-mailto-link.html' title='ASP.NET HyperLink Control: mailto link'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3725763202782022402</id><published>2007-11-17T09:18:00.000-08:00</published><updated>2007-11-17T11:00:38.271-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>Identify Button Clicked in GridView</title><content type='html'>I had a GridView with a ButtonField used to Select a record to display a User's details in a DetailsView. I wanted a second button to display different form for changing a Users's password, since I wanted that to be a separate option.&lt;br /&gt;&lt;br /&gt;GridView (usersGrid):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:ButtonField CommandName="Select" Text="Select" /&gt;&lt;br /&gt;&amp;lt;asp:TemplateField&gt;&lt;br /&gt;    &amp;lt;ItemTemplate&gt;&lt;br /&gt;        &amp;lt;asp:LinkButton runat="server" ID="changePasswordButton" Text="Change Password" OnClick="usersGrid_SelectRow" /&gt;&lt;br /&gt;    &amp;lt;/ItemTemplate&gt;&lt;br /&gt;&amp;lt;/asp:TemplateFild&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Code Behind:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;protected void usersGrid_SelectRow(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt;    GridViewRow row = (GridViewRow)((LinkButton)sender).Parent.Parent;&lt;br /&gt;    usersGrid.SelectedIndex = row.RowIndex;&lt;br /&gt;&lt;br /&gt;    MyDatabase.DBUtil = new MyDatabase.DBUtil();&lt;br /&gt;    changePasswordDetails.DataSource = DB.GetUser(Int16.Parse(usersGrid.SelectedValue.ToString());&lt;br /&gt;    changePasswordDetails.ChangeMode(DetailsViewMode.ReadOnly);&lt;br /&gt;    userDeatils.Visible = false;&lt;br /&gt;    changePasswordDetails.Visible = true;&lt;br /&gt;    changePasswordDetails.DataKeyNames = new string[] { "UserID" };&lt;br /&gt;    changePasswordDetails.DataBind();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3725763202782022402?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3725763202782022402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3725763202782022402' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3725763202782022402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3725763202782022402'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/11/identify-button-clicked-in-gridview.html' title='Identify Button Clicked in GridView'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8811020358259348862</id><published>2007-11-09T23:11:00.000-08:00</published><updated>2007-11-09T23:25:01.474-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>.NET Smart Delete (Details View Client-side delete confirmation)</title><content type='html'>I was working on a database-driven web site and I needed a way to make sure that the admin couldn't delete all the admin user accounts (that was simple enough), but I also wanted a javascript confirmation popup when an admin did delete accounts. &lt;br /&gt;&lt;br /&gt;I found exactly what I was looking for on &lt;a href="http://weblogs.asp.net/despos/" target="_blank"&gt;Dino Esposito's WebLog&lt;/a&gt; on his post &lt;a href="http://weblogs.asp.net/despos/archive/2005/07/06/418127.aspx" target="_blank"&gt;ASP.NET Today: Smart Delete&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;DetailsView and FormView controls support delete operations and delegate the execution to the underlying data source control. If the data source control is configured to execute the delete operation, all works fine, otherwise an exception is thrown.&lt;br /&gt;&lt;br /&gt;The DetailsView generates command buttons automatically and doesn't expose them directly to page code. How can you add a bit of Javascript code to ask for confirmation? Here's the code.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;protected void DetailsView1_ItemCreated(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt;   // Test FooterRow to make sure all rows have been created &lt;br /&gt;   if (DetailsView1.FooterRow != null)&lt;br /&gt;   {&lt;br /&gt;     // The command bar is the last element in the Rows collection&lt;br /&gt;     int commandRowIndex = DetailsView1.Rows.Count-1;&lt;br /&gt;     DetailsViewRow commandRow = DetailsView1.Rows[commandRowIndex];&lt;br /&gt;     &lt;br /&gt;     // Look for the DELETE button&lt;br /&gt;     DataControlFieldCell cell = (DataControlFieldCell) commandRow.Controls[0];&lt;br /&gt;     foreach(Control ctl in cell.Controls)&lt;br /&gt;     {&lt;br /&gt;       LinkButton link = ctl as LinkButton;&lt;br /&gt;       if (link != null)&lt;br /&gt;       {&lt;br /&gt;          if (link.CommandName == "Delete")&lt;br /&gt;          {&lt;br /&gt;             link.ToolTip = "Click here to delete";&lt;br /&gt;             link.OnClientClick = "return confirm('Do you really want to delete this record?');";&lt;br /&gt;          }&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The ItemCreated event doesn't provide any information about the row being created. However, it can be figured out that the footer row is always created and is always the last row to be created. If the FooterRow object is not null, you can conclude that all rows have been created, including the command bar. The command bar is the first row after the data rows and is stored in the Rows collection--it's the last element in the collection. The command bar is a table row (type is DetailsViewRow) and contains a cell (type is DataControlFieldCell). The cell contains as many link buttons (type is DataControlLinkButton) as there are commands. Delete, Edit, New, Update, Cancel are the command names used and useful to identify the right button.&lt;br /&gt;&lt;br /&gt;The FormView is fully templated and lets you manually define appearance and behavior of command buttons. If you place a custom button, or want to use a custom command name for a standard button (Edit, New, Delete), here's how to detect the click on the button. You start by adding a handler for ItemCommand. The code below shows how to deal with a custom Delete button that checks if the bound data source control is enabled for deletion before proceeding.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e)&lt;br /&gt;{&lt;br /&gt;  if (e.CommandName == "SmartDelete")&lt;br /&gt;  {&lt;br /&gt;    IDataSource obj = (IDataSource) FindControl(FormView1.DataSourceID);&lt;br /&gt;    DataSourceView view = obj.GetView("DefaultView");&lt;br /&gt;    if (!view.CanDelete) {&lt;br /&gt;       Response.Write("Sorry, you can't delete");&lt;br /&gt;       return;&lt;br /&gt;    }&lt;br /&gt;    else &lt;br /&gt;       FormView1.DeleteItem();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8811020358259348862?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8811020358259348862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8811020358259348862' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8811020358259348862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8811020358259348862'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/11/net-smart-delete-details-view-client.html' title='.NET Smart Delete (Details View Client-side delete confirmation)'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3454207435297741604</id><published>2007-11-06T17:49:00.000-08:00</published><updated>2007-11-06T18:11:55.527-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>Formatting Date Field in Grid View</title><content type='html'>Due to a bug fix in .NET 2.0, HtmlEncode must be set to False for date formatting to give expected results:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:BoundField DataField="AgendaDate" HeaderText="Agenda Date" SortExpression="AgendaDate" DataFormatString="{0:yyyy-MM-dd}" HtmlEncode=False /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In a Details View using TemplateFields:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;ItemTemplate&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;asp:Label ID="agendaDateLabel" runat="server" Text='&lt;%# Eval("AgendaDate", "{0:yyyy-MM-dd}") %&gt;'&gt;&amp;lt;/asp:Label&gt;&lt;br /&gt;&amp;lt;/ItemTemplate&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3454207435297741604?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3454207435297741604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3454207435297741604' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3454207435297741604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3454207435297741604'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/11/formatting-date-field-in-grid-view.html' title='Formatting Date Field in Grid View'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3807081464429753554</id><published>2007-11-03T07:39:00.000-07:00</published><updated>2007-11-06T17:54:16.441-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>SQL Server 2005 Check Constraint</title><content type='html'>I wanted to use something like the MySQL Enum constraint in SQL Server to limit the values allowed in a column...&lt;br /&gt;&lt;br /&gt;I ended up using a separate table and a foreign key for this, but never the less, here's how to use the Check constraint, in my case, to limit RecordStatus to contain only 'Active' or 'Inactive':&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TABLE NewsItems (&lt;br /&gt;  NewsItemID int IDENTITY NOT NULL PRIMARY KEY,&lt;br /&gt;  RecordStatus nvarchar(10) NOT NULL DEFAULT 'ACTIVE' CHECK (RecordStatus IN ('Active', 'Inactive'))&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3807081464429753554?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3807081464429753554/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3807081464429753554' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3807081464429753554'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3807081464429753554'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/11/sql-server-2005-check-constraint.html' title='SQL Server 2005 Check Constraint'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-382879160361143821</id><published>2007-10-19T22:28:00.000-07:00</published><updated>2007-10-19T22:31:07.388-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>ASP .NET - C# Decimal Comparison</title><content type='html'>A little more shopping cart hacking. Here's how do to Decimal comparisons in C#:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        public static decimal GetShippingCost()&lt;br /&gt;        {&lt;br /&gt;            decimal sum;&lt;br /&gt;            decimal shippingCost;&lt;br /&gt;            sum = GetSubtotal() - GetCouponDiscount();&lt;br /&gt;            if (sum &amp;lt; 0)&lt;br /&gt;                sum = 0;&lt;br /&gt;&lt;br /&gt;            if ( Decimal.Compare(sum, 26.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 8.95m;&lt;br /&gt;            else if ( Decimal.Compare(sum, 35.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 11.95m;&lt;br /&gt;            else if ( Decimal.Compare(sum, 45.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 12.95m;&lt;br /&gt;            else if ( Decimal .Compare(sum, 55.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 16.95m;&lt;br /&gt;            else if ( Decimal.Compare(sum, 74.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 18.95m;&lt;br /&gt;            else if ( Decimal.Compare(sum, 99.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 20.95m;&lt;br /&gt;            else if ( Decimal.Compare(sum, 119.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 22.95m;&lt;br /&gt;            else if (Decimal.Compare(sum, 139.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 24.95m;&lt;br /&gt;            else if (Decimal.Compare (sum, 159.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 26.95m;&lt;br /&gt;            else if (Decimal.Compare(sum, 199.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 29.95m;&lt;br /&gt;            else if ( Decimal.Compare(sum, 249.95m ) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 32.95m;&lt;br /&gt;            else if (Decimal.Compare(sum, 299.95m) &amp;lt;= 0 )&lt;br /&gt;                shippingCost = 34.95m;&lt;br /&gt;            else&lt;br /&gt;                shippingCost = 34.95m;&lt;br /&gt;&lt;br /&gt;            return shippingCost;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-382879160361143821?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/382879160361143821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=382879160361143821' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/382879160361143821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/382879160361143821'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/10/asp-net-c-decimal-comparison.html' title='ASP .NET - C# Decimal Comparison'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4498075174576629197</id><published>2007-10-19T22:17:00.000-07:00</published><updated>2007-10-19T22:24:15.045-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>ASP .NET - Redirecting to HTTPS</title><content type='html'>On a project where I had to install a third party shopping cart, one issue that came up was to make sure all the pages ran under https (many hard coded links used "http"). &lt;br /&gt;&lt;br /&gt;I put the following code in the Global.asax file:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;protected void Application_BeginRequest(Object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt;    if (Request.Url.Port != 443)&lt;br /&gt;    {&lt;br /&gt;        Response.Redirect ("https://www.yourdomain.com" +  Request.Url.AbsolutePath, true);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This uses&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Request.IsSecureConnection&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;to determine if the call was made over SSL.&lt;br /&gt;&lt;br /&gt;So &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if (Request.IsSecureConnection)&lt;br /&gt;{&lt;br /&gt;    Response.Write("HTTPS");&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;    Response.Write("HTTP");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Another way to write this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if (!Request.IsSecureConnection)&lt;br /&gt;{ &lt;br /&gt;    string serverName =HttpUtility.UrlEncode(Request.ServerVariables["SERVER_NAME"]);        &lt;br /&gt;    string filePath = Request.FilePath;&lt;br /&gt;    Response.Redirect("https://" + serverName + filePath);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4498075174576629197?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4498075174576629197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4498075174576629197' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4498075174576629197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4498075174576629197'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/10/asp-net-redirecting-to-https.html' title='ASP .NET - Redirecting to HTTPS'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1781876021478704038</id><published>2007-10-18T13:11:00.000-07:00</published><updated>2007-10-18T13:28:18.166-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP'/><title type='text'>Classic ASP: Sending e-mail (CDONTS -&gt; CDOSYS)</title><content type='html'>One of today's jobs was fixing a mail script running on classic ASP that died after being moved to a new server. Attempting to send an email resulted in this error:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Microsoft VBScript runtime  error '800a01ad'&lt;br /&gt;&lt;br /&gt;ActiveX component can't create object: 'CDONTS.Newmail'&lt;br /&gt;&lt;br /&gt;/aspmailer.asp, line 45&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;CDONTS has been deprecated and replaced with CDOSYS. &lt;br /&gt;&lt;br /&gt;I updated aspmailer.asp (a somewhat redundantly named script) to use CDOSYS. After the update, I got this error:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;The "SendUsing" configuration value is invalid.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So I still need a bit more code.&lt;br /&gt;&lt;br /&gt;This site provided the needed fix:&lt;br /&gt;&lt;br /&gt;http://classicasp.aspfaq.com/email/how-do-i-send-e-mail-with-cdo.html&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!-- &lt;br /&gt;    METADATA &lt;br /&gt;    TYPE="typelib"  &lt;br /&gt;    UUID="CD000000-8B95-11D1-82DB-00C04FB1625D"  &lt;br /&gt;    NAME="CDO for Windows 2000 Library" &lt;br /&gt;--&amp;gt; &lt;br /&gt;&amp;lt;%  &lt;br /&gt;    Set cdoConfig = CreateObject("CDO.Configuration")  &lt;br /&gt; &lt;br /&gt;    With cdoConfig.Fields  &lt;br /&gt;        .Item(cdoSendUsingMethod) = cdoSendUsingPort  &lt;br /&gt;        .Item(cdoSMTPServer) = "&amp;lt;enter_mail.server_here&amp;gt;"  &lt;br /&gt;        .Update  &lt;br /&gt;    End With &lt;br /&gt; &lt;br /&gt;    Set cdoMessage = CreateObject("CDO.Message")  &lt;br /&gt; &lt;br /&gt;    With cdoMessage &lt;br /&gt;        Set .Configuration = cdoConfig &lt;br /&gt;        .From = "from@me.com" &lt;br /&gt;        .To = "to@me.com" &lt;br /&gt;        .Subject = "Sample CDO Message" &lt;br /&gt;        .TextBody = "This is a test for CDO.message" &lt;br /&gt;        .Send &lt;br /&gt;    End With &lt;br /&gt; &lt;br /&gt;    Set cdoMessage = Nothing  &lt;br /&gt;    Set cdoConfig = Nothing  &lt;br /&gt;%&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Replace &amp;lt;enter_mail.server_here&amp;gt; with the name or IP of your SMTP mail server ("localhost" may do the trick).&lt;br /&gt;&lt;br /&gt;The other example provided is as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;% &lt;br /&gt;    sch = "http://schemas.microsoft.com/cdo/configuration/" &lt;br /&gt; &lt;br /&gt;    Set cdoConfig = CreateObject("CDO.Configuration") &lt;br /&gt; &lt;br /&gt;    With cdoConfig.Fields &lt;br /&gt;        .Item(sch &amp; "sendusing") = 2 ' cdoSendUsingPort &lt;br /&gt;        .Item(sch &amp; "smtpserver") = "&amp;lt;enter_mail.server_here&amp;gt;" &lt;br /&gt;        .update &lt;br /&gt;    End With &lt;br /&gt; &lt;br /&gt;    Set cdoMessage = CreateObject("CDO.Message") &lt;br /&gt; &lt;br /&gt;    With cdoMessage &lt;br /&gt;        Set .Configuration = cdoConfig &lt;br /&gt;        .From = "from@me.com" &lt;br /&gt;        .To = "to@me.com" &lt;br /&gt;        .Subject = "Sample CDO Message" &lt;br /&gt;        .TextBody = "This is a test for CDO.message" &lt;br /&gt;        .Send &lt;br /&gt;    End With &lt;br /&gt; &lt;br /&gt;    Set cdoMessage = Nothing &lt;br /&gt;    Set cdoConfig = Nothing &lt;br /&gt;%&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1781876021478704038?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1781876021478704038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1781876021478704038' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1781876021478704038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1781876021478704038'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/10/classic-asp-sending-e-mail-cdonts.html' title='Classic ASP: Sending e-mail (CDONTS -&gt; CDOSYS)'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8716351966897220112</id><published>2007-09-26T07:02:00.000-07:00</published><updated>2007-09-26T07:08:10.402-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>JavaScript Style</title><content type='html'>As I've been doing a lot of Javascript and Ajax these days, I've found these resources valuable:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.pathf.com/agileajax/2007/09/javascript-styl.html" target="_blank"&gt;JavaScript style and the art of anal retention&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dojotoolkit.org/developer/StyleGuide" target="_blank"&gt;Dojo style guide&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ajaxian.com/archives/javascript-style-guide" target="_blank"&gt;Ajaxian commentary on Dojo style guide&lt;/a&gt;&lt;br /&gt;&lt;a href="http://javascript.crockford.com/style1.html" target="_blank"&gt;Crockford style guide, part 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://javascript.crockford.com/style2.html" target="_blank"&gt;Crockford style guide, part 2&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ajaxian.com/archives/douglas-crockfords-elements-of-javascript-style" target="_blank"&gt;Ajaxian commentary on Crockford style guide&lt;/a&gt;&lt;br /&gt;&lt;a href="http://developer.mozilla.org/en/docs/JavaScript_style_guide" target="_blank"&gt;Mozilla style guide&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8716351966897220112?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8716351966897220112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8716351966897220112' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8716351966897220112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8716351966897220112'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/09/javascript-style.html' title='JavaScript Style'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3774856408302661791</id><published>2007-09-19T14:37:00.000-07:00</published><updated>2007-09-19T18:12:51.280-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Ruby on Rails - Legacy MySQL Database</title><content type='html'>I'm rewriting a company admin tool written in mod_perl (Catalyst) and replacing it with a new one using Ruby on Rails. At the moment, I have to keep the legacy database/schema. Most of the old tables don't use auto-incrementing keys, which means I won't get the Rails Active::Record magic and I need to work around the keys.&lt;br /&gt;&lt;br /&gt;Here's an example table:&lt;br /&gt;&lt;br /&gt;mysql&gt; describe clients;&lt;br /&gt;+--------------+-------------+------+-----+---------+-------+&lt;br /&gt;| Field        | Type        | Null | Key | Default | Extra |&lt;br /&gt;+--------------+-------------+------+-----+---------+-------+&lt;br /&gt;| client_abbrv | varchar(5)  | NO   | PRI |         |       | &lt;br /&gt;| client_name  | varchar(50) | YES  |     | NULL    |       | &lt;br /&gt;+--------------+-------------+------+-----+---------+-------+&lt;br /&gt;&lt;br /&gt;To get this to work with Rails, I had to make a few small changes.&lt;br /&gt;&lt;br /&gt;I made one small change in the view, which was setting the name of the primary key field. I changed "client_abbrv" to "id" in the form:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;app/views/client/new.rhtml&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;%= error_messages_for 'client' %&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;fieldset&gt;&lt;br /&gt;    &amp;lt;legend&gt;Add a Client&lt;/legend&gt;&lt;br /&gt;    &amp;lt;% form_tag :action =&gt; "create" do %&gt;&lt;br /&gt;      &amp;lt;p&gt;&lt;br /&gt;        &amp;lt;label for="client_client_name"&gt;Client Name:&lt;/label&gt;&lt;br /&gt;        &amp;lt;%= text_field 'client', 'client_name'  %&gt;&lt;br /&gt;      &amp;lt;/p&gt;&lt;br /&gt;      &amp;lt;p&gt;&lt;br /&gt;        &amp;lt;label for="client_id"&gt;Client Abbrv:&lt;/label&gt;&lt;br /&gt;        &amp;lt;%= text_field 'client', 'id' %&gt;&lt;br /&gt;      &amp;lt;/p&gt;&lt;br /&gt;      &amp;lt;p&gt;&lt;br /&gt;      &amp;lt;%= submit_tag 'Add' %&gt;&lt;br /&gt;      &amp;lt;/p&gt;&lt;br /&gt;    &amp;lt;% end %&gt;&lt;br /&gt;  &amp;lt;/fieldset&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For the model, I had set the primary key with &lt;code&gt;set_primary_key&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;app/models/clients.rb&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Client &lt; ActiveRecord::Base&lt;br /&gt;set_primary_key "client_abbrv"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Luckily, the table was already pluralized. If it had been "client," then I would have had to add this line:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def self.table_name() "client" end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For the controller, I had to change the create method:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;app/controllers/client_controller.rb&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def create&lt;br /&gt;  @client = Client.new&lt;br /&gt;  @client.id = params[:client][:id]&lt;br /&gt;  @client.client_name = params[:client][:client_name]&lt;br /&gt;  if @client.save&lt;br /&gt;    flash[:notice] = "Client was successfully created."&lt;br /&gt;    redirect_to :action =&gt; 'list'&lt;br /&gt;  else&lt;br /&gt;    render :action =&gt; 'new'&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That replaced the old create method where I had the normal:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@client = Client.new(params[:client])&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When using &lt;code&gt;set_primary_key&lt;/code&gt;, you insert data using "id" and typically select data using the actual field name, "client_abbrv" in this case.&lt;br /&gt;&lt;br /&gt;Here's what the controller is doing for the create method:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;dsparling-imbps-computer:~/my/rubydev/uclick-admin dsparlingimbp$ script/console &lt;br /&gt;Loading development environment.&lt;br /&gt;&gt;&gt; client = Client.new&lt;br /&gt;=&gt; #&amp;lt;Client:0x32b5e14 @new_record=true, @attributes={"client_name"=&gt;nil}&gt;&lt;br /&gt;&gt;&gt; client.id = "abc"&lt;br /&gt;=&gt; "abc"&lt;br /&gt;&gt;&gt; client.client_name = "ABC Company"&lt;br /&gt;=&gt; "ABC Company"&lt;br /&gt;&gt;&gt; client.valid?&lt;br /&gt;=&gt; true&lt;br /&gt;&gt;&gt; client.save&lt;br /&gt;=&gt; true&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3774856408302661791?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/3774856408302661791/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=3774856408302661791' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3774856408302661791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3774856408302661791'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/09/ruby-on-rails-legacy-mysql-database.html' title='Ruby on Rails - Legacy MySQL Database'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-880999429769888818</id><published>2007-09-08T09:18:00.001-07:00</published><updated>2008-03-29T05:25:23.495-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Javascript Resources</title><content type='html'>&lt;a href="http://developer.yahoo.com/yui/theater/" target="_blank"&gt;Yahoo! UI Library: YUI Theater&lt;/a&gt;&lt;br /&gt;Douglas Crockford — "The JavaScript Programming Language"&lt;br /&gt;Douglas Crockford — "An Inconvenient API: The Theory of the DOM"&lt;br /&gt;Douglas Crockford — "Advanced JavaScript"&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Douglas Crockford&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://javascript.crockford.com/" target="_blank"&gt;Douglas Crockford's Javascript&lt;/a&gt;&lt;br /&gt;&lt;a href="http://javascript.crockford.com/code.html" target="_blank"&gt;Code Conventions for the JavaScript Programming Language&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;John Resig&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://ejohn.org/" target="_blank"&gt;John Resig&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ejohn.org/blog/javascript-talk-at-northeastern/" target="_blank"&gt;John Resig - JavaScript Talk at Northeastern (video)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Misc&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://www.quirksmode.org/js/contents.html" target="_blank"&gt;QuirksMode - JavaScript&lt;/a&gt;&lt;br /&gt;&lt;a href="http://devedge-temp.mozilla.org/central/javascript/index_en.html" target="_blank"&gt;netscape devedge: JavaScript Central&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.webdeveloper.com/javascript/"&gt;webdeveloper.com: JavaScript&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.webreference.com/programming/javascript/" target="_blank"&gt;Web Reference JavaScript&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.w3schools.com/js/" target="_blank"&gt;W3Schools JavaScript &lt;br /&gt;Tutorial&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.dhtmlgoodies.com/index.html" target="_blank"&gt;DHTML Goodies&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.mattkruse.com/javascript/" target="_blank"&gt;JavaScript Toolbox&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.javascripttoolbox.com/" target="_blank"&gt;JavaScript Toolbox&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.javascripttoolbox.com/bestpractices/" target="_blank"&gt;JavaScript Toolbox - Best Practices&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.jibbering.com/faq/" target="_blank"&gt;comp.lang.javascript FAQ&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Tools&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://www.jslint.com/" target="_blank"&gt;JSLint, The JavaScript Verifier&lt;/a&gt;&lt;br /&gt;&lt;a href="http://javascript.crockford.com/jsmin.html" target="_blank"&gt;JSMIN, The JavaScript Minifier&lt;/a&gt;&lt;br /&gt;&lt;a href="http://dean.edwards.name/packer/" target="_blank"&gt;dean.edwards.name/packer/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.jsunit.net/" target="_blank"&gt;JsUnit&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;W3C&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://www.w3.org/DOM/" target="_blank"&gt;W3C Document Object Model&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Books&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/JavaScript-Definitive-Guide-David-Flanagan/dp/0596101996/" target="_blank"&gt;JavaScript: The Definitive Guide by David Flanagan&lt;/a&gt;&lt;br /&gt;&lt;a href="http://amazon.com/exec/obidos/ASIN/1590597273/ref=nosim/jspro-20" target="_blank"&gt;Pro Javascript Techniques by John Resig&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742/" target="_blank"&gt;JavaScript: The Good Part by Douglas Crockford&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Learning-jQuery-Interaction-Development-JavaScript/dp/1847192505/" garget="_blank"&gt;Learning jQuery by Karl Swedberg and Jonathan Chaffer&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-880999429769888818?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/880999429769888818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=880999429769888818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/880999429769888818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/880999429769888818'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/09/javascript-resources.html' title='Javascript Resources'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4709252093299413626</id><published>2007-09-01T23:16:00.000-07:00</published><updated>2007-09-27T23:26:53.280-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>Upgrading to PHP5 on Mac OS X 10.4</title><content type='html'>I've been running PHP5 for ages on my Linux box, but my new (for me) MacBook Pro had PHP4...um, time for an upgrade. Well, easy enough...&lt;br /&gt;&lt;br /&gt;I downloaded the PHP5 tarball from &lt;a href="http://www.entropy.ch/software/macosx/php/" target="_blank"&gt;http://www.entropy.ch/software/macosx/php/&lt;/a&gt; and did the install. &lt;br /&gt;&lt;br /&gt;Before the install, I commented out all the php4 lines in my apache config file(&lt;code&gt;/etc/httpd/httpd.conf&lt;/code&gt;). &lt;br /&gt;&lt;br /&gt;The entropy package installed under &lt;code&gt;/usr/local/php5&lt;/code&gt; and it added a new config file (&lt;code&gt;/private/etc/httpd/users/+entropy-php.conf&lt;/code&gt;), which is included by the main apache httpd.conf file...restart apache, that's it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4709252093299413626?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4709252093299413626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4709252093299413626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4709252093299413626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4709252093299413626'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/09/upgrading-to-php5-on-mac-os-x-104.html' title='Upgrading to PHP5 on Mac OS X 10.4'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8285474843195462836</id><published>2007-08-28T11:27:00.000-07:00</published><updated>2007-08-28T11:36:27.821-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='RMagick MacOSX'/><title type='text'>RMagick on Mac OSX</title><content type='html'>When installing RMagick, I found that X11 hadn't been installed. It's on the developer CD, which I didn't have handy, so here's what I did.&lt;br /&gt;&lt;br /&gt;1) read the notes here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.apple.com/opensource/tools/runningx11.html" target="_bank"&gt;http://developer.apple.com/opensource/tools/runningx11.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2) Downloaded and installed Xcode and X11SDK from Apple Developers Center.&lt;br /&gt;&lt;br /&gt;3) I still needed X11.app, so I downloaded and installed that from:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://xanana.ucsc.edu/xtal/x11.html" target="_blank"&gt;http://xanana.ucsc.edu/xtal/x11.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;4) Downloaded and installed rm_install from:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://rubyforge.org/projects/rmagick/" target="_blank"&gt;&lt;br /&gt;http://rubyforge.org/projects/rmagick/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This will install ImageMagick and RMagick with all dependencies.&lt;br /&gt;&lt;br /&gt;I originally had downloaded ImageMagick binary and got this error when trying to install RMagick gem:&lt;br /&gt;&lt;br /&gt;"Can't install RMagick. Can't find libMagick or one of the dependent libraries. Check the config.log file for more detailed information."&lt;br /&gt;&lt;br /&gt;Info on the error here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://rubyforge.org/forum/message.php?msg_id=4066" target="_blank"&gt;&lt;br /&gt;http://rubyforge.org/forum/message.php?msg_id=4066&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8285474843195462836?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8285474843195462836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8285474843195462836' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8285474843195462836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8285474843195462836'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/08/rmagick-on-mac-osx.html' title='RMagick on Mac OSX'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-132206846485056231</id><published>2007-08-05T14:39:00.000-07:00</published><updated>2007-08-05T15:06:13.083-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><title type='text'>Ruby on Rails - script/console</title><content type='html'>A nice and easy way to check you validation rules...&lt;br /&gt;&lt;br /&gt;With a table called users with fields user_name, password, and email, we can add simple validation to the model User.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;validates_uniqueness_of :user_name, :email&lt;br /&gt;validates_length_of :user_name, :within =&gt; 4..20&lt;br /&gt;validates_length_of :password, :within =&gt; 4..20&lt;br /&gt;validates_length_of :email, :maximum =&gt; 50&lt;br /&gt;validates_format_of :user_name,&lt;br /&gt;                    :with =&gt; /^[A-Z0-9_]*$/i,&lt;br /&gt;                    :message =&gt; "must contain only letters, " +&lt;br /&gt;                                      "numbers and underscores"&lt;br /&gt;validates_format_of :email,&lt;br /&gt;                    :with =&gt; /@/,&lt;br /&gt;                    :message =&gt; "must be a valid email address"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then using script/console, we can check our validation:&lt;br /&gt;&lt;br /&gt;First, try to add a bad record:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ script/console&lt;br /&gt;Loading development environment.&lt;br /&gt;&gt;&gt; user = User.new(:user_name =&gt; "pooh bear",&lt;br /&gt;?&gt; :password =&gt; "pb",&lt;br /&gt;?&gt; :email =&gt; "poohbear_at_100akerwood.com")&lt;br /&gt;=&gt; #&lt;User:0x32bf9b4 @new_record=true, @attributes={"user_name"=&gt;"pooh bear", "password"=&gt;"pb", "email"=&gt;"poohbear_at_100akerwood.com"}&gt;&lt;br /&gt;&gt;&gt; user.save&lt;br /&gt;=&gt; false&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then you can inspect the errors individually with &lt;code&gt;errors.on&lt;/code&gt; method:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; user.errors.on(:user_name)&lt;br /&gt;=&gt; "must contain only letters, numbers and underscores"&lt;br /&gt;&gt;&gt; user.errors.on(:password)&lt;br /&gt;=&gt; "is too short (minimum is 4 characters)"&lt;br /&gt;&gt;&gt; user.errors.on(:email)&lt;br /&gt;=&gt; "must be a valid email address"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or all at once with &lt;code&gt;errors.full_messages&lt;/code&gt; method:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; user.errors.full_messages&lt;br /&gt;=&gt; ["Screen name must contain only letters, numbers and underscores", "Password is too short (minimum is 4 characters)", "Email must be a valid email address"]&lt;br /&gt;&gt;&gt;  &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-132206846485056231?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/132206846485056231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=132206846485056231' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/132206846485056231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/132206846485056231'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/08/ruby-on-rails-scriptconsole.html' title='Ruby on Rails - script/console'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8182763410472706336</id><published>2007-07-16T13:25:00.000-07:00</published><updated>2007-09-23T16:10:53.697-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mdb2'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='pear'/><title type='text'>PHP PEAR: MDB2</title><content type='html'>The PEAR DB class has been deprecated and replaced with MDB2.&lt;br /&gt;&lt;br /&gt;MDB2 doesn't come with the MySQL driver out to the box, so you need to install that separately:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ pear install MDB2&lt;br /&gt;$ pear install MDB2_Driver_mysql&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here's a simple select, using the default fetchmode of MDB2_FETCHMODE_ORDERED.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?&lt;br /&gt;require_once "MDB2.php";&lt;br /&gt;&lt;br /&gt;$dsn = 'mysql://my_username:@my_password@127.0.0.1/my_db';&lt;br /&gt;&lt;br /&gt;$options = array(&lt;br /&gt;    'debug' =&gt; 2,&lt;br /&gt;    'result_buffering' =&gt; false,&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;$mdb2 =&amp; MDB2::factory($dsn, $options);&lt;br /&gt;if (PEAR::isError($mdb2)) {&lt;br /&gt;    die($mdb2-&gt;getMessage());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Proceed with a query...&lt;br /&gt;$res =&amp; $mdb2-&gt;query('SELECT * FROM my_table');&lt;br /&gt;&lt;br /&gt;// Always check that result is not an error&lt;br /&gt;if (PEAR::isError($res)) {&lt;br /&gt;    die($res-&gt;getMessage());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Iterate through result set (assume default fetchmod is MDB2_FETCHMODE_ORDERED)&lt;br /&gt;while (($row = $res-&gt;fetchRow())) {&lt;br /&gt;    echo $row[0] . " " . $row[1] . "&amp;lt;br/&gt;\n";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The three possible fetchmode values are:&lt;br /&gt;1) MDB2_FETCHMODE_ORDERED (query results returned as array - column numbers are keys)&lt;br /&gt;2) MDB2_FETCHMODE_ASSOC (query results returned as hash/associative array - column names are keys)&lt;br /&gt;3) MDB2_FETCHMODE_OBJECT (query results returned as object - column names as properties)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To change the default fetchmode and use MDB2_FETCHMODE_ASSOC instead, use the setFetchMode method:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$mdb2-&gt;setFetchMode(MDB2_FETCHMODE_ASSOC);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and then iterate through the results:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;while ($row = $res-&gt;fetchRow()) {&lt;br /&gt;    echo $row['column_name_a'] . ' ' . $row['column_name_b'] . "&amp;lt;br/&gt;\n";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Or you can change it per call:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;while ($row = $res-&gt;fetchRow(MDB2_FETCHMODE_ASSOC)) {&lt;br /&gt;    echo $row['client_abbrv'] . ' ' . $row['client_name'] . "&amp;lt;br/&gt;\n";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here's an example of the first method:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?&lt;br /&gt;require_once "MDB2.php";&lt;br /&gt;&lt;br /&gt;$dsn = 'mysql://my_username:@my_password@127.0.0.1/my_db';&lt;br /&gt;&lt;br /&gt;$options = array(&lt;br /&gt;    'debug' =&gt; 2,&lt;br /&gt;    'result_buffering' =&gt; false,&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;$mdb2 =&amp; MDB2::factory($dsn, $options);&lt;br /&gt;if (PEAR::isError($mdb2)) {&lt;br /&gt;    die($mdb2-&gt;getMessage());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Set the fetchmode&lt;br /&gt;$mdb2-&gt;setFetchMode(MDB2_FETCHMODE_ASSOC);&lt;br /&gt;&lt;br /&gt;// Proceed with a query...&lt;br /&gt;$res =&amp; $mdb2-&gt;query('SELECT * FROM my_table');&lt;br /&gt;&lt;br /&gt;// Always check that result is not an error&lt;br /&gt;if (PEAR::isError($res)) {&lt;br /&gt;    die($res-&gt;getMessage());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Iterate through result set&lt;br /&gt;while ($row = $res-&gt;fetchRow()) {&lt;br /&gt;    echo $row['column_name_a'] . ' ' . $row['column_name_b'] . "&amp;lt;br/&gt;\n";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can insert data with a prepared statement:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?&lt;br /&gt;require_once "MDB2.php";&lt;br /&gt;&lt;br /&gt;$dsn = 'mysql://my_username:@my_password@127.0.0.1/my_db';&lt;br /&gt;&lt;br /&gt;$options = array(&lt;br /&gt;    'debug' =&gt; 2,&lt;br /&gt;    'result_buffering' =&gt; false,&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;$mdb2 =&amp; MDB2::factory($dsn, $options);&lt;br /&gt;if (PEAR::isError($mdb2)) {&lt;br /&gt;    die($mdb2-&gt;getMessage());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Insert&lt;br /&gt;$statement = $mdb2-&gt;prepare('INSERT INTO clients VALUES (?, ?)');&lt;br /&gt;$data = array($var1, $var2);&lt;br /&gt;$statement-&gt;execute($data);&lt;br /&gt;$statement-&gt;free();&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;These are just the basics...read all the goodness here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://pear.php.net/manual/en/package.database.mdb2.php"&gt;http://pear.php.net/manual/en/package.database.mdb2.php&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8182763410472706336?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8182763410472706336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8182763410472706336' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8182763410472706336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8182763410472706336'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/07/php-pear-mdb2.html' title='PHP PEAR: MDB2'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8134124151139525504</id><published>2007-07-14T15:19:00.000-07:00</published><updated>2007-09-23T15:57:18.534-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mdb2'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='pear'/><title type='text'>PHP PEAR: MDB2 Error: connect failed (localhost MySQL)</title><content type='html'>I ran into a persistent connect error when trying to connect to localhost MySQL database with MDB2. &lt;br /&gt;&lt;br /&gt;Instead of:&lt;br /&gt;&lt;br /&gt;dsn: mysql://my_username:my_password@localhost/my_db&lt;br /&gt;&lt;br /&gt;use:&lt;br /&gt;&lt;br /&gt;dsn: mysql://my_username:my_password@127.0.0.1/my_db&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8134124151139525504?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8134124151139525504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8134124151139525504' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8134124151139525504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8134124151139525504'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/07/php-pear-mdb2-error-connect-failed.html' title='PHP PEAR: MDB2 Error: connect failed (localhost MySQL)'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1923612344274622316</id><published>2007-07-05T12:50:00.000-07:00</published><updated>2007-07-05T12:53:37.126-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><title type='text'>Viewing Ruby Gem documentation</title><content type='html'>1) Command line&lt;br /&gt;&lt;br /&gt;$ ri &amp;lt;gem_name&amp;gt;&lt;br /&gt;&lt;br /&gt;2) Browser (http://localhost:8808)&lt;br /&gt;&lt;br /&gt;$ gem_server&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1923612344274622316?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1923612344274622316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1923612344274622316' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1923612344274622316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1923612344274622316'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/07/viewing-ruby-gem-documentation.html' title='Viewing Ruby Gem documentation'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-7918362936371465925</id><published>2007-07-05T12:20:00.000-07:00</published><updated>2007-09-23T15:57:31.237-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Emulate PHP5 str_split() in PHP4</title><content type='html'>/* emulate the php5 str_split function&lt;br /&gt; * array str_split( string $string [, int $split_length])&lt;br /&gt; *  Converts a string to an array&lt;br /&gt; *  If the optional split_length param is specified, the returned array&lt;br /&gt; *  will be broken down into chunks with each being split_length in&lt;br /&gt; *  length, otherwise each chuck will be one character in length.&lt;br /&gt; *  False is returned if split_length is less than 1. If the split_length&lt;br /&gt; *  length exceeds the length of string, the entire string is returned&lt;br /&gt; *  as the first (and only) array element.&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;If you want to use optional &lt;code&gt;split_length&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function str_split($str, $l=1) {&lt;br /&gt;  $str_array = explode("\r\n", chunk_split($str,$l));&lt;br /&gt;  return $str_array;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Or optionally, if you just need the simple split (&lt;code&gt;split_length=1&lt;/code&gt;):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function str_split($str) {&lt;br /&gt;  $str_array=array();&lt;br /&gt;  $len=strlen($str);&lt;br /&gt;  for($i=0; $i&lt;$len; $i++) {&lt;br /&gt;    $str_array[]=$str{$i};&lt;br /&gt;  }&lt;br /&gt;  return $str_array;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-7918362936371465925?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/7918362936371465925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=7918362936371465925' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/7918362936371465925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/7918362936371465925'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/07/emulate-php5-strsplit-in-php4.html' title='Emulate PHP5 str_split() in PHP4'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8649042386883766490</id><published>2007-07-05T09:43:00.000-07:00</published><updated>2007-07-05T09:44:36.616-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='Gems'/><title type='text'>Gem List</title><content type='html'>Here's a command to list all your installed Gems:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;gem list | grep '^[a-zA-Z]'&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8649042386883766490?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8649042386883766490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8649042386883766490' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8649042386883766490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8649042386883766490'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/07/gem-list.html' title='Gem List'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4918793558161922896</id><published>2007-06-12T14:34:00.000-07:00</published><updated>2007-06-12T14:38:12.642-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Eclipse Tutorials</title><content type='html'>&lt;a href="https://eclipse-tutorial.dev.java.net/" target="_blank"&gt;eclipse-tutorial: Project Home Page&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.cs.armstrong.edu/liang/intro5e/SupplementJEclipse.pdf" target="_blank"&gt;Eclipse Tutorial&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ibm.com/developerworks/views/opensource/library.jsp?sort_order=desc&amp;expand=&amp;sort_by=Date&amp;show_abstract=false&amp;view_by=Eclipse&amp;search_by=" target="_blank"&gt;developerWorks : Open source : Technical library&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4918793558161922896?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4918793558161922896/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4918793558161922896' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4918793558161922896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4918793558161922896'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/06/eclipse-tutorials.html' title='Eclipse Tutorials'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-6800624313884289283</id><published>2007-06-08T12:25:00.000-07:00</published><updated>2007-06-08T12:28:50.077-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apt-get'/><category scheme='http://www.blogger.com/atom/ns#' term='APT'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>APT Quick Reference</title><content type='html'>I found this handy apt-get &lt;a href="http://www.phildev.net/linux/apt-quickref.html" target="_blank"&gt;Phil's APT Quick Reference&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Download and install &lt;I&gt;package&lt;/I&gt;:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-get install package&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Update apt's list of available packages:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-get update&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Upgrade all installed packages with upgrades available:&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;&lt;CODE&gt;apt-get upgrade&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Upgrade to new distro, or in general upgrade anything available for update including core system packages:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-get dist-upgrade&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Uninstall &lt;I&gt;package&lt;/I&gt;:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-get remove &lt;I&gt;package&lt;/I&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Uninstall &lt;I&gt;package&lt;/I&gt;, and its config files, and don't leave it in the database as 'uninstalled':&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-get --purge remove &lt;I&gt;package&lt;/I&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Search for a package like &lt;I&gt;pattern&lt;/I&gt;:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-cache search &lt;I&gt;pattern&lt;/I&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Get information on installed &lt;I&gt;package&lt;/I&gt;:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;dpkg -s &lt;I&gt;package&lt;/I&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Find which installed package &lt;I&gt;file&lt;/I&gt; belongs to:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;dpkg -S inetd.conf&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;List which files are in &lt;I&gt;package&lt;/I&gt;:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-file list &lt;I&gt;package&lt;/I&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Find out what packages provide &lt;I&gt;file&lt;/I&gt;:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-file search &lt;I&gt;file&lt;/I&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Run a &lt;I&gt;command&lt;/I&gt; (such as &lt;I&gt;./configure&lt;/I&gt; or &lt;I&gt;make&lt;/I&gt;) and have all necessary packages installed as needed:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;auto-apt run &lt;I&gt;command&lt;/I&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;br /&gt;&lt;br /&gt;Unless specified, the package in reference doesn't have to be already installed for these to work... but the database needs to be updated. You can update the appropriate database via:&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-get update&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;or&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;auto-apt update&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;or&lt;BR&gt;&lt;br /&gt;&lt;CODE&gt;apt-file update&lt;/CODE&gt;&lt;BR&gt;&lt;br /&gt;&lt;BR&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-6800624313884289283?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/6800624313884289283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=6800624313884289283' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6800624313884289283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6800624313884289283'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/06/apt-quick-reference.html' title='APT Quick Reference'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-6644550333079646034</id><published>2007-06-08T11:59:00.000-07:00</published><updated>2007-06-08T16:05:52.654-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='mongrel'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Ruby on Rails/Mongrel/Ubuntu</title><content type='html'>I've been using Ubuntu lately and decided to install Ruby on Rails and Mongrel.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ sudo apt-get install ruby irb rdoc&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Or download the source for the latest version (apt-get installs 1.8.4, but the latest source is 1.8.6):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ tar zxvf ruby-1.8.6.tar.gz&lt;br /&gt;$ cd ruby-1.8.6&lt;br /&gt;$ ./configure &lt;br /&gt;$ make&lt;br /&gt;$ sudo make install&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Once ruby is installed, I typically use Gems if I can.&lt;br /&gt;&lt;br /&gt;Download the latest Gems at &lt;a href="http://rubyforge.org/frs/?group_id=126" target="_blank"&gt;http://rubyforge.org/frs/?group_id=126&lt;/a&gt; (0.9.4 in this case) and then:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ tar xzvf rubygems-0.9.4.tgz&lt;br /&gt;$ cd rubygems-0.9.4&lt;br /&gt;$ sudo ruby setup.rb&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Install Rails:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sudo gem install rails --include-dependencies&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Install Mongrel and Mongrel cluster gem plugin:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sudo gem install mongrel --include-dependencies&lt;br /&gt;sudo gem install mongrel_cluster&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Install Apache 2.2&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ tar zxvf httpd-2.2.4.tar.gz&lt;br /&gt;$ cd httpd-2.2.4&lt;br /&gt;$ ./configure \&lt;br /&gt;  --prefix=/usr/local/apache \&lt;br /&gt;  --enable-rewrite \&lt;br /&gt;  --enable-headers \&lt;br /&gt;  --enable-ssl \  &lt;br /&gt;  --enable-proxy \ &lt;br /&gt;  --with-mpm=prefork&lt;br /&gt;$ make&lt;br /&gt;$ sudo make install&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I got this error when running configure:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Configuring Apache Portable Runtime Utility library...&lt;br /&gt;&lt;br /&gt;checking for APR-util... yes&lt;br /&gt;configure: error: Cannot use an external APR-util with the bundled APR&lt;br /&gt;make: *** [apache] Error 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Adding this option fixed the problem:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;--with-included-apr &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running Apache with a single Mongrel Instance&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ mongrel_rails start -p 8000 -e production -d&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Add to apache conf (httpd.connf)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ServerName hostname.com&lt;br /&gt;ServerAlias www.hostname.com&lt;br /&gt;&lt;br /&gt;ProxyPass / http://www.hostname.com:8000/&lt;br /&gt;ProxyPassReverse / http://www.hostname.com:8000/&lt;br /&gt;ProxyPreserveHost on&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Restart Apache and it will forward requests for www.hostname.com on port 80 to Mongrel server running on port 8000.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-6644550333079646034?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/6644550333079646034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=6644550333079646034' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6644550333079646034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6644550333079646034'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/06/ruby-on-railsmongrelubuntu.html' title='Ruby on Rails/Mongrel/Ubuntu'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-5721073802498912192</id><published>2007-06-07T08:44:00.000-07:00</published><updated>2007-06-27T07:12:55.927-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>Javascript/Ajax Libraries</title><content type='html'>I've been working on a few Ajax and DOM scripting projects at work using prototype.js and scriptaculous. Now we're looking at a "Web 2.0" upgrade for some of our sites, so I'm looking at several libraries:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.prototypejs.org/" target="_blank"&gt;Prototype JavaScript Framework&lt;/a&gt;&lt;br /&gt;&lt;a href="http://script.aculo.us/" target="_blank"&gt;script.aculo.us&lt;/a&gt;&lt;br /&gt;&lt;a href="http://dojotoolkit.org/" target="_blank"&gt;The Dojo Toolkit&lt;/a&gt;&lt;br /&gt;&lt;a href="http://openrico.org/" target="_blank"&gt;Rico&lt;/a&gt;&lt;br /&gt;&lt;a href="http://developer.yahoo.com/yui/" target="_blank"&gt;Yahoo! UI Library (YUI)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://mootools.net/" target="_blank"&gt;mootools framework&lt;/a&gt;&lt;br /&gt;&lt;a href="http://mochikit.com/" target="_blank"&gt;MochiKit&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jquery.com/" target="_blank"&gt;JQuery&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There are many, many more...&lt;br /&gt;&lt;a href="http://chandlerproject.org/Projects/AjaxLibraries" target="_blank"&gt;OSA Foundation - Survey of Ajax/JavaScript Libraries&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here's an accoridion demo I created with Rico:&lt;br /&gt;&lt;a href="http://www.dougsparling.com/dev/js/rico/accordion.php" target="_blank"&gt;My Rico Accordion Demo&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-5721073802498912192?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/5721073802498912192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=5721073802498912192' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5721073802498912192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5721073802498912192'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/06/javascriptajax-libraries.html' title='Javascript/Ajax Libraries'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-6771515750034863364</id><published>2007-06-04T22:51:00.002-07:00</published><updated>2007-06-04T23:54:25.505-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DocBook'/><title type='text'>DocBook</title><content type='html'>I've been tackling some documentation at work and decided to take a look at docbook. &lt;br /&gt;&lt;br /&gt;There are a few good resources to start with:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.docbook.org/" target="_blank"&gt;DocBook.org&lt;/a&gt; the home of "DocBook: The Definitive Guide" by &lt;a href="http://nwalsh.com/" target="_blank"&gt;Norman Walsh&lt;/a&gt; and Leonard Muellner (published by &lt;a href="http://www.oreilly.com/" target="_blank"&gt;O'Reilly &amp; Associates, Inc.&lt;/a&gt;), the official documentation for DocBook.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sagehill.net/book-description.html" target="_blank"&gt;"DocBook XSL: The Complete Guide"&lt;/a&gt; by Bob Stayton.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.lodestar2.com/people/dyork/talks/2002/ols/docbook-tutorial/frames/frames.html"  target="_blank"&gt;Single-Source Publishing with DocBook XML&lt;/a&gt; by Dan York.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;With DocBook, you can use SGML (Dsssl styesheets) or XML (XSL stylesheets). I've chosen to work with XML. "DocBook XSL" provides the details of all the tools that are needed. At the moment I'm working on a Mac laptop, using the following:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;DocBook DTD: The DTDs can be found at &lt;a href="http://www.oasis-open.org/docbook/xml/" target="_blank"&gt;http://www.oasis-open.org/docbook/xml/&lt;/a&gt;. I downloaded&lt;br /&gt;&lt;a href="http://www.oasis-open.org/docbook/xml/4.5/" target="_blank"&gt;version 4.5&lt;/a&gt; (docbook-xml-4.5.zip).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;DocBook XSL Stylesheets: The XSL stylesheets can be downloaded from &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=21935" target="_blank"&gt; http://sourceforge.net/project/showfiles.php?group_id=21935&lt;/a&gt;. I downloaded docbook-xsl 1.72.0.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;XSL processor: &lt;a href="http://xmlsoft.org/XSLT/xsltproc2.html" target="_blank"&gt;xsltproc&lt;/a&gt; (already installed on my system). There are a few others as well (Saxon, Xalan).&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I installed everything in my home directory and worked from there, but LSB proposal is:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;DTD: /usr/share/sgml/docbook/xml-dtd-4.5&lt;/li&gt;&lt;br /&gt;&lt;li&gt;XSL: /usr/share/sgml/docbook/docbook-xsl-1.72.0/&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Create a DocBook XML file (book.xml, for example)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&gt;&lt;br /&gt;&amp;lt;!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5/EN"&lt;br /&gt;"/path/to/dtd/docbook-xml-4.5/docbookx.dtd"&gt;&lt;br /&gt;&amp;lt;book&gt;&lt;br /&gt;&amp;lt;bookinfo&gt;&lt;br /&gt;&amp;lt;title&gt;My Book Title&amp;lt;/title&gt;&lt;br /&gt;&amp;lt;/bookinfo&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;chapter&gt;&lt;br /&gt;&amp;lt;title&gt;Chapter Name&amp;lt;/title&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;para&gt;Some text&amp;lt;/para&gt;&lt;br /&gt;&amp;lt;/chapter&gt;&lt;br /&gt;&amp;lt;/book&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Procss to generate html:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ xsltproc --output book.html /path/to/docbook-xsl-1.72.0/html/docbook.xsl book.xml&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can validate XML using xmllint (parser won't necessarily do it).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ xmllint --noout book.xml&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No output will be seen unless there is an error.&lt;br /&gt;&lt;br /&gt;I haven't covered other formats (like converting to pdf using FOP), Java parsers, catalogs, makefiles, and Ant.&lt;br /&gt;&lt;br /&gt;Speaking of Ant, here's a resource for DocBook and Ant:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dpawson.co.uk/docbook/ant.html" target="_blank"&gt;DocBook and Ant&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've already started looking at using &lt;a href="http://cocoon.apache.org/" target="_blank"&gt;Cocoon&lt;/a&gt; with DocBook, but that will be material for another post...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-6771515750034863364?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/6771515750034863364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=6771515750034863364' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6771515750034863364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/6771515750034863364'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/06/docbook.html' title='DocBook'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-5285036134686866167</id><published>2007-06-04T22:40:00.000-07:00</published><updated>2007-06-04T23:51:29.990-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='WebSphere'/><title type='text'>WebSphere Application Server V6.1 on Linux</title><content type='html'>I recently downloaded the full-featured trial download of &lt;a href="http://www14.software.ibm.com/webapp/download/featured.jsp?b=WebSphere" target="_blank"&gt;WebSphere&lt;/a&gt; Application Server V6.1 to my old Fedora Core 5 laptop.&lt;br /&gt;&lt;br /&gt;The installation was amazingly easy...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ tar zxvf websphere.tar.gz&lt;br /&gt;$ cd WAS/install&lt;br /&gt;$ java -jar WAS/setup.jar&lt;br /&gt;$ cd /opt/IBM/WebSphere/AppServer/bin&lt;br /&gt;$ ./startServer server1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After starting WebSphere, you can check out the sample application:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;http://localhost:9080/WSsamples&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-5285036134686866167?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/5285036134686866167/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=5285036134686866167' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5285036134686866167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/5285036134686866167'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/06/websphere-application-server-v61-on.html' title='WebSphere Application Server V6.1 on Linux'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1796752172799519127</id><published>2007-05-25T13:10:00.000-07:00</published><updated>2007-05-25T13:44:36.041-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Music'/><category scheme='http://www.blogger.com/atom/ns#' term='Audio'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Bash'/><title type='text'>Audio file conversion</title><content type='html'>Here's a collection of small scripts for converting audio file formats using lame, mpg123, and mplayer.&lt;br /&gt;&lt;br /&gt;wav2mp3.pl&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;my $in = "/home/doug/music/somedir/";&lt;br /&gt;my $out = $in;&lt;br /&gt;&lt;br /&gt;opendir DH_IN, $in || die "Can't open $in: $!";&lt;br /&gt;foreach my $name (sort readdir(DH_IN)) {&lt;br /&gt;  next unless $name =~ /\.wav$/;&lt;br /&gt;  print "NAME: $name\n";&lt;br /&gt;  my($base_name) = ($name =~ /^(.*)\.wav$/);&lt;br /&gt;  my $in_file = "${in}$base_name.wav";&lt;br /&gt;  my $out_file = "${out}$base_name.mp3";&lt;br /&gt;  `lame -b 192 $in_file $out_file`;&lt;br /&gt;}&lt;br /&gt;close DH_IN;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;wav2mp3.sh&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;bitrate="192"&lt;br /&gt;for wavfile in *.wav&lt;br /&gt;do&lt;br /&gt;   echo "input: $wavfile"&lt;br /&gt;   mp3file=`echo $wavfile | sed s/\\.wav/.mp3/`&lt;br /&gt;   echo "output: $mp3file"&lt;br /&gt;   lame -b $bitrate $wavfile $mp3file&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;mp32wav.sh&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;for mp3file in *.mp3&lt;br /&gt;do&lt;br /&gt;   echo "input: $mp3file"&lt;br /&gt;   wavfile=`echo $mp3file | sed s/\\.mp3/.wav/`&lt;br /&gt;   echo "output: $wavfile"&lt;br /&gt;   mpg123 -w $wavfile $mp3file&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;wma2mp3.sh&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;&lt;br /&gt;if [ -z "$1" ]&lt;br /&gt;then&lt;br /&gt;        echo "Usage: wma2mp3 &lt;file.wma&gt;"&lt;br /&gt;        exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;name=`echo $1 | tr ' ' '_' | tr '[A-Z]' '[a-z]'`&lt;br /&gt;&lt;br /&gt;name="`basename "$name" .wma`.mp3"&lt;br /&gt;&lt;br /&gt;cp "$1" $name&lt;br /&gt;&lt;br /&gt;mplayer -vo null -vc dummy -af resample=44100 -ao pcm:waveheader $name &amp;&amp; lame -m s -h --vbr-new audiodump.wav -o $name&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;m4a2mp3.sh&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;&lt;br /&gt;MPLAYER=mplayer&lt;br /&gt;LAME=lame&lt;br /&gt;&lt;br /&gt;for m4a in *.m4a&lt;br /&gt;do&lt;br /&gt;&lt;br /&gt;    mp3=`echo "$m4a" | sed -e 's/m4a$/mp3/'`&lt;br /&gt;    wav="$m4a.wav"&lt;br /&gt;&lt;br /&gt;    if [ ! -e "$mp3" ]; then&lt;br /&gt;        [ -e "$wav" ] &amp;&amp; rm "$wav"&lt;br /&gt;   mkfifo "$wav" || exit 255&lt;br /&gt;        mplayer "$m4a" -ao pcm:file="$wav" &amp;&gt;/dev/null &amp;&lt;br /&gt;        lame "$wav" "$mp3"&lt;br /&gt;        [ -e "$wav" ] &amp;&amp; rm "$wav"&lt;br /&gt;    fi&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1796752172799519127?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1796752172799519127/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1796752172799519127' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1796752172799519127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1796752172799519127'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/05/audio-file-conversion.html' title='Audio file conversion'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-1653195878580318317</id><published>2007-05-25T12:54:00.000-07:00</published><updated>2007-05-25T12:56:25.168-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Finding installed Perl modules</title><content type='html'>I don't recall where I came across this little script, but it's quite handy for finding installed Perl modules along with their versions.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;&lt;br /&gt;use ExtUtils::Installed;&lt;br /&gt;my $instmod = ExtUtils::Installed-&gt;new();&lt;br /&gt;foreach my $module ($instmod-&gt;modules()) {&lt;br /&gt;    my $version = $instmod-&gt;version($module) || "???";&lt;br /&gt;    print "$module -- $version\n";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-1653195878580318317?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/1653195878580318317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=1653195878580318317' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1653195878580318317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/1653195878580318317'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/05/finding-installed-perl-modules.html' title='Finding installed Perl modules'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-8776353888601086906</id><published>2007-05-16T12:30:00.000-07:00</published><updated>2007-05-16T14:49:30.610-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='iBATIS'/><title type='text'>iBATIS - part 1</title><content type='html'>Very basic and simple iBATIS tutorial for a simple SELECT:&lt;br /&gt;&lt;br /&gt;Download iBATIS from &lt;a href="http://ibatis.apache.org/"&gt;http://ibatis.apache.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Unpack the tar ball and install the jar file (it's now a single file - something like ibatis-2.3.0.677.jar) somewhere on your classpath...or if using with Tomcat or another servlet container, add it to "/WEB-INF/lib" in your for the webapp. &lt;br /&gt;&lt;br /&gt;Database (MySQL)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mysql&gt; describe book;&lt;br /&gt;+------------+--------------+------+-----+---------+----------------+&lt;br /&gt;| Field      | Type         | Null | Key | Default | Extra          |&lt;br /&gt;+------------+--------------+------+-----+---------+----------------+&lt;br /&gt;| id         | int(11)      | NO   | PRI | NULL    | auto_increment |&lt;br /&gt;| title      | varchar(50)  | NO   |     |         |                |&lt;br /&gt;| authors    | varchar(50)  | YES  |     | NULL    |                |&lt;br /&gt;| editor     | varchar(50)  | YES  |     | NULL    |                |&lt;br /&gt;| chapters   | text         | YES  |     | NULL    |                |&lt;br /&gt;| page_count | int(11)      | YES  |     | NULL    |                |&lt;br /&gt;| status     | char(1)      | NO   |     | P       |                |&lt;br /&gt;| price      | decimal(5,2) | YES  |     | NULL    |                |&lt;br /&gt;+------------+--------------+------+-----+---------+----------------+&lt;br /&gt;&lt;br /&gt;mysql&gt; SELECT * FROM book;&lt;br /&gt;+----+----------------------+---------+--------+----------+------------+--------+-------+&lt;br /&gt;| id | title                | authors | editor | chapters | page_count | status | price |&lt;br /&gt;+----+----------------------+---------+--------+----------+------------+--------+-------+&lt;br /&gt;|  1 | Learning Perl 3rd Ed | NULL    | NULL   | NULL     |       NULL | P      | 29.99 |&lt;br /&gt;|  2 | Learning Java 4th Ed | NULL    | NULL   | NULL     |       NULL | P      | 29.99 |&lt;br /&gt;+----+----------------------+---------+--------+----------+------------+--------+-------+&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;SqlMapConfig.xml&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"&lt;br /&gt;"http://www.ibatis.com/dtd/sql-map-config-2.dtd"&gt;&lt;br /&gt;&amp;lt;sqlMapConfig&gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!-- These settings control SqlMap configuration details --&gt;&lt;br /&gt;        &amp;lt;settings&lt;br /&gt;                useStatementNamespaces="true"&lt;br /&gt;        /&gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;transactionManager type="JDBC"&gt;&lt;br /&gt;                &amp;lt;dataSource type="SIMPLE"&gt;&lt;br /&gt;                        &amp;lt;property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/&gt;&lt;br /&gt;                        &amp;lt;property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost/bookdb"/&gt;&lt;br /&gt;                        &amp;lt;property name="JDBC.Username" value="yourusername"/&gt;&lt;br /&gt;                        &amp;lt;property name="JDBC.Password" value="yourpassword"/&gt;&lt;br /&gt;                &amp;lt;/dataSource&gt;&lt;br /&gt;        &amp;lt;/transactionManager&gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!-- Identify all SQL Map XML files to be loaded by this SQL map --&gt;&lt;br /&gt;        &amp;lt;sqlMap resource="BookMap.xml" /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/sqlMapConfig&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;BookMap.xml&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" ?&gt;&lt;br /&gt;&amp;lt;!DOCTYPE sqlMap&lt;br /&gt;PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"&lt;br /&gt;"http://www.ibatis.com/dtd/sql-map-2.dtd"&gt;&lt;br /&gt;&amp;lt;sqlMap namespace="Book"&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;resultMap id="get-Result" class="Book"&gt;&lt;br /&gt;        &amp;lt;result property="id" column="id"/&gt;&lt;br /&gt;        &amp;lt;result property="title" column="title"/&gt;&lt;br /&gt;&amp;lt;/resultMap&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;select id="getById" parameterClass="string" resultMap="get-Result"&gt;&lt;br /&gt;SELECT * FROM book WHERE (id = #value#)&lt;br /&gt;&amp;lt;/select&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;select id="getAll" parameterClass="string" resultMap="get-Result"&gt;&lt;br /&gt;SELECT * FROM book WHERE (status = 'P') ORDER BY title&lt;br /&gt;&amp;lt;/select&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/sqlMap&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Book.java&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import com.ibatis.sqlmap.client.SqlMapClient;&lt;br /&gt;import java.sql.Date;&lt;br /&gt;&lt;br /&gt;public class Book {&lt;br /&gt;&lt;br /&gt;  public int getId()&lt;br /&gt;  {&lt;br /&gt;    return id;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setId(int id)&lt;br /&gt;  {&lt;br /&gt;    this.id = id;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String getTitle()&lt;br /&gt;  {&lt;br /&gt;    return title;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setTitle(String title)&lt;br /&gt;  {&lt;br /&gt;    this.title = title;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public char getStatus()&lt;br /&gt;  {&lt;br /&gt;    return status;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setStatus(char status)&lt;br /&gt;  {&lt;br /&gt;    this.status = status;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private Integer id;&lt;br /&gt;  private String title;&lt;br /&gt;  private char status;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;BookTest.java&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import com.ibatis.sqlmap.client.*;&lt;br /&gt;import com.ibatis.common.resources.Resources;&lt;br /&gt;&lt;br /&gt;import java.io.Reader;&lt;br /&gt;import java.util.List;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;&lt;br /&gt;public class BookTest {&lt;br /&gt;  public static void main(String arg[]) throws Exception {&lt;br /&gt;    String resource = "SqlMapConfig.xml";&lt;br /&gt;    Reader reader = Resources.getResourceAsReader(resource);&lt;br /&gt;    SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);&lt;br /&gt;    List bookList = sqlMap.queryForList("Book.getAll",null);&lt;br /&gt;    System.out.println("Selected " + bookList.size() + " records.");&lt;br /&gt;&lt;br /&gt;    if(bookList.size() == 0){&lt;br /&gt;      System.out.println("OOOPS - bookList size is 0\n");&lt;br /&gt;    }&lt;br /&gt;    Iterator books = bookList.iterator();&lt;br /&gt;    StringBuffer bookBuffer = new StringBuffer();&lt;br /&gt;    while(books.hasNext()){&lt;br /&gt;      Book bookX = (Book)books.next();&lt;br /&gt;      bookBuffer.append("ID: " + bookX.getId() + " TITLE: " + bookX.getTitle() + "\n");&lt;br /&gt;    }&lt;br /&gt;    String bookOptions = bookBuffer.toString();&lt;br /&gt;    System.out.println(bookOptions);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ java BookTest&lt;br /&gt;Selected 2 records.&lt;br /&gt;ID: 2 TITLE: Learning Java 4th Ed&lt;br /&gt;ID: 1 TITLE: Learning Perl 3rd Ed&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-8776353888601086906?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/8776353888601086906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=8776353888601086906' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8776353888601086906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/8776353888601086906'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/05/ibatis-part-1.html' title='iBATIS - part 1'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-4200352067900398819</id><published>2007-05-13T12:13:00.000-07:00</published><updated>2007-05-14T08:08:29.160-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>Tomcat - How to run stand alone on port 80</title><content type='html'>With Apache, all ports below 1024 are privileged ports, so normally to run Tomcat as a stand alone server, you'd have to run as root, which is a Very Bad Idea. Using the jsvc interface, it is possible to bind Tomcat to a privileged port, such as port 80.&lt;br /&gt;&lt;br /&gt;First, change server.xml to use port 80:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ cd $CATALINA_HOME/conf&lt;br /&gt;$ sudo vi server.xml&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and make this change:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    &amp;lt;!--&amp;lt;Connector port="8080" protocol="HTTP/1.1" --&gt;&lt;br /&gt;    &amp;lt;Connector port="80" protocol="HTTP/1.1"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With Tomcat 5 &amp; 6, there will be a &lt;code&gt;jsvc.tar.gz&lt;/code&gt; file in the &lt;code&gt;bin&lt;/code&gt; directory of your &lt;code&gt;$CATALINA_HOME&lt;/code&gt; directory.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ cd $CATALINA_HOME/bin&lt;br /&gt;$ sudo tar zxvf jsvc.tar.gz&lt;br /&gt;$ cd jsvc-src&lt;br /&gt;$ sudo autoconf&lt;br /&gt;$ sudo ./configure&lt;br /&gt;$ sudo make&lt;br /&gt;$ sudo cp jsvc ..&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I had to add a few packages on Ubuntu to compile jsvc...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ sudo apt-get install libc6-dev g++ gcc&lt;br /&gt;$ sudo apt-get install make&lt;br /&gt;$ sudo apt-get install autoconf&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can start Tomcat as "tomcat" user (use which ever existing non-privileged user you want, or create a new user):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ cd $CATALINA_HOME&lt;br /&gt;$ sudo ./bin/jsvc -cp ./bin/bootstrap.jar \&lt;br /&gt;  -user tomcat \&lt;br /&gt;  -outfile ./logs/catalina.out \&lt;br /&gt;  -errfile ./logs/catalina.err \&lt;br /&gt;  org.apache.catalina.startup.Bootstrap&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There is a sample starup script in the &lt;code&gt;$CATALINA_HOME/bin/jsvc-src/native&lt;/code&gt; directory, which can be modified to work on your system:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ cd /etc/init.d&lt;br /&gt;$ sudo cp tomcat tomcat.bak (if needed, and make sure it will start on the run levels you need for startup on server boot)&lt;br /&gt;$ sudo cp $CATALINA_HOME/bin/jsvc-src/native/Tomcat5.sh ./tomcat&lt;br /&gt;$ sudo vi tomcat (edit for your system)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now you can start Tomcat:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ sudo /etc/init.d/tomcat start&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;More info can be found at &lt;a href="http://jakarta.apache.org/commons/daemon/jsvc.html" target="_blank"&gt;Apache Jakarta Project - commons daemon (Java Service)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-4200352067900398819?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/4200352067900398819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=4200352067900398819' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4200352067900398819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/4200352067900398819'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/05/tomcat-how-to-run-stand-alone-on-port.html' title='Tomcat - How to run stand alone on port 80'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3643639393714331361</id><published>2007-04-29T22:49:00.000-07:00</published><updated>2007-05-02T07:25:06.791-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Hibernate 3 Tutorial</title><content type='html'>Here's a simple Hibernate tutorial which will guide you through installation, configuration, and use of Hibernate 3.2, HSQLDB, Ant, and Java on Linux...&lt;br /&gt;&lt;br /&gt;This is a rather contrived example and nothing you would see in the real world, but I'll probably expand on this example in later posts.&lt;br /&gt;&lt;br /&gt;You'll need the following to run this Hibernate example:&lt;br /&gt;&lt;br /&gt;Apache Ant&lt;br /&gt;Hibernate&lt;br /&gt;Hibernate Tools&lt;br /&gt;Hsqldb&lt;br /&gt;&lt;br /&gt;As of April 23, 2007, these were the latest downloads:&lt;br /&gt;&lt;br /&gt;apache-ant-1.7.0-bin.tar.gz&lt;br /&gt;hibernate-3.2.2.ga.tar.gz&lt;br /&gt;HibernateTools-3.2.0.beta9a.zip&lt;br /&gt;hsqldb_1_8_0_7.zip&lt;br /&gt;&lt;br /&gt;I installed these under /usr/local on my laptop (Fedora), but you can install them anywhere that works for you.&lt;br /&gt;&lt;br /&gt;So I ended up with this directory structure:&lt;br /&gt;&lt;br /&gt;/usr/local/apache-ant-1.7.0        &lt;br /&gt;/usr/local/hibernate-3.2    &lt;br /&gt;/usr/local/HibernateTools  &lt;br /&gt;/usr/local/hsqldb &lt;br /&gt;&lt;br /&gt;Note: Manually create the HibernateTools directory and unzip the HibernateTools zip file there.&lt;br /&gt;&lt;br /&gt;Create a project directory where you'll place your project files. I created a project directory called "Book" in my home directory (/home/doug/Book).&lt;br /&gt;&lt;br /&gt;Here's the project file layout:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Book -&lt;br /&gt;  build.properties&lt;br /&gt;  build.xml&lt;br /&gt;  classes -&lt;br /&gt;  data -&lt;br /&gt;  src -&lt;br /&gt;    hibernate.cfg.xml  &lt;br /&gt;    log4j.properties&lt;br /&gt;    com - &lt;br /&gt;      dougsparling -&lt;br /&gt;        AddBook.java  &lt;br /&gt;        Book.hbm.xml  &lt;br /&gt;        Book.java  &lt;br /&gt;        ListBooks.java&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;br /&gt;Database files will build under the data directory. The classes directory will be created during the Ant build process, so you don't need to create that directory manually.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;1) Ant build script&lt;/h3&gt;&lt;br /&gt;Includes targets to create schema/database tables, prepare project files and directories, and compile java source code, as well as a target to add books to the database and another target to read books from databasae.&lt;br /&gt;&lt;br /&gt;Book/build.xml&lt;br /&gt;-------------------&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&gt;&lt;br /&gt;&amp;lt;project name="book"&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- properties --&gt;&lt;br /&gt;  &amp;lt;property file="build.properties"/&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="src" value="src"/&gt;&lt;br /&gt;  &amp;lt;property name="class" value="classes"/&gt;&lt;br /&gt;  &amp;lt;property name="data" value="data"/&gt;&lt;br /&gt;  &amp;lt;property name="hibernate.tools"&lt;br /&gt;            value="${hibernate.tools.home}${hibernate.tools.path}"/&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- project classpath --&gt;&lt;br /&gt;  &amp;lt;path id="project.classpath"&gt;&lt;br /&gt;    &amp;lt;pathelement location="${src}"/&gt;&lt;br /&gt;    &amp;lt;pathelement location="${class}"/&gt;&lt;br /&gt;    &amp;lt;pathelement location="${hibernate.home}/hibernate3.jar"/&gt;&lt;br /&gt;    &amp;lt;fileset dir="${hibernate.home}/lib" includes="**/*.jar"/&gt;&lt;br /&gt;    &amp;lt;pathelement location="${hsql.home}/lib/hsqldb.jar"/&gt;&lt;br /&gt;  &amp;lt;/path&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- Hibernate tools classpath --&gt;&lt;br /&gt;  &amp;lt;path id="tools.classpath"&gt;&lt;br /&gt;    &amp;lt;path refid="project.classpath"/&gt;&lt;br /&gt;    &amp;lt;pathelement location="${hibernate.tools}/hibernate-tools.jar"/&gt;&lt;br /&gt;  &amp;lt;/path&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- task def for Hibernate Tools --&gt;&lt;br /&gt;  &amp;lt;taskdef name="htools"&lt;br /&gt;           classname="org.hibernate.tool.ant.HibernateToolTask"&lt;br /&gt;           classpathref="tools.classpath"/&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- Create runtime subdirectories --&gt;&lt;br /&gt;  &amp;lt;target name="prepare"&gt;&lt;br /&gt;    &amp;lt;mkdir dir="${class}"/&gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- Copy property files and O/R mappings needed at runtime --&gt;&lt;br /&gt;    &amp;lt;copy todir="${class}"&gt;&lt;br /&gt;      &amp;lt;fileset dir="${src}"&gt;&lt;br /&gt;        &amp;lt;include name="**/*.properties"/&gt;&lt;br /&gt;        &amp;lt;include name="**/*.cfg.xml"/&gt;&lt;br /&gt;      &amp;lt;/fileset&gt;&lt;br /&gt;    &amp;lt;/copy&gt;&lt;br /&gt;  &amp;lt;/target&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- Generate schemas for all mapping files --&gt;&lt;br /&gt;  &amp;lt;target name="schema" depends="prepare"&gt;&lt;br /&gt;    &amp;lt;htools destdir="${data}"&gt;&lt;br /&gt;      &amp;lt;classpath refid="tools.classpath"/&gt;&lt;br /&gt;      &amp;lt;configuration&lt;br /&gt;        configurationfile="${src}/hibernate.cfg.xml"/&gt;&lt;br /&gt;      &amp;lt;hbm2ddl drop="true" outputfilename="book.sql"/&gt;&lt;br /&gt;    &amp;lt;/htools&gt;&lt;br /&gt;  &amp;lt;/target&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- Compile java source code --&gt;&lt;br /&gt;  &amp;lt;target name="compile" depends="prepare"&gt;&lt;br /&gt;    &amp;lt;javac srcdir="${src}"&lt;br /&gt;           destdir="${class}"&lt;br /&gt;           debug="on"&lt;br /&gt;           optimize="off"&lt;br /&gt;           deprecation="on"&lt;br /&gt;           classpathref="project.classpath"/&gt;&lt;br /&gt;  &amp;lt;/target&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- Add a book (create and persist) --&gt;&lt;br /&gt;  &amp;lt;target name="addBooks" depends="compile"&gt;&lt;br /&gt;    &amp;lt;java classname="com.dougsparling.AddBook" &lt;br /&gt;             classpathref="project.classpath"/&gt;&lt;br /&gt;  &amp;lt;/target&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- Display persisted data --&gt;&lt;br /&gt;  &amp;lt;target name="listBooks" depends="compile"&gt;&lt;br /&gt;    &amp;lt;java classname="com.dougsparling.ListBooks" &lt;br /&gt;             classpathref="project.classpath"/&gt;&lt;br /&gt;  &amp;lt;/target&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/project&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;2) build.properties&lt;/h3&gt;&lt;br /&gt;This file is included in the build.xml file. build.properties contains paths to the installed libraries.&lt;br /&gt;&lt;br /&gt;Book/build.properties&lt;br /&gt;-----------------------------------------&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Path to the hibernate install directory&lt;br /&gt;hibernate.home=/usr/local/hibernate-3.2&lt;br /&gt;&lt;br /&gt;# Path to the hibernate-tools install directory&lt;br /&gt;hibernate.tools.home=/usr/local/HibernateTools&lt;br /&gt;&lt;br /&gt;# Path to hibernate-tools.jar relative to hibernate.tools.home&lt;br /&gt;hibernate.tools.path=&lt;br /&gt;/plugins/org.hibernate.eclipse_3.2.0.beta9a/lib/tools&lt;br /&gt;&lt;br /&gt;# Path to the HSQL DB install directory&lt;br /&gt;hsql.home=/usr/local/hsqldb&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;3) Hibernate configuration file&lt;/h3&gt;&lt;br /&gt;Database connection information mappings.&lt;br /&gt;&lt;br /&gt;Book/src/hibernate.cfg.xml&lt;br /&gt;--------------------------------&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;br /&gt;&amp;lt;!DOCTYPE hibernate-configuration PUBLIC&lt;br /&gt;  "-//Hibernate/Hibernate Configuration DTD//EN"&lt;br /&gt;  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&gt;&lt;br /&gt;&amp;lt;hibernate-configuration&gt;&lt;br /&gt;  &amp;lt;session-factory&gt;&lt;br /&gt;    &amp;lt;property name="hibernate.connection.url"&gt;&lt;br /&gt;        jdbc:hsqldb:file:data/book;shutdown=true&lt;br /&gt;    &amp;lt;/property&gt;&lt;br /&gt;    &amp;lt;property name="hibernate.connection.driver_class"&gt;&lt;br /&gt;      org.hsqldb.jdbcDriver&lt;br /&gt;    &amp;lt;/property&gt;&lt;br /&gt;    &amp;lt;property name="hibernate.connection.username"&gt;sa&amp;lt;/property&gt;&lt;br /&gt;    &amp;lt;property name="hibernate.connection.password"&gt;&amp;lt;/property&gt;&lt;br /&gt;    &amp;lt;property name="hibernate.connection.pool_size"&gt;0&amp;lt;/property&gt;&lt;br /&gt;    &amp;lt;property name="hibernate.dialect"&gt;&lt;br /&gt;      org.hibernate.dialect.HSQLDialect&lt;br /&gt;    &amp;lt;/property&gt;&lt;br /&gt;    &amp;lt;property name="hibernate.show_sql"&gt;false&amp;lt;/property&gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- mapping resources --&gt;&lt;br /&gt;    &amp;lt;mapping resource="com/dougsparling/Book.hbm.xml"/&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;/session-factory&gt;&lt;br /&gt;&amp;lt;/hibernate-configuration&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;4) Logging&lt;/h3&gt;&lt;br /&gt;Set up logging. You can use the file that comes in the etc directory of the HibernateTools in the unpacked archive file. &lt;br /&gt;&lt;br /&gt;Book/src/log4j.properties &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;5) Book class&lt;/h3&gt;&lt;br /&gt;POJO class to represent a book&lt;br /&gt;&lt;br /&gt;Book/src/com/dougsparling/Book.java&lt;br /&gt;-----------------------------------------&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package com.dougsparling;&lt;br /&gt;&lt;br /&gt;public class Book {&lt;br /&gt;  private int id;&lt;br /&gt;  private String title;&lt;br /&gt;&lt;br /&gt;  public Book(String title) {&lt;br /&gt;    this.title = title;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  Book() {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public int getId() {&lt;br /&gt;    return this.id;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setId(int id) {&lt;br /&gt;    this.id = id;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; public String getTitle() {&lt;br /&gt;    return this.title;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setTitle(String title) {&lt;br /&gt;    this.title = title;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;6) Object mapping for Book class&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Book/src/com/dougsparling/Book.hbm.xml&lt;br /&gt;-------------------------------------------&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&gt;&lt;br /&gt;&amp;lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"&lt;br /&gt;          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;hibernate-mapping&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;class name="com.dougsparling.Book" table="book"&gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;id name="id" type="int" column="id"&gt;&lt;br /&gt;      &amp;lt;generator class="native"/&gt;&lt;br /&gt;    &amp;lt;/id&gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;property name="title" type="string"/&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;/class&gt;&lt;br /&gt;&amp;lt;/hibernate-mapping&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;7) AddBook class&lt;/h3&gt;&lt;br /&gt;Code to add a book to database&lt;br /&gt;&lt;br /&gt;Book/src/com/dougsparling/AddBook.java&lt;br /&gt;--------------------------------------------&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package com.dougsparling;&lt;br /&gt;&lt;br /&gt;import org.hibernate.Session;&lt;br /&gt;import org.hibernate.SessionFactory;&lt;br /&gt;import org.hibernate.cfg.Configuration;&lt;br /&gt;&lt;br /&gt;import com.dougsparling.Book;&lt;br /&gt;&lt;br /&gt;public class AddBook {&lt;br /&gt;  public static void main(String[] args) {&lt;br /&gt;&lt;br /&gt;    String title = "A Book";&lt;br /&gt;&lt;br /&gt;    SessionFactory factory =&lt;br /&gt;      new Configuration().configure().buildSessionFactory();&lt;br /&gt;    Session session = factory.openSession();&lt;br /&gt;    session.beginTransaction();&lt;br /&gt;&lt;br /&gt;    Book book = new Book(title);&lt;br /&gt;&lt;br /&gt;    session.save(book);&lt;br /&gt;    session.getTransaction().commit();&lt;br /&gt;    session.close();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;8) ListBooks class&lt;/h3&gt;&lt;br /&gt;Code to read books from database&lt;br /&gt;&lt;br /&gt;Book/src/com/dougsparling/ListBooks.java&lt;br /&gt;----------------------------------------------&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package com.dougsparling;&lt;br /&gt;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import org.hibernate.Session;&lt;br /&gt;import org.hibernate.SessionFactory;&lt;br /&gt;import org.hibernate.cfg.Configuration;&lt;br /&gt;&lt;br /&gt;import com.dougsparling.Book;&lt;br /&gt;&lt;br /&gt;public class ListBooks {&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    SessionFactory factory =&lt;br /&gt;      new Configuration().configure().buildSessionFactory();&lt;br /&gt;    Session session = factory.openSession();&lt;br /&gt;&lt;br /&gt;    List books = session.createQuery("from Book").list();&lt;br /&gt;    System.out.println("Found " + books.size() + " books(s):");&lt;br /&gt;&lt;br /&gt;    Iterator i = books.iterator();&lt;br /&gt;    while(i.hasNext()) {&lt;br /&gt;      Book book = (Book)i.next();&lt;br /&gt;      System.out.println(book.getTitle());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    session.close();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;9) Ant build&lt;/h3&gt;&lt;br /&gt;At this point it's time to run Ant against the build.xml file.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93/Book$ ant schema&lt;br /&gt;kl93@oiche:/home/kl93/Book$ ant addBooks&lt;br /&gt;kl93@oiche:/home/kl93/Book$ ant listBooks&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3643639393714331361?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3643639393714331361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3643639393714331361'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/04/youll-need-following-to-run-this.html' title='Hibernate 3 Tutorial'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-764283959027750837</id><published>2007-04-28T05:58:00.000-07:00</published><updated>2007-06-01T14:38:36.016-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Perl - DateTime</title><content type='html'>Our servers were recently switched from using local time to UTC. This had an affect on our content, causing it to show several hours early since content availability is based on local time. In the past we had relied on Date::Calc on other various date manipulations using epoch seconds. Having recently worked on two projects with Catalyst, I had become familiar with the Perl module DateTime. Not only was converting UTC to local time a breeze, DateTime required far fewer lines of code, not to mention the ease and readability of date manipulations.&lt;br /&gt;&lt;br /&gt;The standard Unix date command shows the server is on UTC:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche/home/kl93:$ date&lt;br /&gt;Sat Apr 28 13:10:15 UTC 2007&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or in Perl:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;my $date = localtime(time);&lt;br /&gt;print "$date\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;returns&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2007-04-28T13:16:29&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, using DateTime module:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt = DateTime-&gt;now();&lt;br /&gt;print $dt-&gt;datetime(), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime1.pl&lt;br /&gt;2007-04-28T13:23:15&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To get local time, you can either set the desired time zone when you create the DateTime object:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt = DateTime-&gt;now(time_zone =&gt; 'America/Chicago');&lt;br /&gt;print $dt-&gt;datetime(), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or set it after you've created the object:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt = DateTime-&gt;now();&lt;br /&gt;$dt-&gt;set_time_zone('America/Chicago');&lt;br /&gt;print $dt-&gt;datetime(), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we have local time for US Central:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime2.pl&lt;br /&gt;2007-04-28T08:29:56&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Using a named time zone like 'America/Chicago' is nice, as it will calculate DST changes. However, it's not recommended for dates far in the future (read the Pod).&lt;br /&gt;&lt;br /&gt;You can also use "today" in place of "now," which will only initialize the date, not the time:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt1 = DateTime-&gt;today();&lt;br /&gt;print "dt1: ", $dt1-&gt;datetime(), "\n";&lt;br /&gt;my $dt2 = DateTime-&gt;now();&lt;br /&gt;print "dt2: ", $dt2-&gt;datetime(), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime3.pl&lt;br /&gt;dt1: 2007-04-28T00:00:00&lt;br /&gt;dt2: 2007-04-28T17:53:32&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can also initialize the DateTime object to any valid date by passing passing parameters to the constructor:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt = DateTime-&gt;new( year   =&gt; 2001,&lt;br /&gt;                        month  =&gt; 4,&lt;br /&gt;                        day    =&gt; 23,&lt;br /&gt;                        hour   =&gt; 10,&lt;br /&gt;                        minute =&gt; 45,&lt;br /&gt;                        second =&gt; 30,&lt;br /&gt;                        time_zone  =&gt; 'America/Chicago',&lt;br /&gt;                      );&lt;br /&gt;print $dt-&gt;datetime(), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can see that the date has been initialized to April 23, 2005 at 10:45:30 (am):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime4.pl&lt;br /&gt;2001-04-23T10:45:30&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There are several accessors - a quick perusal of the Pod shows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$dt-&gt;year;&lt;br /&gt;$dt-&gt;month;          # 1-12 - also mon&lt;br /&gt;$dt-&gt;day;            # 1-31 - also day_of_month, mday&lt;br /&gt;$dt-&gt;day_of_week;    # 1-7 (Monday is 1) - also dow, wday&lt;br /&gt;$dt-&gt;hour;           # 0-23&lt;br /&gt;$dt-&gt;minute;         # 0-59 - also min&lt;br /&gt;$dt-&gt;second;         # 0-61 (leap seconds!) - also sec&lt;br /&gt;$dt-&gt;day_of_year;    # 1-366 (leap years) - also doy&lt;br /&gt;$dt-&gt;day_of_quarter; # 1.. - also doq&lt;br /&gt;$dt-&gt;quarter;        # 1-4&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I won't cover everything, that's what the Pod is for, but a few handy features include easy date formating and date calculations.&lt;br /&gt;&lt;br /&gt;A few formatting built-ins:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$dt-&gt;ymd;      # 2007-04-28&lt;br /&gt;$dt-&gt;ymd('/'); # 2007/04/28&lt;br /&gt;$dt-&gt;ymd('')   # 20070428&lt;br /&gt;&lt;br /&gt;$dt-&gt;mdy;      # 04-28-2007&lt;br /&gt;$dt-&gt;mdy('/'); # 04/28/2007&lt;br /&gt;$dt-&gt;mdy('');  # 04282007&lt;br /&gt;&lt;br /&gt;$dt-&gt;dmy;      # 28-04-200&lt;br /&gt;$dt-&gt;dmy('/'); # 28/04/2007&lt;br /&gt;$dt-&gt;dmy('');  # 28042007&lt;br /&gt;&lt;br /&gt;$dt-&gt;hms;      # 12:33:45&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And if you need it, you can use 'strftime' for further formatting:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$dt-&gt;strftime("%A, %B %d, %Y"); # Saturday, April 28, 2007&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A few date manipulations:&lt;br /&gt;&lt;br /&gt;You can update an existing DateTime object to another date:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt = DateTime-&gt;new( year   =&gt; 2001,&lt;br /&gt;                        month  =&gt; 4,&lt;br /&gt;                        day    =&gt; 23,&lt;br /&gt;                        hour   =&gt; 10,&lt;br /&gt;                        time_zone  =&gt; 'America/Chicago',&lt;br /&gt;                      );&lt;br /&gt;print $dt-&gt;ymd, "\n";&lt;br /&gt;&lt;br /&gt;$dt-&gt;set( year =&gt; 2007 );&lt;br /&gt;$dt-&gt;set( month =&gt; 11 );&lt;br /&gt;$dt-&gt;set( day =&gt; 30 );&lt;br /&gt;print $dt-&gt;ymd, "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can see that the date was changed from 2001-04-23 to 2007-11-30:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime5.pl&lt;br /&gt;2001-04-23&lt;br /&gt;2007-11-30&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can find x number of years, months, days from a date by using "add" and "subtract" on your DateTime object.&lt;br /&gt;&lt;br /&gt;To find one month from today:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt = DateTime-&gt;now();&lt;br /&gt;print $dt-&gt;datetime(), "\n";&lt;br /&gt;print $dt-&gt;add(months =&gt; 1), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime6.pl&lt;br /&gt;2007-04-28T14:05:35&lt;br /&gt;2007-05-28T14:05:35&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Or one month previous:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt = DateTime-&gt;now();&lt;br /&gt;print $dt-&gt;datetime(), "\n";&lt;br /&gt;print $dt-&gt;subtract(months =&gt; 1), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime7.pl&lt;br /&gt;2007-04-28T14:07:42&lt;br /&gt;2007-03-28T14:07:42&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;One note - DateTime objects are hash references, so if you want to keep your original DateTime object unchanged, you need to clone your object and then use "add" or "subtract" to get the calculated date.&lt;br /&gt;&lt;br /&gt;Here we simply copy $dt1 and update $dt2.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt1 = DateTime-&gt;now();&lt;br /&gt;print "dt1: ", $dt1-&gt;datetime(), "\n";&lt;br /&gt;my $dt2 = $dt1;&lt;br /&gt;$dt2-&gt;add(months =&gt; 1), "\n";&lt;br /&gt;print "dt2: ", $dt2-&gt;datetime(), "\n";&lt;br /&gt;print "dt1: ", $dt1-&gt;datetime(), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that once $dt2 is modified, $dt1 is modified as well (they both "point" to the same DateTime object:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime8.pl&lt;br /&gt;dt1: 2007-04-28T17:19:46&lt;br /&gt;dt2: 2007-05-28T17:19:46&lt;br /&gt;dt1: 2007-05-28T17:19:46&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To prevent this, use the clone method to create a totally new DateTime object:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use DateTime;&lt;br /&gt;my $dt1 = DateTime-&gt;now();&lt;br /&gt;print "dt1: $dt1-&gt;datetime(), "\n";&lt;br /&gt;my $dt2 = $dt1-&gt;clone;&lt;br /&gt;$dt2-&gt;add(months =&gt; 1), "\n";&lt;br /&gt;print "dt2: ", $dt2-&gt;datetime(), "\n";&lt;br /&gt;print "dt1: ", $dt1-&gt;datetime(), "\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now $dt1 remains unchanged:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kl93@oiche:/home/kl93$ perl datetime9.pl&lt;br /&gt;dt1: 2007-04-28T17:23:39&lt;br /&gt;dt2: 2007-05-28T17:23:39&lt;br /&gt;dt1: 2007-04-28T17:23:39&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Find out more about the DateTime module at the &lt;a href="http://datetime.perl.org/" "target=_blank"&gt;Perl DateTime Wiki&lt;/a&gt; or at &lt;a href="http://search.cpan.org/search?mode=module&amp;query=DateTime" "target=_blank"&gt;CPAN&lt;/a&gt; (written by &lt;a href="http://search.cpan.org/~drolsky/" "target=_blank"&gt;Dave  Rolsky&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-764283959027750837?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/764283959027750837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=764283959027750837' title='64 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/764283959027750837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/764283959027750837'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/04/perl-datetime.html' title='Perl - DateTime'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>64</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-7046836904188552861</id><published>2007-04-21T19:49:00.000-07:00</published><updated>2007-05-02T12:07:27.951-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Java/Perl - Command-line arguments</title><content type='html'>Command-line arguments are passed to a Perl program in the array &lt;code&gt;@ARGV&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;my $num_args = @ARGV;&lt;br /&gt;print "Length of \@ARGV array: $num_args\n";&lt;br /&gt;for(my $i = 0; $i %lt; $num_args; $i++) {&lt;br /&gt;  print "Argument $i = |$ARGV[$i]|\n";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;# another way to loop through arguments&lt;br /&gt;my $count = 0;&lt;br /&gt;for my $arg(@ARGV) {&lt;br /&gt;  print "Argument $count = |$arg|\n";&lt;br /&gt;  $count++;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[kl93@localhost ]$ perl args.pl Eeyore Piglet "Pooh Bear"&lt;br /&gt;Argument 0 = |Eeyore|&lt;br /&gt;Argument 1 = |Piglet|&lt;br /&gt;Argument 2 = |Pooh Bear|&lt;br /&gt;Length of @ARGV array: 3&lt;br /&gt;Argument 0 = |Eeyore|&lt;br /&gt;Argument 1 = |Piglet|&lt;br /&gt;Argument 2 = |Pooh Bear|&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Command-line arguments are passed to &lt;code&gt;main&lt;/code&gt; method in a Java program. The arguments are passed as a &lt;code&gt;String&lt;/code&gt; array called &lt;code&gt;args&lt;/code&gt; (or whatever you may choose to call it).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class Args&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    System.out.println("Length of args array: " &lt;br /&gt;                       + args.length);&lt;br /&gt;&lt;br /&gt;    for(int i = 0; i &amp;lt; args.length; i++)&lt;br /&gt;    {&lt;br /&gt;      System.out.println("Argument " + i + " = |" + args[i] + "|");&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output: &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[kl93@localhost ]$ java Args Eeyore Piglet "Pooh Bear"&lt;br /&gt;Length of args array: 3&lt;br /&gt;Argument 0 = |Eeyore|&lt;br /&gt;Argument 1 = |Piglet|&lt;br /&gt;Argument 2 = |Pooh Bear|&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-7046836904188552861?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/7046836904188552861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=7046836904188552861' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/7046836904188552861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/7046836904188552861'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/04/command-line-arguments-are-passed-to.html' title='Java/Perl - Command-line arguments'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-2727041340447845777</id><published>2007-04-21T19:47:00.001-07:00</published><updated>2007-04-28T05:57:20.419-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Java/Perl - String comparison (eq)</title><content type='html'>In Perl, comparison operators are used when comparing either numbers or strings. For comparing strings, the comparison operator for equality is 'eq.' Unlike Java, Perl doesn't have a String class as Perl is a "typeless" language. However, Perl scalar variables can contain numbers or strings, so there isn't much difference between 999 (number) or '999' (string). So comparing strings in Perl for equality is fairly straight forward.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;my $string1 = 'Eeyore';&lt;br /&gt;my $string2 = 'Eeyore';&lt;br /&gt;&lt;br /&gt;if($string1 eq $string2) {&lt;br /&gt;  print "True\n";&lt;br /&gt;} else {&lt;br /&gt;  print "False\n";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The output is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;True&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In Java, strings are objects. In most cases when an equality comparison is made between two strings, it is the value of the two strings that we want to compare. To check if two strings have the same value, the 'equals' method is used. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class Equals&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    String string1 = "Eeyore";&lt;br /&gt;    String string2 = "Eeyore";&lt;br /&gt;    if(string1.equals(string2))&lt;br /&gt;      System.out.println("True");&lt;br /&gt;    else&lt;br /&gt;      System.out.println("False");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The output is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;True&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Note that with Java, there are two ways to create a new string.&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;String string1 = "Eeyore";&lt;/li&gt; // informal method&lt;br /&gt;&lt;li&gt;String string2 = new String("Eeyore");&lt;/li&gt; // formal method&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;There is a subtle difference. With the the informal method, String objects are created and the JVM places them in the "literal pool," an area in JVM memory that allows shared access to String objects. In this case, before a new String object is created, the literal pool is checked to see if an identical string already exists, and if so it is reused. If not, a new String is created and added to the literal pool. That way, if several strings are created with the same value, they all point to the same String object.&lt;br /&gt;&lt;br /&gt;With the formal method, a new String object is created even if the same string already exists. In this case the String object is placed in the JVM general memory.&lt;br /&gt;&lt;br /&gt;To check if two Strings point to the same object, the '==' operator is used.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class Equals2&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    String string1 = "Eeyore";&lt;br /&gt;    String string2 = "Eeyore";&lt;br /&gt;    String string3 = new String("Eeyore");&lt;br /&gt;&lt;br /&gt;    if(string1.equals(string2))&lt;br /&gt;      System.out.println("True");&lt;br /&gt;    else&lt;br /&gt;      System.out.println("False");&lt;br /&gt;&lt;br /&gt;    if(string1.equals(string3))&lt;br /&gt;      System.out.println("True");&lt;br /&gt;    else&lt;br /&gt;      System.out.println("False");&lt;br /&gt;&lt;br /&gt;    if(string1 == string2)&lt;br /&gt;      System.out.println("True");&lt;br /&gt;    else&lt;br /&gt;      System.out.println("False");&lt;br /&gt;&lt;br /&gt;    if(string1 == string3)&lt;br /&gt;      System.out.println("True");&lt;br /&gt;    else&lt;br /&gt;      System.out.println("False");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The output is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;True&lt;br /&gt;True&lt;br /&gt;True&lt;br /&gt;False&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This shows that string1 and string2 have the same value and point to the same String object. This also shows that while string1 and string3 have the same value, they point to different String objects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-2727041340447845777?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/2727041340447845777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=2727041340447845777' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2727041340447845777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2727041340447845777'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/04/in-perl-comparison-operators-are-used.html' title='Java/Perl - String comparison (eq)'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-2552356363343242171</id><published>2007-04-21T19:45:00.001-07:00</published><updated>2007-04-28T05:57:32.410-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Java/Perl - split</title><content type='html'>split breaks up (or splits) a string into "tokens" or substrings according to a separator. split uses a regular expression as the separator. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;my @fields = split /:/, "jim:bob:frank:steve";&lt;br /&gt;foreach my $field (@fields) {&lt;br /&gt;  print "$field\n";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;my $string = "one two  three   four\tfive";&lt;br /&gt;my @array = split /\s+/, $string;&lt;br /&gt;foreach my $el(@array) {&lt;br /&gt;  print "$el\n";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;jim&lt;br /&gt;bob&lt;br /&gt;frank&lt;br /&gt;steve&lt;br /&gt;one &lt;br /&gt;two &lt;br /&gt;three&lt;br /&gt;four &lt;br /&gt;five&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Java 1.4 added the split() method to the String class.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class Split&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    String string1 = "jim:bob:frank:steve";&lt;br /&gt;    String[] names = string1.split(":");&lt;br /&gt;    for(int i=0; i&amp;lt;names.length; i++)&lt;br /&gt;      System.out.println(names[i]);&lt;br /&gt;&lt;br /&gt;    String string2 = "one two  three   four\tfive";&lt;br /&gt;    String[] words = string2.split("\\s+");&lt;br /&gt;    for(int i=0; i&amp;lt;words.length; i++)&lt;br /&gt;      System.out.println(words[i]);&lt;br /&gt;  } &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It is also possible to use the java.util.StringTokenizer to break a string into tokens.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import java.util.StringTokenizer;&lt;br /&gt;&lt;br /&gt;public class StringToke&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    String string1 = "jim:bob:frank:steve";&lt;br /&gt;    StringTokenizer st1 = new StringTokenizer(string1,":");&lt;br /&gt;    while(st1.hasMoreTokens()) &lt;br /&gt;      System.out.println(st1.nextToken());&lt;br /&gt;   &lt;br /&gt;    String string2 = "one two  three   four\tfive";&lt;br /&gt;    StringTokenizer st2 = new StringTokenizer(string2);&lt;br /&gt;    while(st2.hasMoreTokens()) &lt;br /&gt;      System.out.println(st2.nextToken());&lt;br /&gt;  } &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;jim&lt;br /&gt;bob&lt;br /&gt;frank&lt;br /&gt;steve&lt;br /&gt;one&lt;br /&gt;two&lt;br /&gt;three&lt;br /&gt;four&lt;br /&gt;five&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;If no regular expression pattern is used, split defaults to using white space as the separator. (both in Perl and Java)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-2552356363343242171?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kl93.blogspot.com/feeds/2552356363343242171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5575882483986490924&amp;postID=2552356363343242171' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2552356363343242171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/2552356363343242171'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/04/javaperl-split.html' title='Java/Perl - split'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5575882483986490924.post-3697840293543621814</id><published>2007-04-21T19:40:00.000-07:00</published><updated>2007-06-04T13:55:38.837-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Java/Perl - Directory handles</title><content type='html'>With Perl, one way to get a list of names in a given directory is to use a directory handle. On my Fedora box, Perl displays "." and ".." while Java does not.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;my $dir = '/home/kl93';&lt;br /&gt;opendir DH, $dir or die "Cannot open $dir: $!";&lt;br /&gt;foreach my  $file (readdir DH) {&lt;br /&gt;  next if $file =~ /^\.\.?$/;     # skip . and ..&lt;br /&gt;  print "$file\n";&lt;br /&gt;}&lt;br /&gt;close DH;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import java.io.*;&lt;br /&gt;&lt;br /&gt;public class ReadDir&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args) throws Exception&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;    File file = new File("/home/kl93");&lt;br /&gt;&lt;br /&gt;    if( !file.exists() || !file.canRead() )&lt;br /&gt;    {&lt;br /&gt;      System.out.println("Can't read " + file);&lt;br /&gt;      return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if( file.isDirectory() ) {&lt;br /&gt;      String[] files = file.list();&lt;br /&gt;      for(int i=0; i&amp;lt;files.length; i++)&lt;br /&gt;        System.out.println(files[i]);&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;      System.out.println(file + " is not a directory");&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you want to display filenames based on some sort of criteria - like all files with the .java extension for example - then it's often easiest to use a regular expression.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;my $dir = '/home/kl93';&lt;br /&gt;opendir DH, $dir or die "Cannot open $dir: $!";&lt;br /&gt;foreach my  $file (readdir DH) {&lt;br /&gt;  next unless $file =~ /\.java$/;&lt;br /&gt;  print "$file\n";&lt;br /&gt;}&lt;br /&gt;close DH;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import java.io.*;&lt;br /&gt;import java.util.regex.*;&lt;br /&gt;&lt;br /&gt;public class ReadDir2&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args) throws Exception&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;    File file = new File("/home/kl93");&lt;br /&gt;&lt;br /&gt;    if( !file.exists() || !file.canRead() )&lt;br /&gt;    {&lt;br /&gt;      System.out.println("Can't read " + file);&lt;br /&gt;      return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if( file.isDirectory() ) {&lt;br /&gt;      String[] files = file.list();&lt;br /&gt;      for(int i=0; i&amp;lt;files.length; i++)&lt;br /&gt;      {&lt;br /&gt;        if(files[i].matches("^.*\\.java$"))&lt;br /&gt;          System.out.println(files[i]);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;      System.out.println(file + " is not a directory");&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Or&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import java.io.*;&lt;br /&gt;import java.util.regex.*;&lt;br /&gt;&lt;br /&gt;public class ReadDir3&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args) throws Exception&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;    File file = new File("/home/kl93");&lt;br /&gt;&lt;br /&gt;    if( !file.exists() || !file.canRead() )&lt;br /&gt;    {&lt;br /&gt;      System.out.println("Can't read " + file);&lt;br /&gt;      return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if( file.isDirectory() ) {&lt;br /&gt;      String[] files = file.list();&lt;br /&gt;      Pattern pattern = Pattern.compile("\\.java$");&lt;br /&gt;      Matcher matcher;&lt;br /&gt;      for(int i=0; i&amp;lt;files.length; i++)&lt;br /&gt;      {&lt;br /&gt;        matcher = pattern.matcher(files[i]);&lt;br /&gt;        if(matcher.find())&lt;br /&gt;          System.out.println(files[i]);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;      System.out.println(file + " is not a directory");&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Sort (ascending)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;my $dir = '/home/kl93';&lt;br /&gt;opendir DH, $dir or die "Cannot open $dir: $!";&lt;br /&gt;foreach my $file (sort readdir(DH)) {&lt;br /&gt;  print "$file\n";&lt;br /&gt;}&lt;br /&gt;close DH;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Sort desending&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;my $dir = '/home/kl93';&lt;br /&gt;opendir DH, $dir or die "Cannot open $dir: $!";&lt;br /&gt;foreach my $file (reverse(sort readdir(DH))) {&lt;br /&gt;  print "$file\n";&lt;br /&gt;}&lt;br /&gt;close DH;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5575882483986490924-3697840293543621814?l=kl93.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3697840293543621814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5575882483986490924/posts/default/3697840293543621814'/><link rel='alternate' type='text/html' href='http://kl93.blogspot.com/2007/04/javaperl-directory-handles.html' title='Java/Perl - Directory handles'/><author><name>Doug Sparling</name><uri>http://www.blogger.com/profile/10217915963486446068</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YFrXdAA3hPI/ShXsTVfw4sI/AAAAAAAAAJk/M1ZgQpJTv3g/S220/dss20081025-01.jpg'/></author></entry></feed>
