<?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-20834841</id><updated>2011-07-30T14:06:45.779-05:00</updated><category term='Ruby Rails VM PostgreSQL'/><category term='2006'/><category term='Ruby'/><category term='St. Louis'/><category term='Rails'/><title type='text'>Green Programming</title><subtitle type='html'>Environmentally safe code</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-20834841.post-146044995399848403</id><published>2009-10-17T18:11:00.010-05:00</published><updated>2009-12-27T12:58:45.950-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby Rails VM PostgreSQL'/><title type='text'>LAPR - RoR on Hardy VM w/Postgres</title><content type='html'>Well, if there is LAMP, LAPP and LAMR. What about LAPR - Linux, Apache, PostgreSQL and Ruby on Rails? My friend Ben said he tried out Ruby (he's a Python guy), but it didn't support Postgres very well. I wanted to see for myself, (having just arrived from Missouri- the ShowMe state). First I tried installing Postgres on an existing RoR VMWare appliance, but for some reason, could not get Ruby talking to the gem. &lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;Next I tried the opposite approach. Converting an existing LAPP iso into LAPR. I am more familiar with installing Rails on Ubuntu than installing PG. That went much smoother, after, of course gnashing my teeth on the previous install.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Turnkey[1] makes some nice appliances for testing things out and for deployments. They have a Rails stack, a LAMP and the aforementioned LAPP stack. (They also have a Django Python one I'm dying to try out).  They are based on Ubuntu and seem somewhat affiliated with them. They seem to all use Hardy because that is the latest LTS release. There is also a way to deploy your app in the 'cloud". For some appliance vendors this means an Amazon EC2 instance. For Turnkey, they are using VPS.NET (see the site for details).&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What I like about Turnkey appliances is they are distributed as (Live/Installable) .isos and not pre-built vdks or other VM images. They will work anywhere even burned to a CD and booted from there. They also offer a Core appliance where you can build your own and utilize the web based interface they've built. &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once installed or booted from the Live CD, you point your web browser at the provided IP address or SSH into it. (using the root password you set up during the install). From there you apt-get install away! Now, Turnkey keeps their appliances up-to date daily with security updates, but not with application updates. I had to apt-get update and then apt-get upgrade.  On my LAPP instance, this seemed to update PostrgeSQL to 8.3.8. &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As I am wont to do, I installed Ruby and Rails using the tried and true method outlined on the Download page for Rails [2]. This involves compiling from source. To do this on Ubunt, see my earlier Post: Ruby with readline on Ubuntu [3]. &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once you have Rails installed, you need to install the sqlite3-ruby gem before testing it out, as Rails is configured to use Sqlite3 out of the box. But to install it, you have to first install Sqlite3 and its development library.&lt;br /&gt;&lt;/div&gt;&lt;div class="code"&gt;&lt;pre&gt;sudo apt-get install sqlite3 libsqlite3-dev&lt;br /&gt;sudo gem install sqlite3-rub&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;At this point, create a Rails app and start the Webrick server. Point your browser at the ip address&lt;ip&gt;:3000 and you should see the familiar Rails Welcome page. Clicking on "About your application environment" should reveal all the various gem versions including the DB adapter:Sqlite3.&lt;/ip&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next, set up a model using the scaffold generator:&lt;br /&gt;&lt;/div&gt;&lt;div class="code"&gt;&lt;pre&gt;./script/generate scaffold Post name:sting comment:text&lt;br /&gt;rake db:migrate&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Going to  ip address&lt;ip&gt;:3000/posts should show the empty posts model you just created. Now, on to installing Postgres support:&lt;/ip&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;pre&gt;sudo apt-get install libpq-dev&lt;br /&gt;sudo gem install pg&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;The correct gem to install is 'pg', no matter what you may have heard. Next setup config/database.yml:&lt;br /&gt;&lt;div class="code"&gt;&lt;pre&gt;production:&lt;br /&gt;adapter: postgresql&lt;br /&gt;database: app&lt;br /&gt;username: postgres&lt;br /&gt;encoding: utf8&lt;br /&gt;pool: 5&lt;br /&gt;timeout: 5000&lt;br /&gt;&lt;/pre&gt;Turnkey LAPP ships with the postgres user having no password. Also, Postgres defaults to US-ASCII encoding, but Ruby expects UTF-8. (Ruby 1.9 lets you specify different encodings). &lt;br /&gt;&lt;/div&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="code"&gt;Finally, do another:&lt;br /&gt;&lt;/div&gt;&lt;div class="code"&gt;&lt;pre&gt;rake RAILS_ENV=production db:create db:migrate&lt;br /&gt;# close and restart the server in production mode:&lt;br /&gt;./script/server -e production&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Now, enter any posts in your web browser, and they should show up in the phpPgAdmin screen. &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You have successfully created a LAPR appliance. Go collect your fame and fortune!&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[1] http://www.turnkeylinux.org/&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[2] http://rubyonrails.org/download&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[3] http://greenprogrammer.blogspot.com/2006/05/ruby-wreadline-on-ubuntu.html&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-146044995399848403?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/146044995399848403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/146044995399848403'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2009/10/lapr-ror-on-hardy-vm-wpostgres.html' title='LAPR - RoR on Hardy VM w/Postgres'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-6321650143590710778</id><published>2006-12-30T11:49:00.000-06:00</published><updated>2007-01-02T17:58:56.626-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='2006'/><category scheme='http://www.blogger.com/atom/ns#' term='St. Louis'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Saint Louis: The Pursuit of Rubyness ('06)</title><content type='html'>Well, this has certainly been a breakout year for Ruby in the St. Louis, Missouri area. Our little Ruby brigade (Stlruby.org[1]) saw its attendance mushroom from an average 7-8/meeting to around 20. So much so that we are seeking a larger space to hold meetings. We have been thankful to Mark Volkman and the staff at OCI [3] for sponsoring our group and providing a place to meet since our second meeting. Thanks Mark and everyone at OCI.&lt;br /&gt;&lt;br /&gt;Curt Hibbs kicked off our first meeting at a dinner with Dave Thomas at the Gateway Software Symposium (the "No Fluff, Just Stuff tour,") in March of 2005. I wish I could have been there, but we reprised the dinner this year in March. We got to meet Dave, Bruce Tate, Justin Gehtland, Neil Ford and some other NFJS'ers. These guys are all very young, super brainy and quite funny. I had a blast at the dinner. Pics here[4]&lt;br /&gt;&lt;br /&gt;Curt also presented this year at RailsConf in Chicago, a talk titled "Inside Instant Rails," about his ubiquitous InstantRails project for Windows.  Curt hasn't sat on his laurels for both the InstantRails and One-Click Ruby projects for Windows. 2006 saw a new book co-authored by Bruce Tate and Curt: Up and Running Ruby on Rails. [5] He also contributed to Ajax Hacks by Bruce Perry [6]. His One-Click Ruby project hit 1 million downloads in November. It is always near the top of the most active projects on Rubyforge. Sliiiiiick!&lt;br /&gt;&lt;br /&gt;Our numbers may have grown, but the reason might not be solely due to the explosion of interest in Rails. Occasionally, we've asked our membership what they are doing with Ruby and the answer seems more or less split 50-50 between Ruby and Rails work/interests. St. Louis has a fairly large number of web development organizations and a lot of enterprise shops in the biotech, aerospace and financial industries. Ruby is beginning to make inroads in Java shops and even a few Microsoft shops (of which there are a lot in this area.) Mark has even used Ruby at Scott Air Force Base.&lt;br /&gt;&lt;br /&gt;Speaking of Mark and NFJS tour, Mark gave a presentation titled "Ruby Tools" this year. Mark's talks are always well done and very interesting even if you've never heard of the subject. I remember his Distributed Ruby presentation (when we could still all fit in OCI's conference room,) with great appreciation. I went home and built a Rails Wiki using no DB, just the DRb stuff. Mark will return with "Ruby Plays Well With Others" at the 2007 Gateway Software Symposium. The talk will cover JRuby and writing C extensions. A few people from our group attended the talk by Charles Nutter on JRuby at the Gateway Java group. Ruby and Java are certainly two great tastes that taste great together!&lt;br /&gt;&lt;span class="q"&gt;&lt;br /&gt;Mark and Rob Smith have taught various Ruby and Rails classes at OCI in 2006 with more to come in 2007. Ruby training has seen its biggest increase in 2006. The interest has led two of our members, Mike Sullivan and  &lt;/span&gt;&lt;span style="font-weight: normal;" class="lg"&gt;Jeff Barczewski&lt;/span&gt; to form a new training consultancy (Inspired Horizons [7] specializing in Ruby and Rails training. It kicks off in 2007, registration is now open for the first workshops which will cover enterprise stuff with Rails and JRuby. (There is that Java thing again.)&lt;br /&gt;&lt;br /&gt;Our membership sure gets around. In addition to Curt, Jeff, Mike and Kyle Cordes attended the RailsConf in Chicago. (I am counting Kyle as a member and sponsor at-large. He currently hosts our web site, and promotes Ruby in his Agile talks. Can't wait for your Lua Users Group to start up, Kyle!) Around town, Curt, Mark, Rob, Jeff and I have given talks to various other users groups. Besides Stlruby, we have presented at St. L Linux (stllug), StLUnix (sluug) St. Charles LUG (stclug) St. Louis Web Developer's (stlweb) and the St. Louis XP users group (xpstl) Several of them and other members also taught at the all day St. Louis Code Camp.[8] David Holsclaw gave a presentation on RoR and Jeff taught a class on Extending Rails featuring MasterView (more on that below.) Cory Foy (a member at-large in outstate Missouri,) taught a program on Ruby for C#/.Net developers comparing the languages and Rails and ASP.Net. I am sure there will be more of this in 2007. Stay tuned.&lt;br /&gt;&lt;br /&gt;Speaking of Jeff, you may not be aware of his excellent Rails project MasterView  MV is an attribute language for Rails. You can use WYSIWYG editors like DreamWeaver to edit your views as regular .html files and put attributes on tags like a, input and select. MasterView will render them as ERb in .rhtml files on the fly. &lt;span class="q"&gt;2006 saw the release of version 0.3 which featured a new DSL for writing your own customized attributes. Sweet!&lt;br /&gt;&lt;br /&gt;Sean Carley has also been very active this year in Ruby projects. He contributed the cat2rb quiz to the weekly Ruby Quiz [9] He also founded the weekly hacking night in St. Louis. Attendance was low, so it is currently on hiatus.  There are a lot of monthly IT related events in St. Louis, so much so that nearly every weeknight (and quite a few weekends as well) can entertain us. Balancing that with work and family can be quite tough. Sean has contributed to ruby projects like ParseTree, checkr, and Zentest. He has also been involved in many book and other writing projects. Be sure to check out his blog [10]&lt;br /&gt;&lt;br /&gt;Quite a few of us are active in the blogosphere (oh how I loath that particular term. Forgive me.) Besides Sean's check out Curt's writing on O'Reilly's Ruby web log. [11] Curt also has his own Blog featuring a lot of Ruby wisdom [12] Also check out Pat Eyler's (a member on our mailing list, but lives in Utah,) blog [13] Pat also writes for the &lt;/span&gt;&lt;span class="q"&gt;O'Reilly Ruby blog. Kyle and Cory also have blogs. They are at [14,15] respectively  Yippee for self-named blogs!&lt;br /&gt;&lt;br /&gt;Some of our members have taken what they have learned and applied it to actual stuff. &lt;/span&gt;Steve Molitor&lt;span id="_user_hohlen@yahoo.com" style="color: rgb(91, 16, 148);"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;and John Hohlen have developed a fantasy golf site using Ruby on Rails. It is just getting off the ground, but they hope to grow the league this year. Check it out at  [17]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="q"&gt;&lt;br /&gt;What about yours truly? Well, I have given 4 presentations on Ruby and Rails at various users groups as I mentioned before. I am presently involved as a partner in a full time Rails consultancy (WDT Solutions [16]). We just finished a rather large Rails+Masterview commercial project for a company in the health care field. I contributed one bug to RSpec and a number of suggestions and feedback to Jeff and Deb on the Masterview team.&lt;br /&gt;&lt;br /&gt;Our group has grown so much this past year, that we have decided to actually use a bit of organization. To that end we have formed a steering committee. We meet for about an hour at Friday's before the main meeting. Our first accomplishment is to lay out the presentations for the first few months of 2007. We also migrated the mailing list from Yahoo Groups to Google Groups, which has a much nicer management and user interface.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Well, I am sure I've missed something (or many somethings.) If I didn't cover your book, project, presentation in 2006, please email me and I'll incorporate it.  That's it for ruby in St. Louis in 2006. 2007 is shaping up to be another fantastic year in the wide world of Ruby. Prognostication is not usually my forte, but if I had to guess at happenings in '07, I'd say that Curt will become even more famous. Dave and Bruce, et. al. will show up at the NFJS tour and have food with us. More projects will be contributed to, more blog posts written, more presentations will be given, more conferences will be attended. Outside of Japan, Seattle, Portland and Utah, St. Louis will be the place to be for all things Ruby.&lt;br /&gt;&lt;br /&gt;Have a Happy New Year!&lt;br /&gt;&lt;span class="q"&gt;&lt;br /&gt;Ed&lt;br /&gt;[1] StlRuby &lt;a href="http://stlruby.org/ruwiki/ruwiki.cgi/"&gt;http://stlruby.org/ruwiki/ruwiki.cgi/&lt;/a&gt;&lt;br /&gt;[2] New Google Groups for us: &lt;a href="http://groups-beta.google.com/group/stlruby"&gt;http://groups-beta.google.com/group/stlruby&lt;/a&gt;&lt;br /&gt;[3] OCI &lt;a href="http://www.ociweb.com/"&gt;http://www.ociweb.com/&lt;/a&gt;&lt;br /&gt;[4] Pictures from our dinner with dave, Bruce and folks at the Gateway Software conference&lt;br /&gt;&lt;a href="http://www.cornetdesign.com/images/DSC00476.jpg"&gt;http://www.cornetdesign.com/images/DSC00476.jpg &lt;/a&gt;(Dave is the one imbibing You can barely see the top of my head)&lt;br /&gt;&lt;a href="http://www.cornetdesign.com/images/DSC00477.jpg"&gt;http://www.cornetdesign.com/images/DSC00477.jpg&lt;/a&gt; (Jeff is the one at the left closest to the camera.)&lt;br /&gt;[5] Up and running Ruby on Rails &lt;a href="http://www.amazon.com/Ruby-Rails-Running-Bruce-Tate/dp/0596101325/sr=1-1/qid=1167512231/ref=sr_1_1/103-6671475-6469421?ie=UTF8&amp;s=books"&gt;http://www.amazon.com/Ruby-Rails-Running-Bruce-Tate/dp/0596101325/sr=1-1/qid=1167512231/ref=sr_1_1/103-6671475-6469421?ie=UTF8&amp;amp;s=books&lt;/a&gt;&lt;br /&gt;[6] Ajax Hacks &lt;a href="http://www.amazon.com/Ajax-Hacks-Bruce-Perry/dp/0596101694/sr=8-1/qid=1167512145/ref=pd_bbs_sr_1/103-6671475-6469421?ie=UTF8&amp;s=books"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;a href="http://www.amazon.com/Ajax-Hacks-Bruce-Perry/dp/0596101694/sr=8-1/qid=1167512145/ref=pd_bbs_sr_1/103-6671475-6469421?ie=UTF8&amp;amp;s=books"&gt;&lt;span class="q"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a href="http://www.amazon.com/Ajax-Hacks-Bruce-Perry/dp/0596101694/sr=8-1/qid=1167512145/ref=pd_bbs_sr_1/103-6671475-6469421?ie=UTF8&amp;s=books"&gt;http://www.amazon.com/Ajax-Hacks-Bruce-Perry/dp/0596101694/sr=8-1/qid=1167512145/ref=pd_bbs_sr_1/103-6671475-6469421?ie=UTF8&amp;amp;s=books&lt;/a&gt;&lt;span class="q"&gt;&lt;br /&gt;[7] Inspired Horizons, Ruby Training &lt;/span&gt;&lt;a href="http://inspiredhorizons.com/"&gt;&lt;span class="q"&gt;http://inspiredhorizons.com/&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="q"&gt;[8] St. Louis Code Camp &lt;a href="http://www.stlcodecamp.org/"&gt;http://www.stlcodecamp.org&lt;/a&gt;&lt;br /&gt;[9] cat2rfb &lt;a href="http://rubyquiz.com/quiz77.html"&gt;http://rubyquiz.com/quiz77.html&lt;/a&gt;&lt;br /&gt;[10] O'Reilly Ruby Weblog &lt;a href="http://www.oreillynet.com/ruby/"&gt;http://www.oreillynet.com/ruby/&lt;/a&gt;&lt;br /&gt;[11] Curt's Comments &lt;a href="http://curthibbs.wordpress.com/"&gt;http://curthibbs.wordpress.com/&lt;/a&gt;&lt;br /&gt;[13] Pat Eyler : On Ruby &lt;a href="http://on-ruby.blogspot.com/"&gt;http://on-ruby.blogspot.com/&lt;/a&gt;&lt;br /&gt;[14]&lt;/span&gt;&lt;span class="q"&gt; Kyls's blog &lt;a href="http://kylecordes.com/"&gt;http://kylecordes.com/&lt;/a&gt;&lt;br /&gt;[15] Cory's blog &lt;a href="http://www.cornetdesign.com/"&gt;http://www.cornetdesign.com/&lt;/a&gt;&lt;br /&gt;[16] WDT Solutions, LLC. &lt;a href="http://www.wdtsolutions.com/"&gt;http://www.wdtsolutions.com&lt;/a&gt;&lt;br /&gt;[17] Fantasy Golf Site &lt;/span&gt;&lt;a onclick="return top.js.OpenExtLink(window,event,this)" href="http://www.rgfgc.com/" target="_blank"&gt;http://www.rgfgc.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-6321650143590710778?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/6321650143590710778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=6321650143590710778' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/6321650143590710778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/6321650143590710778'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/12/saint-louis-pursuit-of-rubyness-06.html' title='Saint Louis: The Pursuit of Rubyness (&apos;06)'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-115637318364607238</id><published>2006-08-23T17:22:00.000-05:00</published><updated>2006-08-23T18:05:12.716-05:00</updated><title type='text'>Testing XML-ish stuff in Rails</title><content type='html'>Hi fellow Railsians,&lt;br /&gt;&lt;br /&gt;Today post is in answer to a question from Chris T on the Rails list. Chris asks:&lt;br /&gt;"Probably dead obvious, but are there any assertions for easing testing&lt;br /&gt;of xml output, both for builder templates (for RSS feed -- something&lt;br /&gt;like a version of assert_tag) and for the new restful stuff."&lt;br /&gt;&lt;br /&gt;I've seen this question come up several times in the past. The trouble with assert_tag and assert_no_tag is that they are hooked directly to the response object of your controllers. Which means you can only use them in functional or integration tests. You could fake out a response object, but there is a simpler solution, just recreate them. They are essentially a call to the find method of HTML::Document.&lt;br /&gt;&lt;br /&gt;Here is what I did: Add the following to the end your test/test_helper.rb:&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  # Add more helper methods to be used by all tests here...&lt;br /&gt;  def assert_xml_tag(xml, conditions)&lt;br /&gt;    doc = HTML::Document.new(xml)&lt;br /&gt;    assert doc.find(conditions), &lt;br /&gt;      "expected tag, but no tag found matching #{conditions.inspect} in:\n#{xml.inspect}"&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def assert_no_xml_tag(xml, conditions)&lt;br /&gt;    doc = HTML::Document.new(xml)&lt;br /&gt;    assert !doc.find(conditions), &lt;br /&gt;      "expected no tag, but found tag matching #{conditions.inspect} in:\n#{xml.inspect}"&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I chose to use the actual value as the first parameter rather than the expected value because it allows for nicer looking paramter hash values. To use it, use just like assert_tag and assert_no_tag:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def test_xml_correct&lt;br /&gt;   assert_xml_tag "&lt;x&gt;&lt;y&gt;&lt;z&gt;&lt;/z&gt;&lt;/y&gt;&lt;/x&gt;", :tag =&gt; 'z', &lt;br /&gt;     :parent =&gt; {:tag =&gt; 'y',&lt;br /&gt;                :parent =&gt; {:tag =&gt; 'x'}}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I usually have a default object under test with a single method to output. This allows for a micro-DSL-ish thing to reduce typing overhead:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;protected&lt;br /&gt;    def assert_render(conditions)&lt;br /&gt;       assert_xml_tag @thing.render, conditions&lt;br /&gt;    end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-115637318364607238?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/115637318364607238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=115637318364607238' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/115637318364607238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/115637318364607238'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/08/testing-xml-ish-stuff-in-rails.html' title='Testing XML-ish stuff in Rails'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-115447112348355161</id><published>2006-08-01T16:53:00.000-05:00</published><updated>2006-08-01T17:25:23.530-05:00</updated><title type='text'>Simplified user roles in Rails</title><content type='html'>Usually, the discussion around user authentication and authorization in Rails revolves around an authentication plugin, engine or a login generator. Next, you might get into the types of users and this is where you might see a discussion about Roles, UserRoles and Users. There is plenty of tutorials about this usually describing an example of HABTM or has_many :through. But for simple cases, you can get the effect of user roles without much effort at all, just through normal Rails associations.&lt;br /&gt;&lt;br /&gt;In addition to your 'users' table, create tables for each type of role. These can contain attributes specific to that type of user. For instance, you can have a admin type of user with specific flags allowing different types of CRUD access. A business contact user might have additional ways to be contacted (phone extension, cell phone, mail stop, etc.) For each table, add a user_id foreign key. In the models, make sure these all 'belongs_to :user'.&lt;br /&gt;&lt;br /&gt;Then in the User model, add a 'has_one :admin' and 'has_one :business_contact' etc. for each associated table. The has_one association adds methods to the model to make it easy to query the relation:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;user = User.find 1&lt;br /&gt;if user.admin&lt;br /&gt;  # do admin stuff&lt;br /&gt;end&lt;br /&gt;...&lt;br /&gt;details.save unless user.business_contact.nil?&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Each user can participate in more than one role. This keeps the user login centralized and the authorization stuff very readable. Adding a new type only requires adding a new table and updating app/models/user.rb to add the has_one associtation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This simple strategy might not be enough for your needs. It doesn't work if you anticipate adding user roles on the fly to a running system. In this case, you'd probably want to look into a permissions system tied to a HABTM based Role and UserRole model. I've only described a solution for a fixed amount of user types, more or less hard coded into the models.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-115447112348355161?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/115447112348355161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=115447112348355161' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/115447112348355161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/115447112348355161'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/08/simplified-user-roles-in-rails.html' title='Simplified user roles in Rails'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-115231304838621832</id><published>2006-07-07T17:42:00.000-05:00</published><updated>2006-07-07T18:52:37.156-05:00</updated><title type='text'>Testing Helpers and Helping Testers</title><content type='html'>The Rails helper_test plugin [1] is a useful thing that provides you with more tools to better test-cover your code. View helpers that live in app/helpers should be tested in isolation from unit and functional/integration tests. This is true just on the face of it. But additionally, you get to access Rails helper methods which you are usually combining with your own stuff. Hard to do that in normal unit tests, and the setup in integration tests is a little too bloated for my taste.&lt;br /&gt;&lt;br /&gt;There are a few tricks that can be used to make this run even smoother.  The first trick is to utilize assert_tag to check your HTML generation. assert_tag wants to check the body in the @response object which is expected to be a valid XHTML string. But you are not in the request/response environment of functional/integration tests, so @response is not available. Not to worry, we can just fake it out for now. Create a class with an accessible instance variable that is an instantiated string named body:&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Response&lt;br /&gt;attr_writer :body&lt;br /&gt;def initialize&lt;br /&gt;  @body = ""&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def body&lt;br /&gt;  "&amp;lt;x&amp;gt;" + @body + "&amp;lt;/x&amp;gt;"&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;In your test method, assign @response = Response.new. Assign the output of your helper method to @response.body. Now assert_tag will work in all it's glory.&lt;br /&gt;&lt;br /&gt;The next trick involves testing the image_tag helper.  If my helper generates one or more img tags, they can be hard to test with assert_tag. The reason for this is due to the change in Rails to help the various asset tags work better with browser side caches.  The helper&lt;br /&gt;image_tag "graphic.gif"&lt;br /&gt;results in something similar:&lt;br /&gt;&amp;lt;img src="/images/graphic.gif?12345678"&amp;gt;&lt;br /&gt;&lt;br /&gt;where the parameter after the ? is a file based timestamp. This helps the browser to decide to get a new copy of the asset or not. But calling assert_tag :tag =&gt; 'img', :attributes =&gt; {:src =&gt; "/images/graphic.gif?12345678"} is brittle, since if you update the timestamp, (say the next time you get an update from Subversion,) your tests will break. The easy solution to this is to force the ASSET_ID to always be a fixed string. Add this line to config/environments/test.rb:&lt;br /&gt;&lt;br /&gt;ENV['RAILS_ASSET_ID']=12345&lt;br /&gt;&lt;br /&gt;Now this will be constant in your tests:&lt;div class="code"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def test_image_asset&lt;br /&gt;   @response = Response.new&lt;br /&gt;   @response.body = my_helper_that_returns_an_img_tag&lt;br /&gt;   assert_tag :tag =&gt; "img", :attributes =&gt; {:src =&gt; "/images/graphic.gif?12345"}&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://nubyonrails.topfunky.com/articles/2006/04/07/test-your-helpers"&gt; http://nubyonrails.topfunky.com/articles/2006/04/07/test-your-helpers&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-115231304838621832?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/115231304838621832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=115231304838621832' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/115231304838621832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/115231304838621832'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/07/testing-helpers-and-helping-testers.html' title='Testing Helpers and Helping Testers'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-114668291175792284</id><published>2006-05-03T12:31:00.000-05:00</published><updated>2006-05-03T14:01:51.816-05:00</updated><title type='text'>StL.rb Hacking Night - Hacking the Ruby Quiz</title><content type='html'>Well, once again Craig, Sean and I met this past Tuesday for the weekly hacking night of the St. Louis Ruby Brigrade. We decided to work on the current Ruby Quiz which Sean had submitted. It was a lot of fun and a good idea for what to work on if there is no other ideas.&lt;br /&gt;&lt;br /&gt;This week's quiz [1] concerned cat2rfb.rb which from the RubyQuiz site he says : "The goal of cat2rafb is to implement a command line utility that will allow you to submit arbitrary text to http://rafb.net/paste/ and get the URL for the text back." You have to understand what rafb.net/paste is all about. This is a site where you can post snippets of code or text then it redirects you to a page where your code is displayed and syntax colorized. But the cool thing is the URL can be shared with others to collaborate.&lt;br /&gt;&lt;br /&gt;From their FAQ [2]: "&lt;span class="itemdef"&gt;What is a 'nopaste' site?&lt;/span&gt; &lt;p&gt;&lt;span class="desc"&gt; A 'nopaste' site allows people to paste chunks of code for others to view. This is useful for situations such as asking for programming help on IRC, where it is frowned upon to paste chunks of code to the channel or to individual. With a nopaste site, the user pastes his or her code to the site and is given a url to provide to others so they can find the code."&lt;/span&gt;&lt;/p&gt;What Sean wanted was an easy command line way to paste the code from files, or stdin w/o having to go through the web site. Bonus points if you convert the resulting URL from rafb.net through rubyurl.com which is a Rails equivalent to tinyurl.com that converts long URLs to short ones. (Not that the resulting rafb.net code display URLs are that long anyway.)&lt;br /&gt;&lt;br /&gt;Sean hadn't actually come up with an answer for his own quiz yet, so that made me suspect he wanted to prime the WHN attendees with some actual cool work to do. In any case, it was a fairly good learning session for me. We actually set up an IRC session on freenode/#stl.rb to share links. Eating our own dogfood, I guess.&lt;br /&gt;&lt;br /&gt;The basic idea is becoming familiar with Net::HTTP posts and gets. Sean went for a Ruby Golf approach, while I took the opposite approach. I wanted to provide options and error checking and read from an optional config file. The fields on the nopaste form allow you to choose from different languages, choose a nickname and give it a description. This makes it easier to find in the Recent pastes screen.&lt;br /&gt;&lt;br /&gt;The other tricky part is understanding how to follow a redirect from Net::HTTP#post. Turns out Net::HTTPResponse has a bunch of subclasses. So you can do a 'case when' around the response object and then query its 'location' key (it behaves like a hash.)&lt;br /&gt;&lt;br /&gt;I also figured out the issues wrt using GetoptLong and ARGF together. You need to process the arguments first, then set a post argument to ARGF.readlines. Also, RDoc::usage is a seriously cool thing. It looks at the comments at the top of your file and processes them into an usage statement and then exits. How can it see the comments in a file that calls it? Very deep Ruby-fu there. But this fits nicely with the DRY rule (comments and usage decared just once.)&lt;br /&gt;&lt;br /&gt;So, we finished up right when the meeting was supposed to end. This kind of exploration to solve the quiz was well suited to the amount of time allocated for a hacking night. Look on ruby-talk for mine, Sean's and other answers to this week's quiz.&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://www.rubyquiz.com/quiz77.html"&gt;http://www.rubyquiz.com/quiz77.html&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://rafb.net/paste/faq.html"&gt;http://rafb.net/paste/faq.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-114668291175792284?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/114668291175792284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=114668291175792284' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/114668291175792284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/114668291175792284'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/05/stlrb-hacking-night-hacking-ruby-quiz.html' title='StL.rb Hacking Night - Hacking the Ruby Quiz'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-114650628948454963</id><published>2006-05-01T12:41:00.000-05:00</published><updated>2006-05-08T10:15:49.256-05:00</updated><title type='text'>Ruby w/readline  on Ubuntu</title><content type='html'>Getting Ruby running on Ubuntu 5.10 (Breezy) can be tricky. The issue is Breezy wants Ruby 1.8.3 from apt-get, and that has known problems with Rails 1.x. I usually recommend people install ruby 1.8.4 from source to work with Rails 1.1. But the base install of Ubuntu doesn't have many source build tools and libraries. This shows up in various places. For instance, running 'script/console' barfs complaining about missing the readline require. That is because irb wasn't built with it in the 1.8.4 build tree. Another issue you may have run into is support for rubygems is lacking due to a missing zlib development library. This may have messed up your install of Rails or various plugins.&lt;br /&gt;&lt;br /&gt;Before we start read this guide: [1] Be sure to add the extra repositories, if you haven't yet.&lt;br /&gt;&lt;br /&gt;Here are a bunch of commands that I executed to get Ruby built.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;apt-get install build-essential&lt;br /&gt;apt-get install bison byacc gperf&lt;br /&gt;apt-get install zlib1g-dev&lt;br /&gt;apt-get install libreadline5 libreadline5-dev&lt;br /&gt;apt-get install libncurses5 libncurses5-dev temcap-compat&lt;br /&gt;apt-get install libssl-dev&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you have previously tried to build it, then rm -rf ruby-1.8.4 and tar zxvf ruby-1.8.4.tar.gz; cd ruby-1.8.4; ./configure; make; sudo make install&lt;br /&gt;&lt;br /&gt;Retest in your rails app: script/console. Everything should work.&lt;br /&gt;&lt;br /&gt;The last install is for openssl development headers and libs. This is a Rake dependency in certain cases. (Not Rails specific.)&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://ubuntuguide.org/"&gt;http://ubuntuguide.org/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-114650628948454963?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/114650628948454963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=114650628948454963' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/114650628948454963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/114650628948454963'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/05/ruby-wreadline-on-ubuntu.html' title='Ruby w/readline  on Ubuntu'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-114555550990711373</id><published>2006-04-20T12:47:00.000-05:00</published><updated>2006-05-01T12:35:12.363-05:00</updated><title type='text'>Further adventures along our Trail</title><content type='html'>More about Migrations.&lt;br /&gt;&lt;br /&gt;Here are a few more things I've learned about Rails 1.1 DB Migrations, or I forgot to note in my last post.&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;Make small migrations. It is ok to have very many migrations. Goes with test a little, code a little, repeat, refactor, etc.&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;Don't put in the id column for the table. The create_table method does that by default.&lt;/li&gt;&lt;li&gt;When naming your migrations, only use "pure" CamelCase. E.g. This "AddSSNToClient" doesn't work because ./script/generate migration will creare 003_add_ssn_to_client but the name of the class will be AddSSNToClient, and 'rake migrate' will look for AddSsnToClient.&lt;/li&gt;   &lt;li&gt;Use db/schema.rb to populate your production databases and other development servers. This will still preserve your version # and should allow you to back out to previous versions even on these DB instances.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Commit any code changes prior to your first migration. Tag this so you know where you came from.&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;Use rake db:schema:dump one time when you want to start using migations from a pre-existing SQL DDL generated schema. At this point you will be at version 0. Generate your next model or generate a new migration which will be version 1. If you back out via rake migrate VERSION=0 you will be at the last point before you started using migrations.&lt;/li&gt;&lt;li&gt;You can port your development environment to a new computer and a new instance of your DB server. Check out your head SVN trunk. I have a Rake task that generates my DBs and sets up config/database.yml*. run that or create at least your development and test dbs. Then run 'rake migrate'. You can backup and restore your old data into your new MySQL instance.&lt;br /&gt;&lt;/li&gt;  &lt;/ul&gt;In my last post, I said you should start Rails Migrations from Day 1. That is true, but what if you have an existing schema? That's OK, too. It will just start at revision 0. From that point forward, you want to do migrations only.&lt;br /&gt;&lt;br /&gt;If you are using MySQL, then I recommend doing a &lt;pre&gt;mysqldump -t db_name &gt;db/mydbstruct.sql&lt;/pre&gt; and commiting that before continuing. You should even make a full backup of your database, which is always a good idea when playing around with DBs.&lt;br /&gt;&lt;br /&gt;The sequence (for legacy DB conversion to Rails Migrations) is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;mysqldump -t mydb &gt;db/mydb_struct.sql&lt;/li&gt;&lt;li&gt;svn add db/mydb_struct.sql&lt;/li&gt;&lt;li&gt;svn commit -m "Commit DB Version 000 prior to first migration"&lt;br /&gt;&lt;/li&gt;&lt;li&gt;"svn copy" to tags/DBVersion_000&lt;/li&gt;&lt;li&gt;./script/generate migration AddColumnToMytabs&lt;/li&gt;&lt;li&gt;Edit db/migrate/001_add_column_to_mytabs.rb and add your column(s)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;rake migrate&lt;/li&gt;&lt;li&gt;rake # to run tests&lt;/li&gt;&lt;li&gt;svn commit -m "Switched to Rails Migrations. DB Version 001. Added column to Mytabs."&lt;br /&gt;&lt;/li&gt;&lt;li&gt;svn copy to tags/DBVersion_001&lt;/li&gt;&lt;/ul&gt;Or, if you are creating a new model,&lt;br /&gt;&lt;ul&gt;&lt;li&gt;./script/generate model NewModel&lt;/li&gt;&lt;li&gt;Edit db/migrate/001_add_columns_to_mytabs.rb&lt;/li&gt;&lt;li&gt;... etc.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Some have suggested that you should do &lt;span style="font-style: italic;"&gt;rake db:schema:dump&lt;/span&gt; then copy and paste the output inside db/schema.rb into a new migation. I am not exactly sure when this is useful. Perhaps if you want to start using migrations from scratch so that your first migration (001) creates all your legacy tables.&lt;br /&gt;&lt;br /&gt;* This is my rake task. I copy it into lib/tasks (actually I have a generator to do that for me.) The fix_yaml task is needed in my case because I am running MySQL 4.1.x on Ubuntu. The socket is in a different place than Rails thinks and I don't want to be root for my personal DBs I create.&lt;br /&gt;&lt;br /&gt;lib/tasks/create_db.rake&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;require 'yaml'&lt;br /&gt;fn_yaml='config/database.yml'&lt;br /&gt;myuserid='me'&lt;br /&gt;yml=YAML::load(File.open(fn_yaml))&lt;br /&gt;&lt;br /&gt;desc 'Creates databases in mysql'&lt;br /&gt;task :create_db =&gt; [:fix_yaml] do&lt;br /&gt;      databases do |db|&lt;br /&gt;              system "echo create database #{yml[db]['database']} | mysql"&lt;br /&gt;      end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;desc 'Drops databases in mysql'&lt;br /&gt;task :drop_db do&lt;br /&gt;      databases do |db|&lt;br /&gt;              system "echo drop database #{yml[db]['database']} | mysql"&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;desc 'Fix database.yml'&lt;br /&gt;task :fix_yaml do&lt;br /&gt;      databases do |db|&lt;br /&gt;              yml[db]['username'] = me&lt;br /&gt;              yml[db]['socket'] = '/var/run/mysqld/mysqld.sock'&lt;br /&gt;      end&lt;br /&gt;      File.new(fn_yaml, 'w').write yml.to_yaml&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;def databases&lt;br /&gt;      %w{development test production}.each do |db|&lt;br /&gt;              yield db&lt;br /&gt;      end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-114555550990711373?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/114555550990711373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=114555550990711373' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/114555550990711373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/114555550990711373'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/04/further-adventures-along-our-trail.html' title='Further adventures along our Trail'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-114549007895106218</id><published>2006-04-19T18:36:00.000-05:00</published><updated>2006-04-22T12:46:27.463-05:00</updated><title type='text'>Happy Trails</title><content type='html'>Happy Migrations.&lt;br /&gt;&lt;br /&gt;Rails 1.1 has a really cool mechanism for dealing with updates to a database during development: Migrations. Actually, I think migrations predates Rails 1.1, but that is where I first discovered it and it is supposed to be improved. Anyway, migrations are the way you should do all your database development from day 1. It makes the handling database changes much more agile. I tried to wrap my head around migrations from reading online docs, but I was quite unsuited to that task. Thankfully, I attended the 2nd Weekly Hacking Night [1] of StL.rb with Sean Carely and Craig Buchek and I learned what a dunce I had been.&lt;br /&gt;&lt;br /&gt;Here are some notes about migrations that I have collected. Others have written eloquently on the mechanics of migrations [2], [3]. I am primarily concerned about the process of migrations. What to do and when to do it.&lt;br /&gt;&lt;br /&gt;Lets start with some advice from my little green friend:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Yoda says:&lt;/span&gt;  &lt;span style="font-style: italic;"&gt;If once you start down the migration path, forever will it dominate your destiny, consume you it will.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lets also assume some starting parameters:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;You are starting a new project.&lt;/li&gt;   &lt;li&gt;You are using Rails 1.1&lt;/li&gt;   &lt;li&gt;Your DB engine is supported by schema-type Ruby. IOW, you can use db/schema.rb instead of the old schema.sql style. (These are at least MySQL, PostgresSQL and SQLLite, mssql. And some rumored others.) I will be using MySQL here.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;You are using Subversion for version control.&lt;br /&gt;&lt;/li&gt;  &lt;/ul&gt;  and finally:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;You are committed to never use SQL to modify your DB structure again.&lt;/li&gt; &lt;/ul&gt;Whew, glad thats out of the way. Migrations and models and tests are well integrated in R1.1. You should use the model generator to create them. Lets begin at the point where we have created our fresh Rails app, we have created a repository with trunk, tags and branches folders in SVN for it, imported our created rails app into trunk and checked out a new working copy. We should have adjusted config/database.yml to reflect our connection and login parameters for MySQL. We may have done other stuff like create controllers and some views, but we haven't created our first model yet. We haven't even created our databases yet. This is where we start with our first migrations.&lt;br /&gt;&lt;br /&gt;Our Rails app is called trails and it will feature campers, equipment, counselors, hikes, etc. Lets create our databases:&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;pre&gt;for d in development test production; do echo create database trails_${d}\;; done | mysql&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;Now lets add our first model: Camper.&lt;br /&gt;&lt;pre&gt;./script/generate model Camper&lt;br /&gt;exists  app/models/&lt;br /&gt;exists  test/unit/&lt;br /&gt;exists  test/fixtures/&lt;br /&gt;create  app/models/camper.rb&lt;br /&gt;create  test/unit/camper_test.rb&lt;br /&gt;create  test/fixtures/campers.yml&lt;br /&gt;create  db/migrate&lt;br /&gt;create  db/migrate/001_create_campers.rb&lt;br /&gt;&lt;/pre&gt;Note that it created db/migrate and 001_create_campers.rb for us. This is how we are going to create our first table. Note that the version # is 001. As you create new migrations, these will increment, e.g. 002_xxx.rb, 003_yyy.rb, etc. When you run your migrations, rake will load them in that order and the highest versioned file in db/migrate will become the schema version #. More on that later.&lt;br /&gt;&lt;br /&gt;Next you need to edit db/migrate/001_create_campers.rb and add columns to the table. Next run &lt;pre&gt;rake migrate&lt;/pre&gt;This will create the table in the development db and create a new table called schema_info with a version column. That version will be set to 1. It will also create a file called db/schema.rb with all our current table settings. Schema.rb will contain the current version of the DB since our last rake migrate, so that is a quick way to discover the current version #. The test framework will use db/schema.rb to create the test database and set its version to 1 as well. Just running &lt;pre&gt;rake&lt;/pre&gt; will do that for you, as well as running all your tests.&lt;br /&gt;&lt;br /&gt;We next create a new model &lt;span style="font-style: italic;"&gt;Equipment&lt;/span&gt; using the same procress of generate model, edit db/002_create_euipment.rb and rake migrate. Now our development schema_info.version is 2 and we have a new table called equipment.&lt;br /&gt;&lt;br /&gt;Next we might decide that each camper is responsible for some pieces of equipment. We need to link our Campers to our Equipment on a foreign key which we forgot to add when we created the model. We do that by generating a new migration: &lt;pre&gt;./script/generate migration AddCamperIdToEquipment&lt;/pre&gt;Add our column to db/migrate/003_add_camper_id_to_equipment,rb and then run &lt;pre&gt;rake migrate&lt;/pre&gt;We are now at version 3. Adding some tests, then runing rake with no options will update our test DB to version 3 as well.&lt;br /&gt;&lt;br /&gt;At this point, we have done a few migations and have a code base that is passing all our tests. Time to check in. Before we do, Sean pointed out that we can use Subversion metadata to keep commits in sync with our DB. &lt;pre&gt;svn propset migrate-version 001 .&lt;/pre&gt; will do that for us. Later, we can &lt;span style="font-style: italic;"&gt;svn propget migrate-version .&lt;/span&gt; to query it.&lt;br /&gt;&lt;pre&gt;svn status&lt;/pre&gt; Add any missing files, then &lt;pre&gt;svn commit -m "Database now at version 003"&lt;/pre&gt;Whenever I commit following one or more migrations, I like to tag it so it is recorded that the code base is working to a specific DB release.&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;pre style=""&gt;svn copy -m "DB Version 003" svn+ssh://ip.of.host.box/path/to/repos/trunk svn+ssh://ip.of.host.box/path/to/repos/tags/DBVersion_003&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;After a few more models have been generated and migrations executed, we might want to revert to a previous database version. Assuming we are at version 7, we just migrate down with :&lt;br /&gt;&lt;pre&gt;rake migate VERSION=6&lt;/pre&gt;We can run svn diff to discover what code changes we made since our last tag DBVersion_006 and back those out as well. I generally make it a policy to commit and tag in SVN when I've created a few models (or just one) or I've generated a special migration to add, rename or remove a column.&lt;br /&gt;&lt;br /&gt;To summarize:&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;&lt;pre&gt;./script/generate model ModelName&lt;br /&gt;- edit db/migrate/001_create_model_names.rb&lt;br /&gt;rake migrate&lt;br /&gt;rake        # runs tests, updates test DB to current schema.&lt;br /&gt;./script/generate model NewModel&lt;br /&gt;- edit db/migrate/002_create_new_models.rb&lt;br /&gt;rake migrate&lt;br /&gt;rake&lt;br /&gt;# add a missing column&lt;br /&gt;./script/generate migration AddColumnToNewModels&lt;br /&gt;- edit db/migrate/003_add_column_to_new_models.rb&lt;br /&gt;rake migrate&lt;br /&gt;rake&lt;br /&gt;# check in&lt;br /&gt;svn propset migrate-version 003 .&lt;br /&gt;svn status      # discover unversioned files&lt;br /&gt;svn add db/migrate/001_ , 002 ...   etc.&lt;br /&gt;svn commit -m "DB Version 003"&lt;br /&gt;svn copy -m "DB Version 003" svn+ssh://ip.of.host.box/path/to/repos/trunk svn+ssh://ip.of.host.box/path/to/repos/tags/DBVersion_003&lt;br /&gt;...&lt;br /&gt;# revert to a previous version of the DB Current version is 7&lt;br /&gt;rake migate VERSION=6&lt;br /&gt;svn diff svn+ssh://ip.of.svn.box/path/to/repos/tags/DBVersion_006 svn+ssh://ip.of.svn.box/path/to/repos/trunk&lt;br /&gt;# make changes or use svn revert&lt;br /&gt;rake     # revert our test DB to version 6 and rerun our tests.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;One last note. If you generate migrations, be sure to name them uniquely. That is because rake will load all the classes in db/migrate in order of version # and Ruby will overrite the first same named class with the last same named class. Use explicit names that reflect what the migration is going to do, e.g. AddClassNameToStudents. This is the ProgramingByIntention [4] principle of XP.&lt;br /&gt;&lt;br /&gt;Overall, I have found migrations to fit nicely with the XP test-code-refactor cycle. It opens the database up to being able to be refactored. Subversion is a tool that helps me when I inevitably shoot myself in the foot.&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://sean-carley.blogspot.com/2006/04/stlrb-hacking-nights.html#links"&gt;http://sean-carley.blogspot.com/2006/04/stlrb-hacking-nights.html#links&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://wiki.rubyonrails.com/rails/pages/UsingMigrations"&gt;http://wiki.rubyonrails.com/rails/pages/UsingMigrations&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://rails.rubyonrails.org/classes/ActiveRecord/Migration.html"&gt;http://rails.rubyonrails.org/classes/ActiveRecord/Migration.html&lt;br /&gt;&lt;/a&gt;[4] &lt;a href="http://c2.com/cgi/wiki?IntentionalProgramming"&gt;http://c2.com/cgi/wiki?IntentionalProgramming&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-114549007895106218?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/114549007895106218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=114549007895106218' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/114549007895106218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/114549007895106218'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/04/happy-trails.html' title='Happy Trails'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20834841.post-113700498477643907</id><published>2006-01-11T12:39:00.000-06:00</published><updated>2006-01-11T20:09:11.426-06:00</updated><title type='text'>What is Green Programming?</title><content type='html'>This is just an initial post.&lt;br /&gt;&lt;br /&gt;Green programming is an attempt to synthesize the principals of environmentally sound policy and the Agile Software set. IOW, just like we should aspire to use renewable energy sources to help the health of the planet, we should also use reusable software elements to create robust, healthy code for our customers. Eco-friendly practices might be thought of as applicable to software devlopment. Just as we are concerned with the various biota and climate of the planet, we should be concerned with the over-all health of the software eco-system. I am specifically concerned with threats to free and open source software from patents and copyright concerns.&lt;br /&gt;&lt;br /&gt;Actually, I just needed a title and domain, so I thought I might ride the currently fashionable "Green" movement. Please forgive my impetuousness.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20834841-113700498477643907?l=greenprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://greenprogrammer.blogspot.com/feeds/113700498477643907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20834841&amp;postID=113700498477643907' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/113700498477643907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20834841/posts/default/113700498477643907'/><link rel='alternate' type='text/html' href='http://greenprogrammer.blogspot.com/2006/01/what-is-green-programming.html' title='What is Green Programming?'/><author><name>Ed Howland</name><uri>http://www.blogger.com/profile/12016196435680843966</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>
