tag:blogger.com,1999:blog-15251780188113561292024-02-18T20:28:27.002-06:00fairleadsless is more...Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-1525178018811356129.post-23662068084830191552022-11-10T12:51:00.000-06:002022-11-10T12:51:03.363-06:00<a href="https://mastodon.social/@SeanPLynch" rel="me">Mastodon</a>
<p>Find me on mastodon as</p><p> @SeanPLynch@mastodon.social</p><p>https://mastodon.social/@SeanPLynch</p><p><br /></p><p>See you there!<br /></p>
Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com0tag:blogger.com,1999:blog-1525178018811356129.post-14599338601712344312008-05-02T14:22:00.000-05:002008-05-02T14:28:01.144-05:00Agile Web Development With Rails 3rd Ed. covers Rails 2.0!<p>The tireless <a href="http://www.pragprog.com">Pragmatic programmers</a> have released a new version of <a href="http://www.pragprog.com/titles/rails3/agile-web-development-with-rails-third-edition">Agile Web Development with Rails</a>, and it covers Rails 2.0!<br /><br /><p>Its still in beta form, but you can get the PDF version online. If you bought a copy of the 2nd edition since March 2008 you can get a coupon for a free upgrade.<br /><br /><p>See the pragmatic web site for details.Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com6tag:blogger.com,1999:blog-1525178018811356129.post-25653045337236638232008-02-29T10:22:00.000-06:002008-03-17T09:21:58.745-05:00Rails 2.0 Step by Step (part 2.1)<h1>Rails 2.0 Step by Step (part 2.1)</h1><br /><ul><br /><li> Part 1 is <a href="http://fairleads.blogspot.com/2007/12/rails-20-and-scaffolding-step-by-step.html">here</a><br /></li><li> Part 2 is <a href="http://fairleads.blogspot.com/2008/01/this-is-second-part-of-my-series.html">here</a><br /></li></ul><br /><p>This is a short post to address an error I made in my part 2 post. I posted a bad copy of the index.html.erb file, and I apologize to those of you who read my blog. Thanks to your comments my error was caught.<br /><br />The correct code you should use in the index.html.erb file is below, just cut and paste this block:<br /><br /><pre><blockquote><br /><tt><br /><div id="movie-list"><br /> <h1>Movie Listing</h1><br /><br /> <table cellpadding="5" cellspacing="0"><br /> <% for movie in @movies %><br /> <tr valign="top" class="<%= cycle('list-line-odd', 'list-line-even') %>"><br /><br /> <td><br /> <img class="list-one-sheet" src="<%= movie.one_sheet_url %>"/><br /> </td><br /><br /> <td width="60%"><br /> <span class="list-title"><%= h(movie.title) %></span><br /><br /> <%= h(truncate(movie.description, 80)) %><br /> </td><br /><br /> <td class="list-actions"><br /> <%= link_to 'Show', movie %><br /> <%= link_to 'Edit', edit_movie_path(movie) %><br /> <%= link_to 'Destroy', movie, :confirm => 'Are you sure?', :method => :delete %><br /> </td><br /> </tr><br /> <% end %><br /> </table><br /></div><br /><br /><br /><%= link_to 'New movie', :action => 'new' %><br /></tt></blockquote></pre><br /><br /><br /></p><p><span style="font-weight: bold;">Note:</span> I have just gone back and edited part 2 to include this correction.<br /></p>Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com5tag:blogger.com,1999:blog-1525178018811356129.post-39813313219690514232008-01-27T19:33:00.002-06:002009-01-13T12:41:06.702-06:00Rails 2.0 Step by Step (part 2)<span style="font-family:arial;">This is the second part of my series.<br />Part 1 is <a href="http://fairleads.blogspot.com/2007/12/rails-20-and-scaffolding-step-by-step.html">here</a>.<br /></span><span style="font-family:arial;">Thanks for all of the great comments and help.</span><span style="font-family:arial;"><br /></span><br /><span style="font-family:arial;">I think one of the most important comments came from enklare who pointed out that with Rails 2.0 you should explicitly set the database when you create a new Rails app by using the -d flag.</span><span style="font-family:arial;"> </span><span style="font-family:arial;"><br /><br />Instead of using the command</span><br /><span style="font-family:courier new;">work$</span><span style="font-weight: bold;font-family:courier new;" > rails exchange</span><span style="font-family:courier new;"> </span><span style="font-family:arial;"><br /><span style="font-family:arial;">use the command</span></span><br /><span style="font-family:courier new;">work$</span><span style="font-weight: bold;font-family:courier new;" > rails -d mysql exchange</span><br /><br /><span style="font-family:arial;">To create the exchange app.<br /><br />( typing 'rails --help' at the command line will give a short list of available options)<br /><br />This will help Rails configure your application if you have other databases like SQLLite installed.</span><span style="font-family:arial;"><br />SQLLite is the default database for Rails as of Rails version 2.0. </span><span style="font-size:130%;"><span style="font-weight: bold;font-family:arial;" ><br />-------------------------------------------------------------------------------------------------------------<br /><span style="font-size:180%;">Rails 2.0 Step by Step<br />(part 2)</span><br /><br />Model View Controller</span></span><br /><span style="font-family:arial;">The Model View Controller(MVC) design pattern was first described in 1979 by <a href="http://en.wikipedia.org/wiki/Trygve_Reenskaug">Trygve Reenskaug </a>while working at Xerox on Smalltalk. MVC is not a new syntax construct like an if statement or a data type like an array or int but more a way of looking at how to structure programs and</span><span style="font-family:arial;"> divide the parts up in a logical and useful way.<br /><br />Following MVC guidelines has been shown to organize applications in a way that makes them easy to manage and maintain. After working with the MVC pattern for a while you will grow to see the benefits that the division of labor produce. </span> <span style="font-family:arial;">Rails is a strict MVC frame work.<br /><br />If you stick to the MVC pattern you will find Rails easier to understand and use.</span> <span style="font-weight: bold;font-family:arial;" ><br /><br />Model</span> <span style="font-family:arial;"><br />The Model is all about the data. This includes getting the data in and out of the data store. The scaffolding we set up in part one gives us the four basic operation of using a data store Create,</span><span style="font-family:arial;"> Read, Update and Destroy. Other data centric functionality also goes in the Model. Searching for data, manipulating data, validating input, and possibly editing the data for display (although sometimes this might logically be part of the view as well). </span> <span style="font-weight: bold;font-family:arial;" ><br /><br />View</span> <span style="font-family:arial;"><br />The View renders the Model in an interactive displayable format. It takes the data in the Model and paints it up on the screen for you to see and interact with.</span> <span style="font-weight: bold;font-family:arial;" ><br /><br />Controller</span><br /><span style="font-family:arial;">The Controller responds to events communicating with the Model and the View. This is like the Main loop in a state machine waiting for events like user actions or Model data to show up and reacting as the program dictates to those events.</span> <span style="font-family:arial;">Let's look at the Model View and Controller created by the Rails scaffolding, and start updating each of them with our own code.<br /><br />We'll make changes to the Model and to the view and then get into the controller and migrations in the next installment.</span><br /><br /><span style="font-weight: bold;font-family:arial;" >The Model in Rails</span><br /><span style="font-family:arial;">The scaffold command created a model in the app/model/ folder called movies.rb.<br /><br />Look in ~/work/exchange/app/models/movies.rb and you'll see a pretty sparse Model</span><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiepWT65dn87dHcdjRZ0TUqKd1KTbMJlQ72OW47MZWk_ZkHgYMq-GAneTYQmvpWCdNIBPUUvVpOP7lQhGN8aZJ7qEu8n6bWXYDSt644c8yTn-pfvuoH_8AmDqBjtgXw3Bn_PlO3ZwhZcH2x/s1600-h/01.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiepWT65dn87dHcdjRZ0TUqKd1KTbMJlQ72OW47MZWk_ZkHgYMq-GAneTYQmvpWCdNIBPUUvVpOP7lQhGN8aZJ7qEu8n6bWXYDSt644c8yTn-pfvuoH_8AmDqBjtgXw3Bn_PlO3ZwhZcH2x/s400/01.png" alt="" id="BLOGGER_PHOTO_ID_5160336661577327058" border="0" /></a><br /><span style="font-family:arial;">The file is a Ruby file and the lines</span> <span style="font-weight: bold;font-family:courier new;" ><br />class Movie <><br /><span style="font-weight: bold;font-family:courier new;" >end</span> <span style="font-family:arial;"><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;"><br />declare a class named Movie that inherits from class ActiveRecord::Base. Active Record is one of the gems installed along with Rails. </span><br /><span style="font-family:arial;"><br />Looking in the <a href="http://api.rubyonrails.org/">Ruby on Rails api documentation</a> for ActiveRecord::Base in the Classes section shows all of the methods, attributes, exceptions and other parts available in class ActiveRecord::Base. We'll see that an instance of the class Movie could be called anything but the Rails convention is to use a variable named movie or @movie. You will see this in code covered below.</span> <span style="font-family:arial;"><br /><br />The :: symbol is the Ruby scope operator. In ActiveRecord::Base it means that you are referring to the Base of ActiveRecord and not some other base. </span><br /><span style="font-family:arial;"><br /></span><span style="font-family:arial;">We can customize our Model by adding code here just as in earlier versions of Rails. By adding our own code Movie will inherit from and extend the ActiveRecord::Base class.</span> <span style="font-family:arial;"><br /><br />The line</span><br /><span style="font-weight: bold;font-family:courier new;" >validates_presence_of :title, :description, :one_sheet_url</span><span style="font-weight: bold;"> </span><span style="font-family:arial;"><br /><br />will check to make sure that there is, at least, some value entered in the fields on the form.</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuycQCKlnqojhsele4JLpNd6LbHVQDYfMCvRBm5sR3jyoIXZ948JKR0Y39LtM4sAjB88o6zBKbJ6Axn4fLDmOCSbde4UfLs9rTSwEk5jn9CdTq18DLr0FDcHGhoeUTN-4YWwcBypgEsuMZ/s1600-h/02.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuycQCKlnqojhsele4JLpNd6LbHVQDYfMCvRBm5sR3jyoIXZ948JKR0Y39LtM4sAjB88o6zBKbJ6Axn4fLDmOCSbde4UfLs9rTSwEk5jn9CdTq18DLr0FDcHGhoeUTN-4YWwcBypgEsuMZ/s400/02.png" alt="" id="BLOGGER_PHOTO_ID_5160336545613210050" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">Let's create a new movie and see how the model behaves when we leave out the description and one sheet image location.</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYZKFs2-bw5j5Z_WBA13LjtMnK051JmQVxA_MgoX-NE9xWi7qZQ8-CzBePWC3RbrOGkHklssQ52RBaaf5vh7UUxFY11-aE-hsnFp0A8BIN6_UfscTGRjFssUbfL01cFdjm3GFAN3jROTgK/s1600-h/03.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYZKFs2-bw5j5Z_WBA13LjtMnK051JmQVxA_MgoX-NE9xWi7qZQ8-CzBePWC3RbrOGkHklssQ52RBaaf5vh7UUxFY11-aE-hsnFp0A8BIN6_UfscTGRjFssUbfL01cFdjm3GFAN3jROTgK/s400/03.png" alt="" id="BLOGGER_PHOTO_ID_5160336446828962226" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">The Model won't allow a new row to be created if these fields are blank. Rails provides many validation features out of the box. The errors are listed at the top of the screen along with a description of the problem encountered and the fields with errors are highlighted in the form. </span> <span style="font-family:arial;"><br /><br />Taking a cue out of the AWDWR depot app we can check the format of data entered too.</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf7Ml4glzfUM7huj6llhMB4epGsEj1S1ATfIGQ43Cvm_zdHm-V21fJEMw6n0xA8Zxb7VVhuV5LvL2rGtAEWEUtnVts_6lWaIw4qgy_OcBGvjzXpAM9iC553kXiaGPIcvNjXMV11EEtolRW/s1600-h/04.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf7Ml4glzfUM7huj6llhMB4epGsEj1S1ATfIGQ43Cvm_zdHm-V21fJEMw6n0xA8Zxb7VVhuV5LvL2rGtAEWEUtnVts_6lWaIw4qgy_OcBGvjzXpAM9iC553kXiaGPIcvNjXMV11EEtolRW/s400/04.png" alt="" id="BLOGGER_PHOTO_ID_5160336322274910626" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">Let's add some data but give the wrong file extension to our image to see how the model handles the input:</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmNdqlmDUVnvCRQ8zfgIdSUIUcefVZMjZSKbM7vmw-shyYxqaQAOz5OZoaJnWblV-dFQAqQU3d_hKQcfvEKCrJAU4pz6apbSN4hIbfk9WXSJjYpGSBmIdjGizgJPHbfuvUs6CHTdoFv7ZY/s1600-h/05.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmNdqlmDUVnvCRQ8zfgIdSUIUcefVZMjZSKbM7vmw-shyYxqaQAOz5OZoaJnWblV-dFQAqQU3d_hKQcfvEKCrJAU4pz6apbSN4hIbfk9WXSJjYpGSBmIdjGizgJPHbfuvUs6CHTdoFv7ZY/s400/05.png" alt="" id="BLOGGER_PHOTO_ID_5160336253555433874" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">The model correctly flags the badly formatted entry as an error and prints a message. Note that the message displayed is the customized message we put in our model's validation "must be a URL for a GIF, JPG, or PNG image".<br /></span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-family:arial;"><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;">Fixing the file extension allows the model to accept the presence and format of our input. By fixing this error the Model saves the movie instance as a row in our table.</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq5yDH7Py1khHeZ9nML1LkyG-0FyEX0tljYxqFQ7oWD6OytxyjmHwfW9kU7Dc5ndZvj43q7oBJR3F5OBhbVDYEKTMvxiJ-zXRo4NzdjBzfGwuZzqMSImD8gRvCuR8zyYLgFenBlv7nfeEE/s1600-h/06.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq5yDH7Py1khHeZ9nML1LkyG-0FyEX0tljYxqFQ7oWD6OytxyjmHwfW9kU7Dc5ndZvj43q7oBJR3F5OBhbVDYEKTMvxiJ-zXRo4NzdjBzfGwuZzqMSImD8gRvCuR8zyYLgFenBlv7nfeEE/s400/06.png" alt="" id="BLOGGER_PHOTO_ID_5160336167656087938" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;"><a href="http://wiki.rubyonrails.com/rails/pages/UnderstandingValidation">There are plenty</a> of <a href="http://wiki.rubyonrails.com/rails/pages/HowtoValidate">places to go</a> to learn more about validation in Ruby on Rails.</span> <span style="font-family:arial;">The <a href="http://rails.rubyonrails.com/classes/ActiveRecord/Validations.html">Rails documentation</a> is also a good resource as well as the <a href="http://rails.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html">models available</a> to do validation.</span> <span style="font-family:arial;"><br /></span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-family:arial;"><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;">Placing logic like this in the model, instead of embedding it in the logic for the screen, helps reduce duplication and ensures that all data being entered undergoes the same validation regardless of the interface used to enter the data.</span></span><span style="font-weight: bold;font-family:courier new;" > <span style="font-weight: bold;font-family:arial;" ><br /><br />The View in Rails</span><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">The view created by our scaffolding is pretty plain. Looking in the /app/views/ directory you will see two directories, layouts and movies. from the exchange directory change into the views directory and you can see them.</span><br /></span><span style="font-family:courier new;"><span style="font-family:courier new;">exchange$</span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:courier new;" > cd app/views/</span><br /></span><span style="font-family:courier new;"><span style="font-family:courier new;">exchange/app/views$</span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:courier new;" > ls -p</span> <span style="font-weight: bold;font-family:courier new;" ><br />layouts/ movies/</span><br /><span style="font-family:arial;"><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;">movies/ has files that correspond to the various pages we have used in this demo so far</span><br /></span><span style="font-family:courier new;"><span style="font-family:courier new;">exchange/app/views$</span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:courier new;" > cd movies/</span><br /></span><span style="font-family:courier new;"><span style="font-family:courier new;">exchange/app/views/movies$</span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:courier new;" > ls -p</span><br /><span style="font-weight: bold;font-family:courier new;" >edit.html.erb index.html.erb new.html.erb show.html.erb</span><br /><span style="font-family:arial;"><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;">The .html.erb extension tells us that these files are chunks of html with embedded ruby. Looking at the file show.html.erb shows the html and the embedded ruby code.</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ3sEdJi84jpGUxA35MbMQ6M14C7NT-lanO2ZyQ1E5tUmARm3qgKs4J1Phpd07-eWwdMB2DFZzbA4oU3aMPI0QxcpV37wvLjIZXiHzpfyIz5g1vpD_PcW4OU98_yg7gkrZ9FGi1z4T0Yx2/s1600-h/07.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ3sEdJi84jpGUxA35MbMQ6M14C7NT-lanO2ZyQ1E5tUmARm3qgKs4J1Phpd07-eWwdMB2DFZzbA4oU3aMPI0QxcpV37wvLjIZXiHzpfyIz5g1vpD_PcW4OU98_yg7gkrZ9FGi1z4T0Yx2/s400/07.png" alt="" id="BLOGGER_PHOTO_ID_5160336103231578482" border="0" /></a></span><span style="font-family:courier new;"> <span style="font-family:arial;">Comparing this to the successfully created entry above shows where the Title:, Description:, and One sheet url: come from in our html. The parts between the '<%=' and the '%>' are the embedded ruby code. The code here displays the title, description, and one_sheet_url of the movie instance in @movie.<br /></span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-family:arial;"><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;">The two pieces of embedded Ruby with 'link_to' at the bottom show the buttons for Edit and Back. This code is where the text 'Edit' and 'Back' come from as well a the path or action for the controller to take when the button is pressed.<br /></span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-family:arial;"><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;">For the 'Edit' action the instance @movie is also passed as a parameter.</span><br /><br /><span style="font-family:arial;">The 'h' in the '< % = h...% >' is there to strip any unwanted html and is a little beyond the discussion at this point.</span><br /><br /><span style="font-family:arial;">Comparing this to the screen you cannot see where is no place for the green text "Movie was successfully created" originates.<br /><br />The show.html.erb file is also missing the html, head, and body tags needed for a web page.</span> <span style="font-family:arial;">We'll find these in the layouts directory.</span><br /></span><span style="font-family:courier new;"><span style="font-family:courier new;">exchange/app/views/movies$</span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:courier new;" > cd ..</span><br /></span><span style="font-family:courier new;"><span style="font-family:courier new;">exchange/app/views$</span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:courier new;" > cd layouts/</span><br /></span><span style="font-family:courier new;"><span style="font-family:courier new;">exchange/app/views/layouts$</span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:courier new;" > ls -p</span><br /><span style="font-weight: bold;font-family:courier new;" >movies.html.erb</span><br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5bHJXoulcAbgI7LXPMG9M6Z-RNwA7T3Plrj0penXgzqBYdJjJC7YeK7dsnLcyJyB7r1m_bhsqbS9eK2Sq7IdgcjLZ18pfLb49T8WZgn8EcaxoEPAZa1x491O1TL5_znmYKRt2W3zr9-rL/s1600-h/08.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5bHJXoulcAbgI7LXPMG9M6Z-RNwA7T3Plrj0penXgzqBYdJjJC7YeK7dsnLcyJyB7r1m_bhsqbS9eK2Sq7IdgcjLZ18pfLb49T8WZgn8EcaxoEPAZa1x491O1TL5_znmYKRt2W3zr9-rL/s400/08.png" alt="" id="BLOGGER_PHOTO_ID_5160336004447330658" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">The scaffolding has created a default layout for the movie view called movies.html.erb. This file contains the parts needed to build a valid web page including our DOCTYPE, title, html, head and body tags, as well as where the color green came from for the friendly notice "Movie was successfully created".</span><br /><br /><span style="font-family:arial;">The <%= yield %> is where the chunks of html from the files under the /views directory go when a page is built for display. </span> <span style="font-family:arial;">The controller matches the chunk of html from the views/ directory to the action. Listing all of the movies uses the index.html.erb file, creating a new movie uses the</span><span style="font-family:arial;"> new.html.erb file, editing an existing movie uses the edit.html.erb file, and showing one existing movie uses the show.html.erb file.</span> <span style="font-family:arial;"><br /><br />Also note that our original web page uses a css stylesheet called 'scaffold'.</span> <span style="font-family:arial;"><br /><br /></span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:arial;" >Customized View</span> <span style="font-size:85%;"><span style="font-family:arial;"><span style="font-weight: bold;"><br />Side Note:</span> </span></span></span><span style="font-family:courier new;"><span style="font-size:85%;"><span style="font-family:arial;">I spend most of my professional time optimizing queries. Sounds exciting, I know. I don't have the gene for good design, so I'll keep it simple. There are plenty of people in the Rails community with great design ideas so there are plenty of better places for you to go to get layout tips. </span></span> <span style="font-family:arial;"><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;"><br />Add some div id tags to our page and create a simple stylesheet. First change the movies.html.erb</span></span><span style="font-weight: bold;font-family:courier new;" ><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtBcxSMCO8Fsjl_ZWiYUq9xuA_lTHvhSgAnQCEy4IvhIGNvuJ40pNrez6_LMPj3irXRqOXGXYcpcELDTwAjP0Jcpo68zvsWAQdlwQKU9JjacDpFRbEoEd-BsfJkk-Nhv0prlzNTNdoY6lh/s1600-h/09.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtBcxSMCO8Fsjl_ZWiYUq9xuA_lTHvhSgAnQCEy4IvhIGNvuJ40pNrez6_LMPj3irXRqOXGXYcpcELDTwAjP0Jcpo68zvsWAQdlwQKU9JjacDpFRbEoEd-BsfJkk-Nhv0prlzNTNdoY6lh/s400/09.png" alt="" id="BLOGGER_PHOTO_ID_5160335897073148242" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">The scaffold command created a stylesheet in the directory /exchange/public/stylesheets called scaffold.css. Create one called exchange.css that looks like</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><span style="font-weight: bold;font-family:courier new;" >/* Global styles */<br />/* START:notice */<br />#notice {<br />border: 2px solid red;<br />padding: 1em;<br />margin-bottom: 2em;</span><br /><span style="font-weight: bold;font-family:courier new;" > background-color: #f0f0f0;<br />font: bold smaller sans-serif;<br />}<br />/* END:notice */<br />/* Styles for main page */<br />#banner {<br />background: #0099cc;<br />padding-top: 10px;<br />padding-bottom: 20px;<br />border-bottom: 4px solid;<br />/* font: small-caps 50px/50px "Times New Roman", serif; */</span><br /><span style="font-weight: bold;font-family:courier new;" > font: small-caps 50px/50px serif;<br />color: #000080;<br />text-align: center;<br />}<br />#banner img {<br />float: left;<br />}<br />#columns {<br />background: #9999ff;</span><br /><span style="font-weight: bold;font-family:courier new;" >}<br />#main {<br />margin-left: 12em;<br />padding-top: 4ex;<br />padding-left: 2em;<br />background: white;<br />}<br />#side {<br />float: left;</span><br /><span style="font-weight: bold;font-family:courier new;" > padding-top: 1em;<br />padding-left: 1em;<br />padding-bottom: 1em;<br />width: 10em;<br />background: #9999ff;<br />}<br />#side a {<br />color: #00ffff;<br />font-size: small;</span><br /><span style="font-weight: bold;font-family:courier new;" >}<br />h1 {<br />font: 150% sans-serif;<br />color: #226;<br />border-bottom: 3px dotted #77d;<br />}</span><br /><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">Starting script/server and pointing your browser to http://localhost:3000/movies should give you something like this</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP-xRTK2DEtOpgHYSULM0TCfSiY5EQCeZq3ifjnqaiSiY0z4EbEqvFBsw30IrDC7gaelYstETIPqWIcsaIqceKOFKcQ1Oj9pkrlPEdAI-iaoAwgywzAHLnhTaPGCiromTjsKpiEkMLlS5a/s1600-h/10.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP-xRTK2DEtOpgHYSULM0TCfSiY5EQCeZq3ifjnqaiSiY0z4EbEqvFBsw30IrDC7gaelYstETIPqWIcsaIqceKOFKcQ1Oj9pkrlPEdAI-iaoAwgywzAHLnhTaPGCiromTjsKpiEkMLlS5a/s400/10.png" alt="" id="BLOGGER_PHOTO_ID_5160335815468769602" border="0" /></a></span><span style="font-family:courier new;"> <span style="font-family:arial;">It looks a little nicer, but the listing can be made nicer and we can save some duplication in the edit and new pages with a partial form. (The rails.png logo was put in the /exchange/public/images directory by the rails command when our app was created).</span> <span style="font-family:arial;"><br /></span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:arial;" ><br />Partials</span><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">If you compare the new.html.erb and the edit.html.erb files you will see that they are almost exactly the same.<br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;"><br />Look at the do loop between the <% form_for(@movie) do |f| %> and <% end %> and the only difference is the text passed in the line with 'f.submit'. The new page has the text "Create" and the edit page has the text "Update".<br /><br />Make a copy of this section from either file and paste it in a file called _form.html.erb in the same views directory. </span><br /><span style="font-family:arial;"><br />Edit the text passed in the 'f.submit' line and use a variable named label_text instead so the /exchange/app/views/movies/_form.html.erb file looks like this</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKhHyvc2J-lH-wAC0Q2l6FUd0vwjCh1ze9pkkjUaTMfMzoZDN_moZTMobnV-rbjqf9fT3jVysajPR_uXwnAXlYrcqp6bBqLAuVuFC6toGn2UEPSG5M-2Ec4-_KFiy5OKG8KIfwct3eixdU/s1600-h/11.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKhHyvc2J-lH-wAC0Q2l6FUd0vwjCh1ze9pkkjUaTMfMzoZDN_moZTMobnV-rbjqf9fT3jVysajPR_uXwnAXlYrcqp6bBqLAuVuFC6toGn2UEPSG5M-2Ec4-_KFiy5OKG8KIfwct3eixdU/s400/11.png" alt="" id="BLOGGER_PHOTO_ID_5160335729569423666" border="0" /></a></span><span style="font-family:courier new;"><span style="font-family:arial;">The variable label_text will be passed in from the edit or new pages with the correct value inside. </span> <span style="font-family:arial;">Make the edit.html.erb page look like this<br /></span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-family:arial;"><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI_gxJrrrTq4kFFPDbEHkuzKP88883KG-z9kDrZaoW5kBJh9AYItRX1zZ_1OvTtu4I8Y4LGAutsWxmHXzoZxE7pu-s7ZVIhljjUPd4rzPmNYn798w4dMAI_EXvsggqmBv75S1EjnZvPbFn/s1600-h/12.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI_gxJrrrTq4kFFPDbEHkuzKP88883KG-z9kDrZaoW5kBJh9AYItRX1zZ_1OvTtu4I8Y4LGAutsWxmHXzoZxE7pu-s7ZVIhljjUPd4rzPmNYn798w4dMAI_EXvsggqmBv75S1EjnZvPbFn/s400/12.png" alt="" id="BLOGGER_PHOTO_ID_5160335639375110434" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">Everything between the form_for do and the end is replaced with the one line</span></span><span style="font-weight: bold;font-family:courier new;" ><br /><span style="font-size:85%;"><span style="font-weight: bold;font-family:courier new;" ><%= render :partial => "form", :locals => { :f => f, :label_text => "Update"} %></span></span><br /><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">Similarly , edit the new.html.erb file so it looks like</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifrHC23ncBOFyyE73xAIkUtH_LfY_vdPw0MumnlKxmXuFFGAkmh-wDJVcyDBk7iNy6IDzTn1yKW0Ah72zEgsbhe2HtZtVyVPcDPsB-Jfl-Qy8tEesJRk0hr-aKSlS3D51Ao8JxgWLi7ubn/s1600-h/13.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifrHC23ncBOFyyE73xAIkUtH_LfY_vdPw0MumnlKxmXuFFGAkmh-wDJVcyDBk7iNy6IDzTn1yKW0Ah72zEgsbhe2HtZtVyVPcDPsB-Jfl-Qy8tEesJRk0hr-aKSlS3D51Ao8JxgWLi7ubn/s400/13.png" alt="" id="BLOGGER_PHOTO_ID_5160335557770731794" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">This will render the partial _form and pass it the local variables and the variable label_text with either the value "Create" or "Update". Let's see if it works by editing one of our existing movies.</span></span><span style="font-weight: bold;font-family:courier new;" ><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjco9oFQVcjy3etATlJ6F8rQvKl7HSo0ygzCSyjno72mNYCHsNh82zgiSdhaOYfQnmMwUW5SSzIIMlvOAjZimlgjs6zibqz8ViiwFqBmMSINaIrCYoX2pSw6qeV240TckhXylmKsT73ebez/s1600-h/14.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjco9oFQVcjy3etATlJ6F8rQvKl7HSo0ygzCSyjno72mNYCHsNh82zgiSdhaOYfQnmMwUW5SSzIIMlvOAjZimlgjs6zibqz8ViiwFqBmMSINaIrCYoX2pSw6qeV240TckhXylmKsT73ebez/s400/14.png" alt="" id="BLOGGER_PHOTO_ID_5160335467576418562" border="0" /></a></span><span style="font-family:courier new;"><br /><span style="font-family:arial;">Things look the same as before, which is exactly what we wanted.</span><br /><br /><span style="font-family:arial;">Creating a new movie also continues to work as before</span><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNbzzu-3mzSSZ73uEJnVEqzZhQ-0waf6OvfgtTaIZVxvUPHXc3-KwUrTvcJElYFJC1mp4ykyPdFjWv_9RLiUjsbCKx2rnEOe71qhJ7o-9arDQvB51w2ZY87flbOqzLdjCaSqEbNirnJnKc/s1600-h/15.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNbzzu-3mzSSZ73uEJnVEqzZhQ-0waf6OvfgtTaIZVxvUPHXc3-KwUrTvcJElYFJC1mp4ykyPdFjWv_9RLiUjsbCKx2rnEOe71qhJ7o-9arDQvB51w2ZY87flbOqzLdjCaSqEbNirnJnKc/s400/15.png" alt="" id="BLOGGER_PHOTO_ID_5160335055259558130" border="0" /></a><br /><span style="font-weight: bold;font-family:arial;" >Making a list, checking it twice</span><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">let's make the listing look a little more organized. </span> <span style="font-family:arial;">Edit the index.html.erb file so it looks like this:<br /><br /><pre><blockquote><br /><tt><br /><div id="movie-list"><br /><h1>Movie Listing</h1><br /><br /><table cellpadding="5" cellspacing="0"><br /><% for movie in @movies %><br /><tr valign="top" class="<%= cycle('list-line-odd', 'list-line-even') %>"><br /><br /> <td><br /> <img class="list-one-sheet" src="<%= movie.one_sheet_url %>"/><br /> </td><br /><br /> <td width="60%"><br /> <span class="list-title"><%= h(movie.title) %></span><br /><br /> <%= h(truncate(movie.description, 80)) %><br /> </td><br /><br /> <td class="list-actions"><br /> <%= link_to 'Show', movie %><br /> <%= link_to 'Edit', edit_movie_path(movie) %><br /> <%= link_to 'Destroy', movie, :confirm => 'Are you sure?', :method => :delete %><br /> </td><br /></tr><br /><% end %><br /></table><br /></div><br /><br /><br /><%= link_to 'New movie', :action => 'new' %><br /></tt></blockquote></pre><br /><br /><br /><br /></span></span><span style="font-weight: bold;font-family:courier new;" ><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">Then add a section to the exchange.css file for our movie-list div id tag that looks like<br /><br /></span></span><span style="font-weight: bold;font-family:courier new;" ><span style="font-weight: bold;font-family:courier new;" >#movie-list .list-title {<br />color: #244;<br />font-weight: bold;<br />font-size: larger;<br />}<br /><br />#movie-list .list-one-sheet {<br />width: 60px;<br />height: 70px;<br />}<br /><br /><br />#movie-list .list-actions {<br />font-size: x-small;<br />text-align: right;<br />padding-left: 1em;<br />}<br /><br />#movie-list .list-line-even {<br />background: #ffccff;<br />}<br /><br />#movie-list .list-line-odd {<br />background: #d0d0d0;<br />}<br /><br /></span><span style="font-weight: bold;font-family:courier new;" ><br /><br /></span></span><span style="font-family:courier new;"><span style="font-family:arial;">The index.html.erb file should now render a page that looks like</span></span><span style="font-weight: bold;font-family:courier new;" ><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuHCZj5Ot03_7IO6lD31TOebILO2eNaCpLxjDLNPmv_J1XHxW8mi-8uHPnkcw6Dh3ir4feV2biDW0E04Dcb9gm7b36lFHnT2CxzA9fn06GizlCEmy1F8zuR-wijrnjjYQ45CnkvoJ29jjc/s1600-h/17.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuHCZj5Ot03_7IO6lD31TOebILO2eNaCpLxjDLNPmv_J1XHxW8mi-8uHPnkcw6Dh3ir4feV2biDW0E04Dcb9gm7b36lFHnT2CxzA9fn06GizlCEmy1F8zuR-wijrnjjYQ45CnkvoJ29jjc/s400/17.png" alt="" id="BLOGGER_PHOTO_ID_5160334827626291410" border="0" /></a><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">here are a few one sheet images for you to play with (you might have to rename them)</span></span><span style="font-weight: bold;font-family:courier new;" >.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ_NMIJC6jmI4srNClHpW7Nu4ppOdt2aK60wMc0IYTUSGLtKN6LRJvAKITM4xeIyYIstEMb2evKBUVDSqckADL1miUVqRVmrvKbxdMVtPEfWB7QZ2aWR8K3MVoMOu4uChqLoru3We_BR_o/s1600-h/MITWS1.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ_NMIJC6jmI4srNClHpW7Nu4ppOdt2aK60wMc0IYTUSGLtKN6LRJvAKITM4xeIyYIstEMb2evKBUVDSqckADL1miUVqRVmrvKbxdMVtPEfWB7QZ2aWR8K3MVoMOu4uChqLoru3We_BR_o/s400/MITWS1.jpg" alt="" id="BLOGGER_PHOTO_ID_5160343739683430930" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAnsAjjq0mKu1ZMaciHTgvwvPR6LG3EdqkFbgED4WR8H9fxGrTVl1cjUREngOObECLjhphimslydaFT3hNixHq_u1q5SfHc88d9Mq8EPPivc1tzC9w565WpsaywyqvtMXKd5SGCMmyxMJg/s1600-h/BHT1.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAnsAjjq0mKu1ZMaciHTgvwvPR6LG3EdqkFbgED4WR8H9fxGrTVl1cjUREngOObECLjhphimslydaFT3hNixHq_u1q5SfHc88d9Mq8EPPivc1tzC9w565WpsaywyqvtMXKd5SGCMmyxMJg/s400/BHT1.jpg" alt="" id="BLOGGER_PHOTO_ID_5160343649489117698" border="0" /></a><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9SdiYhAYYnNJ5m776tzoi_2F7-09OnAH4GW_DJHpLfq-8H2Ko88NBJgBEIbpN9H3TnOCG2ysev3gr3-yNmDB5cchprfEj7SyyIFLSt6IqnV8T2sThJbv8kM-5yqNqjSP2dTqjwk1J7r3A/s1600-h/BJ1.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9SdiYhAYYnNJ5m776tzoi_2F7-09OnAH4GW_DJHpLfq-8H2Ko88NBJgBEIbpN9H3TnOCG2ysev3gr3-yNmDB5cchprfEj7SyyIFLSt6IqnV8T2sThJbv8kM-5yqNqjSP2dTqjwk1J7r3A/s400/BJ1.jpg" alt="" id="BLOGGER_PHOTO_ID_5160343559294804466" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKZHyZ8K7uqqXwznpAZ76SMCG8AzGpSwdRTCop8gDE-NnA-qYart09OVV0FcyLkfdzHmZ55Hcs5fioPzKYf5LmEt8-Qbq1ojvDBfi8UhWDfZO3BghAucm9fMpTD_UkH_-OQEVhhGW1ZklW/s1600-h/TROLL1.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKZHyZ8K7uqqXwznpAZ76SMCG8AzGpSwdRTCop8gDE-NnA-qYart09OVV0FcyLkfdzHmZ55Hcs5fioPzKYf5LmEt8-Qbq1ojvDBfi8UhWDfZO3BghAucm9fMpTD_UkH_-OQEVhhGW1ZklW/s400/TROLL1.jpg" alt="" id="BLOGGER_PHOTO_ID_5160343477690425826" border="0" /></a><br /><br /><br /></span><span style="font-family:courier new;"><span style="font-family:arial;">Copies of these images should be placed in the /exchange/public/images/ directory.</span><br /><br /><span style="font-family:arial;">What has been done so far?</span><br /><ul><li><span style="font-family:arial;"> Reviewed the Model View Controller design pattern</span></li><li><span style="font-family:arial;"> Added validation rules to our model</span></li><li><span style="font-family:arial;"> Added a banner and sidebar to our pages</span></li><li><span style="font-family:arial;"> Created a style sheet for our app</span></li><li><span style="font-family:arial;"> Used a partial form to get rid of code duplication</span></li><li><span style="font-family:arial;"> made a prettier listing for our main index page</span></li><li><span style="font-family:arial;"> added some graphics to the /public/images directory</span></li></ul><br /><br /><span style="font-family:arial;">Next time I'll look at the controller and a Rails 2.0 trick for adding new columns in a migration.</span></span>Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com192tag:blogger.com,1999:blog-1525178018811356129.post-61035354126872182742007-12-15T08:32:00.000-06:002008-12-09T03:21:54.339-06:00Rails 2.0 and Scaffolding Step by Step<span style="font-size:180%;"><span style="font-weight: bold;">Rails 2.0 step by step.<br /></span><span><span style="font-size:100%;"><br /><span style="font-size:100%;"></span></span></span></span><ul><li><span style="font-size:100%;"><span><a href="http://fairleads.blogspot.com/2008/01/this-is-second-part-of-my-series.html">Part 2 is here</a></span></span></li></ul><span style="font-size:180%;"><span style="font-weight: bold;"><br /></span></span><a href="http://www.rubyonrails.org/">Ruby on Rails 2.0 </a>was released by the Rails core team on <a href="http://www.37signals.com/svn/posts/734-rails-20">Friday, December 7th</a>. There were <a href="http://ryandaigle.com/articles/2007/12/7/rails-2-0-final-released-summary-of-features">quite a few changes </a> in the 2.0 release, including the way that Rails generates scaffolding code. This change will probably cause trouble for people using tutorials written for previous versions of Rails. I hope this tutorial will help readers get started with Rails 2.0 and keep the community of Rails developers growing.<br /><br />This is the first part of a multi-part tutorial. It will cover enough to get a scaffolded Rails application up and running under Rails 2.0.<br /><br />This first installment of the tutorial will cover installing Rails and then using Rails to generate a new scaffolded application capable of the four basic database functions of creating, reading, updating, and deleting data. Later installments will cover replacement of scaffolding with actual code that will add to the model view and controller portions of the Rails application. The goal of this first part of the tutorial is to get new users over the changes made to scaffolding in Rails 2.0, and get the basic scaffolded application up and running.<br /><br />Rails has proven itself to been excellent choice for the needs of most teams and projects.<br /><br /><span style="font-weight: bold;">Note:</span>If you are following a detailed tutorial or book based on earlier rails version, it would probably be best to install an earlier version of Rails for use with that book. For example, the book <a href="http://www.pragprog.com/titles/rails2">Agile Web Development with Rails (AWDWR)</a> by Dave Thomas and David Heinemeier Hansson is based on Rails 1.2.x. Instructions on how to install an earlier version of Rails are given later in this tutorial.<br /><br />Use this tutorial to get started with Rails 2.0 and not older versions.<br /><br />You will need to have MySQL installed on your system to follow along with this tutorial. <a href="http://www.mysql.com/">You can search the web</a> for the best way to install MySQL on your system, It won't be covered here.<br /><br /><span style="font-weight: bold;font-size:130%;" >Installing Rails 2.0</span><br />Installing Rails 2.0 is done the same way as in 1.2.x versions of rails. There are basically three steps to follow.<ul><li>Install Ruby for your Distro or OS</li><li>Download and install Ruby gems</li><li>Use gems to install rails</li></ul>the <a href="http://www.rubyonrails.org/down">Get Rails</a> link and <a href="http://wiki.rubyonrails.org/rails/pages/GettingStartedWithRails">the getting started with rails</a> link have the best available information. Follow these links to get Rails installed on your system.<br /><br />On my debian machine I used the following commands to install Rails 2.0.<br /><br /><span style="font-weight: bold;">Install Ruby:</span><br />Change to the superuser and use the debian package manager to install ruby<br /><span style="font-family:courier new;">#</span><span style="font-weight: bold;font-family:courier new;" > apt-get install ruby irb ri rdoc build-essential<br /></span><br /><span style="font-weight: bold;">Install Ruby gems:</span><br />Then <a href="http://rubyforge.org/frs/?group_id=126">download Ruby gems</a>, the ruby package management software, unpack it, change into the rubygems directory and run the file setup.rb as superuser:<br /><span style="font-family:courier new;">$</span><span style="font-weight: bold;font-family:courier new;" > tar -xvzf rubygems-0.9.5.tgz</span><br /><span style="font-family:courier new;">$</span><span style="font-weight: bold;font-family:courier new;" > cd rubygems-0.9.5</span><br /><span style="font-family:courier new;">$</span><span style="font-weight: bold;font-family:courier new;" > su</span><br /><span style="font-family:courier new;">#</span><span style="font-weight: bold;font-family:courier new;" > ruby ./setup.rb<br /></span><br /><span style="font-weight: bold;">Use gems to install Rails:</span><br />The gem package manager can install Rails and all of its dependencies. As superuser issue the command:<br /><span style="font-family:courier new;">#</span><span style="font-weight: bold;font-family:courier new;" > gem install rails --include-dependencies<br /></span><span style="font-weight: bold;font-family:courier new;" >INFO: `gem install -y` is now default and will be removed<br /></span><span style="font-weight: bold;font-family:courier new;" >INFO: use --ignore-dependencies to install only the gems you list<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed rake-0.7.3<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed activesupport-2.0.1<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed activerecord-2.0.1<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed actionpack-2.0.1<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed actionmailer-2.0.1<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed activeresource-2.0.1<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed rails-2.0.1<br /></span><span style="font-weight: bold;font-family:courier new;" >7 gems installed<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing ri documentation for rake-0.7.3...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing ri documentation for activesupport-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing ri documentation for activerecord-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing ri documentation for actionpack-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing ri documentation for actionmailer-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing ri documentation for activeresource-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing RDoc documentation for rake-0.7.3...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing RDoc documentation for activesupport-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing RDoc documentation for activerecord-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing RDoc documentation for actionpack-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing RDoc documentation for actionmailer-2.0.1...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing RDoc documentation for activeresource-2.0.1...<br /></span><br />Checking the version of Rails at the command line should give a version number for Rails:<br /><span>$ </span><span style="font-weight: bold;">rails -v<br /></span><span style="font-weight: bold;">Rails 2.0.1</span><br /><br />If you have trouble installing Rails follow the links above or go to the <a href="http://www.railsforum.com/">Rails Forum</a> for help.<br /><br /><span style="font-weight: bold;">Using older versions</span><br />If you are using a book like <a href="http://pragprog.com/titles/rails2">AWDWR from the pragmatic programmers</a> It would probably be best to use an earlier version of Rails. To install a previous version of Rails, use the following command:<br /><span style="font-family:courier new;">#</span><span style="font-weight: bold;font-family:courier new;" > gem install --version=1.2.5 rails --include-dependencies<br /></span><span style="font-weight: bold;font-family:courier new;" >INFO: `gem install -y` is now default and will be removed<br /></span><span style="font-weight: bold;font-family:courier new;" >INFO: use --ignore-dependencies to install only the gems you list<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed activerecord-1.15.5<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed actionpack-1.13.5<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed actionmailer-1.3.5<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed actionwebservice-1.2.5<br /></span><span style="font-weight: bold;font-family:courier new;" >Successfully installed rails-1.2.5<br /></span><span style="font-weight: bold;font-family:courier new;" >5 gems installed<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing ri documentation for activerecord-1.15.5...<br /></span><span style="font-weight: bold;font-family:courier new;" >Installing ri documentation for actionpack-1.13.5...<br /></span><span style="font-weight: bold;font-family:courier new;" >...<br /></span><br /><span style="font-family:courier new;">$</span><span style="font-weight: bold;font-family:courier new;" > rails -v<br /></span><span style="font-weight: bold;font-family:courier new;" >Rails 1.2.5</span><br /><br /><span style="font-weight: bold;">Updating old versions of Rails</span><br />In order to update an older version of Rails to the most current, use the gem command:<br /><span style="font-family:courier new;">$</span><span style="font-weight: bold;font-family:courier new;" > gem update rails –-include-dependencies<br /></span><br />Now let's see how we can get a basic Rails application up and running with a few commands<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Using Rails 2.0</span><br /><br /></span><span style="font-weight: bold;">Getting started and checking out our installation</span><br />Creating a new project in Rails 2.0 starts out much like previous versions. This tutorial uses the example of creating an application to manage the inventory at a local Mom and Pop video rental store, Mom and Pop's Movie Exchange. We'll call the project 'exchange'.<br /><br />We'll create a directory to keep our work in, change to that directory and use the 'rails' command to create the shell for the exchange application. A great deal of information will flash by on your terminal as Rails creates the basic structure of the application.<br /><span style="font-family:courier new;">$</span><span style="font-weight: bold;font-family:courier new;" > mkdir work<br /></span><span style="font-family:courier new;">$</span><span style="font-weight: bold;font-family:courier new;" > cd work<br /></span><span style="font-family:courier new;">work$</span><span style="font-weight: bold;font-family:courier new;" > rails exchange<br /></span><span style="font-weight: bold;font-family:courier new;" >create<br /></span><span style="font-weight: bold;font-family:courier new;" >create app/controllers<br /></span><span style="font-weight: bold;font-family:courier new;" >create app/helpers<br /></span><span style="font-weight: bold;font-family:courier new;" >create app/models<br /></span><span style="font-weight: bold;font-family:courier new;" >create app/views/layouts<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/environments<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/initializers<br /></span><span style="font-weight: bold;font-family:courier new;" >create db<br /></span><span style="font-weight: bold;font-family:courier new;" >create doc<br /></span><span style="font-weight: bold;font-family:courier new;" >create lib<br /></span><span style="font-weight: bold;font-family:courier new;" >create lib/tasks<br /></span><span style="font-weight: bold;font-family:courier new;" >create log<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/images<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/javascripts<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/stylesheets<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/performance<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/process<br /></span><span style="font-weight: bold;font-family:courier new;" >create test/fixtures<br /></span><span style="font-weight: bold;font-family:courier new;" >create test/functional<br /></span><span style="font-weight: bold;font-family:courier new;" >create test/integration<br /></span><span style="font-weight: bold;font-family:courier new;" >create test/mocks/development<br /></span><span style="font-weight: bold;font-family:courier new;" >create test/mocks/test<br /></span><span style="font-weight: bold;font-family:courier new;" >create test/unit<br /></span><span style="font-weight: bold;font-family:courier new;" >create vendor<br /></span><span style="font-weight: bold;font-family:courier new;" >create vendor/plugins<br /></span><span style="font-weight: bold;font-family:courier new;" >create tmp/sessions<br /></span><span style="font-weight: bold;font-family:courier new;" >create tmp/sockets<br /></span><span style="font-weight: bold;font-family:courier new;" >create tmp/cache<br /></span><span style="font-weight: bold;font-family:courier new;" >create tmp/pids<br /></span><span style="font-weight: bold;font-family:courier new;" >create Rakefile<br /></span><span style="font-weight: bold;font-family:courier new;" >create README<br /></span><span style="font-weight: bold;font-family:courier new;" >create app/controllers/application.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create app/helpers/application_helper.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create test/test_helper.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/database.yml<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/routes.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/.htaccess<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/initializers/inflections.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/initializers/mime_types.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/boot.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/environment.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/environments/production.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/environments/development.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create config/environments/test.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/about<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/console<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/destroy<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/generate<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/performance/benchmarker<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/performance/profiler<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/performance/request<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/process/reaper<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/process/spawner<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/process/inspector<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/runner<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/server<br /></span><span style="font-weight: bold;font-family:courier new;" >create script/plugin<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/dispatch.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/dispatch.cgi<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/dispatch.fcgi<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/404.html<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/422.html<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/500.html<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/index.html<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/favicon.ico<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/robots.txt<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/images/rails.png<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/javascripts/prototype.js<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/javascripts/effects.js<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/javascripts/dragdrop.js<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/javascripts/controls.js<br /></span><span style="font-weight: bold;font-family:courier new;" >create public/javascripts/application.js<br /></span><span style="font-weight: bold;font-family:courier new;" >create doc/README_FOR_APP<br /></span><span style="font-weight: bold;font-family:courier new;" >create log/server.log<br /></span><span style="font-weight: bold;font-family:courier new;" >create log/production.log<br /></span><span style="font-weight: bold;font-family:courier new;" >create log/development.log<br /></span><span style="font-weight: bold;font-family:courier new;" >create log/test.log<br /></span><br />Rails generates an entire framework for the application. Change into the newly created exchange directory and get to work.<br /><span style="font-family:courier new;">work$</span><span style="font-weight: bold;font-family:courier new;" > cd exchange<br /></span><span style="font-family:courier new;">exchange$</span><span style="font-weight: bold;font-family:courier new;" > ls -p<br /></span><span style="font-weight: bold;font-family:courier new;" >app/ db/ lib/ public/ README test/ vendor/<br /></span><span style="font-weight: bold;font-family:courier new;" >config/ doc/ log/ Rakefile script/ tmp/<br /></span><span style="font-weight: bold;"><br />Setting up the Model and Database Table<br /></span>At this point many web frameworks would have to use database commands and DDL's to create the table we need to hold our movie inventory data, but thanks to Rails tight coupling between the data and the application we can use Rails to create and manage the tables our project will need. In the Model-View-Controller pattern of application design it's the model that regulates access to the data.<br /><br />Rails can create the database and tables needed for the exchange project. Look at the file /exchange/config/database.yml, in it you can see the structure of the databases used in Rails:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz5dKdxsXCXYZ1NuQQCTh9NH4PIvs9j4HUCFMs3SolS1kVpIIaZRR9bDo03LcZXz9X0G_ogRJSMSS6a15JxK26zqaXaV-RaWmoVsgW5LyDRr6QFqIQ44fkuJ-dfKkvSp6y6YXUpCH9bf6k/s1600-h/databaseyaml1.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 448px; height: 310px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz5dKdxsXCXYZ1NuQQCTh9NH4PIvs9j4HUCFMs3SolS1kVpIIaZRR9bDo03LcZXz9X0G_ogRJSMSS6a15JxK26zqaXaV-RaWmoVsgW5LyDRr6QFqIQ44fkuJ-dfKkvSp6y6YXUpCH9bf6k/s400/databaseyaml1.png" alt="" id="BLOGGER_PHOTO_ID_5144214234159515170" border="0" /></a><br /><br /><picture here="">You can see that there are separate tables for development testing and production. This separation helps in the development and mainte</picture><picture here="">nance of Rails projects.<br /><br />In a difference from earlier Rails versions, Rails 2.0 will create the databases needed with the</picture><picture here=""> command:</picture><br /><picture here="">exchange$</picture><picture style="font-weight: bold;" here=""> rake db:create:all<br /></picture><picture style="font-weight: bold;" here="">(in /home/sean01/work/exchange)<br /></picture><picture here="">exchange$</picture><br /><picture here=""><br /><span style="font-weight: bold;">Starting the web server</span><br />Rails includes its own web server, so let's fire it up and see if we have everything working so far.</picture><picture here=""> To start the rails webserver, WEBbrick, use the command:<br /><span style="font-family:courier new;">exchange$</span><span style="font-weight: bold;font-family:courier new;" > ruby script/server<br /></span></picture><picture style="font-family: courier new; font-weight: bold;" here="">=> Booting WEBrick...<br />=> Rails application started on http://0.0.0.0:3000<br /></picture><picture style="font-family: courier new; font-weight: bold;" here="">=> Ctrl-C to shutdown server; call with --help for options<br /></picture><picture style="font-family: courier new; font-weight: bold;" here="">[2007-12-13 12:01:16] INFO WEBrick 1.3.1<br /></picture><picture style="font-family: courier new; font-weight: bold;" here="">[2007-12-13 12:01:16] INFO ruby 1.8.5 (2006-08-25) [i486-linux]<br />[2007-12-13 12:01:16] INFO WEBrick::HTTPServer#start: pid=3637 port=3000</picture><br /><picture here=""><br />open your favorite browser and point torwards the URL http://localhost:3000<br />You should see something like:<br /><br /><picture here=""></picture></picture><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixNKPLiGhcDnlrkBUG2kErIFjG49H0y24nmPc6O4nfRSVNBosb2pWDLjd7UkjAuegphglfhyphenhyphenDygb96-L7cvgyn5x8EdT2Qm2Mqfu45RaDP4bN85495ZGzy72nf1RXW15pZ-RiNrKgS-1bz/s1600-h/railswelcome1.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixNKPLiGhcDnlrkBUG2kErIFjG49H0y24nmPc6O4nfRSVNBosb2pWDLjd7UkjAuegphglfhyphenhyphenDygb96-L7cvgyn5x8EdT2Qm2Mqfu45RaDP4bN85495ZGzy72nf1RXW15pZ-RiNrKgS-1bz/s400/railswelcome1.png" alt="" id="BLOGGER_PHOTO_ID_5144215312196306482" border="0" /></a><br /><picture here=""><picture here=""><br /><br />Clicking on the 'About your application's environment' link will activate a little piece of AJAX code that lists the particulars of your rails application.</picture></picture><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOG9ZoGMUT_hB0qiHWPwo7wlfuUN6Di9OabtsBydBrbg_I9irIilaX4R2g20ecKAB8innUlky1SD4C7UHAUXpptuCRhTE2fOo74WGqAkOM3v_8VNSBYQ4qWjnhZxjSwRwZcKmJgGW7_QH-/s1600-h/railswelcome2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOG9ZoGMUT_hB0qiHWPwo7wlfuUN6Di9OabtsBydBrbg_I9irIilaX4R2g20ecKAB8innUlky1SD4C7UHAUXpptuCRhTE2fOo74WGqAkOM3v_8VNSBYQ4qWjnhZxjSwRwZcKmJgGW7_QH-/s400/railswelcome2.png" alt="" id="BLOGGER_PHOTO_ID_5144216544851920450" border="0" /></a><br /><picture here=""><picture here=""><picture here=""><br />Notice that the default environment is development and not testing or production. This is just what we want during our development phase!<br /></picture></picture></picture><br /><picture here=""><picture here=""><picture here="">A ctrl-c in the terminal where the WEBbrick server is running will kill the server.</picture></picture></picture><br /><br /><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Old vs. New</span></picture></picture></picture><picture here=""><picture here=""><picture here=""><br />The next steps show where differences between older Rails tutorials will become greatest. Older tutorials would script/generate a model then use the migrate file created to layout columns in the model's database table. Next you would script/generate a controller and add scaffolding.</picture></picture></picture><picture here=""><picture here=""><picture here=""> This will fail in Rails 2.0.<br /><br />In Rails 2.0 it will take fewer steps, but may be a little harder to follow because so much is accomplished with so few commands. First we need to think about the movie inventory table.</picture></picture></picture><br /><br /><picture here=""><picture here=""><picture here="">Start simple. Movies should have, at minimum a title, a description and a movie poster. Columns for other data like release date, rating or quantity on hand can be added later by altering the</picture></picture></picture><picture here=""><picture here=""><picture here=""> table through migrations. The next step is to create a model whose job will be to manage the data stored in the database.<br /><br />The following command will generate the model, plus scaffolding, and the database migration</picture></picture></picture><picture here=""><picture here=""><picture here=""> script needed as well as a controller, helper, and testing support files:<br /><br /><span style="font-family:courier new;">exchange$</span><span style="font-weight: bold;font-family:courier new;" > ruby script/generate scaffold Movie title:string description:text one_sheet_url:string</span><br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">exists app/models/<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">exists app/controllers/<br />exists app/helpers/<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create app/views/movies<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">exists app/views/layouts/<br />exists test/functional/<br />exists test/unit/<br />create app/views/movies/index.html.erb<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create app/views/movies/show.html.erb<br />create app/views/movies/new.html.erb<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create app/views/movies/edit.html.erb<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create app/views/layouts/movies.html.erb<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create public/stylesheets/scaffold.css dependency model<br />exists app/models/<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">exists test/unit/<br />exists test/fixtures/<br />create app/models/movie.rb<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create test/unit/movie_test.rb<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create test/fixtures/movies.yml<br /></picture></picture></picture><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create db/migrate<br />create db/migrate/001_create_movies.rb</picture></picture></picture><br /><picture style="font-family: courier new; font-weight: bold;" here=""><picture here=""><picture here="">create app/controllers/movies_controller.rb<br /></picture></picture></picture><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;font-family:courier new;" >create test/functional/movies_controller_test.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >create app/helpers/movies_helper.rb<br /></span><span style="font-weight: bold;font-family:courier new;" >route map.resources :movies</span><br /><span style="font-weight: bold;"><br />Making Movies</span></picture></picture></picture><picture here=""><picture here=""><picture here=""><br />The table will get created by the file in db/migrate/001_create_movies.rb . Let's look at the file</picture></picture></picture><picture here=""><picture here=""><picture here=""> now:<br /><picture here=""></picture></picture></picture></picture><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGODH4gpCQ_S-Bjfg4l0KZ6ID-pEBZveHCvMxm-zIsM7Ppp1HFqKwBLM3402crP3E1EzSa4B7y-kqXMut_StXOHUMEnRXtUIVgAI_8044y3NNvu8u_vUJzRZCLBfDPrcOiw5_84-TvGd8_/s1600-h/migration1.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGODH4gpCQ_S-Bjfg4l0KZ6ID-pEBZveHCvMxm-zIsM7Ppp1HFqKwBLM3402crP3E1EzSa4B7y-kqXMut_StXOHUMEnRXtUIVgAI_8044y3NNvu8u_vUJzRZCLBfDPrcOiw5_84-TvGd8_/s400/migration1.png" alt="" id="BLOGGER_PHOTO_ID_5144217382370543186" border="0" /></a><br /><picture here=""><picture here=""><picture here=""><picture here="">This file will create a table called movies that will be tied to the model Movie. This is a Rails naming convention. A table people would match a model Person. A table cars would match a model Car. You can also see how the parameters we fed the script/generate command show up as table columns and types in this migration file.<br /><br />Apply this migration to actually create the table with the command:</picture></picture></picture></picture><br /><picture style="font-family: courier new;" here=""><picture here=""><picture here=""><picture here="">exchange$</picture></picture></picture></picture><picture style="font-weight: bold; font-family: courier new;" here=""><picture here=""><picture here=""><picture here=""> rake db:migrate<br /></picture></picture></picture></picture><picture style="font-weight: bold; font-family: courier new;" here=""><picture here=""><picture here=""><picture here="">(in /home/sean01/work/exchange)<br /></picture></picture></picture></picture><picture style="font-weight: bold; font-family: courier new;" here=""><picture here=""><picture here=""><picture here="">== 1 CreateMovies: migrating </picture></picture></picture></picture><picture style="font-weight: bold; font-family: courier new;" here=""><picture here=""><picture here=""><picture here="">==================================================<br /></picture></picture></picture></picture><picture style="font-weight: bold; font-family: courier new;" here=""><picture here=""><picture here=""><picture here="">-- create_table(:movies)<br />-> 0.0040s<br />== 1 CreateMovies: migrated (0.0042s) =========================================</picture></picture></picture></picture><br /><picture here=""><picture here=""><picture here=""><picture here=""><br />To see what our work so far has produced, start the WEBbrick server with the command (if you didn't kill the earlier one use a control-c to kill it now):</picture></picture></picture></picture><br /><picture style="font-family: courier new;" here=""><picture here=""><picture here=""><picture here="">/exchange$</picture></picture></picture></picture><picture style="font-weight: bold; font-family: courier new;" here=""><picture here=""><picture here=""><picture here=""> ruby script/server<br /></picture></picture></picture></picture><picture style="font-weight: bold; font-family: courier new;" here=""><picture here=""><picture here=""><picture here="">=> Booting WEBrick...<br />=> Rails application started on http://0.0.0.0:3000<br />=> Ctrl-C to shutdown server; call with --help for options<br /></picture></picture></picture></picture><picture style="font-weight: bold; font-family: courier new;" here=""><picture here=""><picture here=""><picture here="">[2007-12-13 17:12:06] INFO WEBrick 1.3.1<br /></picture></picture></picture></picture><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;font-family:courier new;" >[2007-12-13 17:12:06] INFO ruby 1.8.5 (2006-08-25) [i486-linux]<br /></span><span style="font-weight: bold;font-family:courier new;" >[2007-12-13 17:12:06] INFO WEBrick::HTTPServer#start: pid=4054 port=3000</span><br /><br />point your web browse to the URL http://localhost:3000/movies and look at what we have</picture></picture></picture></picture><picture here=""><picture here=""><picture here=""><picture here=""> created.</picture></picture></picture></picture><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6axqxr1UlK-bu5L_UeoZgdgwWDfxjBOctaRL47X6tbKVPSfagZ2PMfcQwVM8xCN0zC-wzid9v4kPsCdSDPNdjPtSFcMyUiOCFgNGQ4LjeCw3DcywJ0sgJ7txUyeRjEK3cBzkgs5YQhdVm/s1600-h/movies1.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6axqxr1UlK-bu5L_UeoZgdgwWDfxjBOctaRL47X6tbKVPSfagZ2PMfcQwVM8xCN0zC-wzid9v4kPsCdSDPNdjPtSFcMyUiOCFgNGQ4LjeCw3DcywJ0sgJ7txUyeRjEK3cBzkgs5YQhdVm/s400/movies1.png" alt="" id="BLOGGER_PHOTO_ID_5144219310810859106" border="0" /></a><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""></picture></picture></picture></picture></picture><br /><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><br />It looks pretty bare, but we don't have any inventory yet. Click on the 'New Movie' link to start adding some movies to the inventory.<br /><picture here=""></picture></picture></picture></picture></picture></picture><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN79R7gJxCdyUdtOGGC3lP6lXA8yM4wlaq37gc2da6s9cqRynHnk8W_u8BcZDrYjYDxMnRavhaV_psFAHf1vFNMBQx9fClz7BEq8WAyAySIr36_2ykFTVo3RZeyWh7DAHlqd90WbZn2Txw/s1600-h/movies2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN79R7gJxCdyUdtOGGC3lP6lXA8yM4wlaq37gc2da6s9cqRynHnk8W_u8BcZDrYjYDxMnRavhaV_psFAHf1vFNMBQx9fClz7BEq8WAyAySIr36_2ykFTVo3RZeyWh7DAHlqd90WbZn2Txw/s400/movies2.png" alt="" id="BLOGGER_PHOTO_ID_5144219310810859122" border="0" /></a><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><br />Add a title, description and path to the one-sheet and click Create.</picture></picture></picture></picture></picture></picture><br /><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""></picture></picture></picture></picture></picture></picture></picture><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpOKMEFOKlrc_pNh9pJYq1aNyUmx2ys3rYgK5yCsujNfY8mDtXMHShNOHg4GN2XMM92ofjxj52Fq1Tdz8fxReo3q6SH-zTSeAn8jcAx2Kcg4mRmTMfiyqDen7HjzR8olr5IAI7vygbZ82u/s1600-h/movies3.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpOKMEFOKlrc_pNh9pJYq1aNyUmx2ys3rYgK5yCsujNfY8mDtXMHShNOHg4GN2XMM92ofjxj52Fq1Tdz8fxReo3q6SH-zTSeAn8jcAx2Kcg4mRmTMfiyqDen7HjzR8olr5IAI7vygbZ82u/s400/movies3.png" alt="" id="BLOGGER_PHOTO_ID_5144219315105826434" border="0" /></a><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here="">Click the button labeled 'Back' (not the browser back arrow) to return to the main listing and add another movie.<br /></picture></picture></picture></picture></picture></picture></picture><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""></picture></picture></picture></picture></picture></picture></picture></picture><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZSYLh7-xQWGKGoLLMNdm9xsUFZdbrRMRMBvjFTdp8JY05GHGcNBMWRxONsPJG4bX-9z-Q4DKW29OxmVXTmgZBENgdAWxZpJ_EoYs7DycC_1hVe952jUvaN6gr3_Povu5wFPZz0dDPVs65/s1600-h/movies4.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZSYLh7-xQWGKGoLLMNdm9xsUFZdbrRMRMBvjFTdp8JY05GHGcNBMWRxONsPJG4bX-9z-Q4DKW29OxmVXTmgZBENgdAWxZpJ_EoYs7DycC_1hVe952jUvaN6gr3_Povu5wFPZz0dDPVs65/s400/movies4.png" alt="" id="BLOGGER_PHOTO_ID_5144219319400793746" border="0" /></a><br /><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here="">This is still pretty bare bones, but we haven't even written any real code yet!<br /></picture></picture></picture></picture></picture></picture></picture></picture><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd3Unf7QqU_8fEZSwyrXZ6k9pQbdoc6XxkOhbLN94enNHBbzgkSRvU4BS6siWGbu1odFsGNPPQLu6E7uO_Y60ESEHQ_0fZR6KlL_wmWfC2LRTYwdrOW1H7yAJ3Xt3sgfptirTjEcGVxw3J/s1600-h/movies5.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd3Unf7QqU_8fEZSwyrXZ6k9pQbdoc6XxkOhbLN94enNHBbzgkSRvU4BS6siWGbu1odFsGNPPQLu6E7uO_Y60ESEHQ_0fZR6KlL_wmWfC2LRTYwdrOW1H7yAJ3Xt3sgfptirTjEcGVxw3J/s400/movies5.png" alt="" id="BLOGGER_PHOTO_ID_5144219323695761058" border="0" /></a><br /><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Oh CRUD!</span><br />In database terms CRUD is a good thing. Its an acronym for Create, Read, Update and Delete;</picture></picture></picture></picture></picture></picture></picture></picture><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""> the four most basic functionalities of a data store. The exchange app has this basic functionality without writing one line of code. It isn't pretty at this point an does not have any interesting bits and pieces, but it does work.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">What has been done so far?</span></span><br /></picture></picture></picture></picture></picture></picture></picture></picture><ul><li><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Installed Rails<br /></span>#gem install rails --include-dependencies</picture></picture></picture></picture></picture></picture></picture></picture></li><li><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Created an aplication with the rails command<br /></span>$rails exchange</picture></picture></picture></picture></picture></picture></picture></picture></li><li><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Created the databases for the application with the rake command<br /></span>$ rake db:create:all</picture></picture></picture></picture></picture></picture></picture></picture></li><li><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Used the script/generate command to create the scaffolding for the application<br /></span>$ ruby script/generate scaffold Movie title:string description:text one_sheet_url:string</picture></picture></picture></picture></picture></picture></picture></picture></li><li><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Created the database table using the generated migration file<br /></span>$ rake db:migrate</picture></picture></picture></picture></picture></picture></picture></picture></li><li><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Started the webserver with the script/server command<br /></span>$ ruby script/server</picture></picture></picture></picture></picture></picture></picture></picture></li><li><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-weight: bold;">Pointed our web browser to the application and started entering and editing data<br /></span>http://localhost:3000/movies</picture></picture></picture></picture></picture></picture></picture></picture></li></ul><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><span style="font-size:130%;"><br /></span><span style="font-weight: bold;font-size:130%;" >Part 2</span><br />Next time we'll cover some actually coding. We'll look at how to use code in the Model, View, and Controller to alter the exchange application's look and functionality as well as learning about Rails built-in test support.<br /><br />The purpose of scaffolding is to get started, but scaffolding should be replaced as we add code to our project. The usefulness of scaffolding is that we have an actual functioning application right from the start. We can make a change to the view, and test that nothing else breaks. Then repeat the process adding feature after feature until the application is ready for delivery. Its much easier to make changes to an application that already works than, it is to non-functional code that doesn't give any feed back.<br /><br /></picture></picture></picture></picture></picture></picture></picture></picture><ul><li><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><picture here=""><a href="http://fairleads.blogspot.com/2008/01/this-is-second-part-of-my-series.html">Part 2 is here</a></picture></picture></picture></picture></picture></picture></picture></picture></li></ul>Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com141tag:blogger.com,1999:blog-1525178018811356129.post-83284928992833777552007-06-25T09:58:00.001-05:002008-02-13T14:59:36.654-06:00Playa del Carmen<h1>Vacation</h1><br /><p>I haven't been around to add to the blog for a while, I was on vacation with my family. I just couldn't pull myself away from the warm sunny tropical beach to fiddle around with the hotel's internet connection and spend time on a post or two.<br /><br /><p>We went to part of the Yucatan south of Cancun often called the 'Riviera Maya', in the town of Playa del Carmen. The water was warm and clear, the beaches have really made a comeback after last year's hurricane, and the food at our resort was fantastic. Our kids are too small to do some of the larger jungle excursions, but we visited the nerby bird sanctuary Xaman Ha with the family. My daughter and I went horseback riding in the jungle one day as well.<br /><br /><p>The resorts had three little Hobie cats guests could take out whenever they wanted, as well as several kayaks and sailboards. I tried to take out a cat as often as I could and truly enjoyed sailing the small craft through the clear caribean water between the mainland and Cozumel.<br /><br /><p>We stayed at the Viva Azteca. It is the smaller of two Viva resorts in Playa del Carmen. Viva is an Italian based company, and it showed through in the variety and quality of food served at the resort. Italians know how to eat.<br /><br /><p>Getting back meant a pile of e-mail to clean up, but a vacation from the computer, and from blackberries and cell phones is the best.</p>Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com0tag:blogger.com,1999:blog-1525178018811356129.post-6310042111262221692007-06-07T15:56:00.000-05:002007-06-08T08:13:50.397-05:00Learning Ruby<h1>An Introduction to Ruby</h1><br /><p><a href="http://www.ruby-lang.org/">Ruby</a> is a pure object oriented scripting language that runs on most personal computer operating systems including Windows, Linux, Mac OS/X, and BSD. Ruby also runs on most commercial Unix based operating systems as well. Ruby was created in 1995 by <a href="http://www.rubyist.net/~matz/">Yukihiro Matsumoto</a>, usually referd to as "Matz".<br /><br /><p>Ruby's popularity grew steadily in the decade following its release. Ruby's growth and popularity are similar to the <a href="http://www.python.org/">python language</a>. Both languages have similar goals of simplifying programming. Many programmers have become proficient in both languages, and any perceived 'competition' between the two is usually positive and constructive. Matz mixed together some favorite aspects of other languages he worked with including Perl, Smalltalk, Eiffel, Ada, and Lisp to create Ruby. He wanted a more interactive language that was natural to work in. Something that seemed to 'fit just right'.<br /><p>I came to ruby late, and through my use of <a href="http://rubyonrails.org">Ruby on Rails</a> in 2005. I've been a proffesional programmer for over a decade, and was most recently building web apps with Java. Rails was like a ray of sunshine in a dark world. The clean, simple approach to programming and the strict adherance to the MVC framework was a great change from the drudgery of configuring large scale Java apps. I was able to pick up Rails pretty quick and become proficcient, but to be better I will need to learn Ruby. So far I am happy to be a 'newbie' in such a great community!<br /><p>Although I have learned a great deal of Ruby while working with Rails over the last few years, I am going to start over at the begining with Ruby. I've pretty much just picked up Ruby knowledge as I've gone along. I hope that a more rigorous approach to learning Ruby will help me be a better Rails programmer. I'm going to blog about my lessons in Ruby from the start, believing that taking the time to put what I'm learning in writing will help me to understand more.<br /><p>Most likely I'll just be giving a few readers a nice chuckle at my incompetence.<br /><p>In <a href="http://www.linuxdevcenter.com/pub/a/linux/2001/11/29/ruby.html">an interview with O'Reilly</a>, Matz is quoted as saying:<br /><blockquote><br />"I wanted a scripting language that was more powerful than Perl, and more object-oriented than Python. That's why I decided to design my own language."<br /></blockquote><br />So far Matz, and the Ruby community are meeting that goal.<br /><p>You can learn much more about Ruby at the <a href="http://www.ruby-lang.org/en/">Ruby Language site</a>.<br /><p>Ruby is free software and is available, either, uder the <a href="http://www.gnu.org/licenses/gpl.txt">GPL</a> or the <a href="http://www.ruby-lang.org/en/about/license.txt">Ruby Software License</a>.<br /><br /><hr /><br /><h1>Getting started with Ruby</h1><br /><br /><p>The first step you need to take in learning Ruby is to <a href="http://www.ruby-lang.org/en/downloads/">get Ruby on your machine</a>.<br /><br /><h3>Mac OS X</h3><br /><br /><p>Mac OS X comes with Ruby pre-installed. If you don't have it, go to <a href="http://www.apple.com/downloads/macosx/unix_open_source/rubyprogramminglanguage.html">the Apple download site</a>.</p><br /><br /><p>To install from source, go to the <a href="#source">Source</a> section.</p><br /><hr /><br /><h3>Windows</h3><br /><br /><p>Go to the ruby forge website and download the latest<br /><a href="http://rubyforge.org/frs/?group_id=167">one click installer</a> and run it.<br /><hr /><br /><h3>Linux</h3><br /><br /><p>Linux distros usually have ruby installed already. If you need to install it, its best to use your distro's package management system:</p><br /><br /><br /><strong>Debian Gnu/Linux</strong><br /><pre><tt> $ apt-get install ruby irb rdoc</tt></pre><br /><strong>RPM distros</strong><br />Download an RPM from <a href="http://rpmfind.net/linux/rpm2html/search.php?query=Ruby">RPM Find</a> and install with<br /><pre><tt> $ rpm -Uhv ruby-*.rpm</tt></pre>(You can also use something like yum, Yast, or apt4rpm if they are on your distro)<br /><br /><strong>Gentoo Linux</strong><br /><pre><tt> $ emerge ruby</tt></pre><br /><strong>Source</strong><br />Go to the <a href="#source">Source</a> section.<br /><hr /><br /><h3>FreeBSD</h3><br /><br /><p>Ruby is part of the FreeBSD ports collection. You can install it with:<br /><br /><pre><tt><br /> $ cd /usr/ports/lang/ruby<br /><br /> $ make && make install<br /></tt></pre><br /><p></p><br /><hr /><br /><h3><a name="source">Source</a> (good for all UNIX)</h3><br /><br /><p>Get the latest source code for Ruby <a href="http://www.ruby-lang.org/en/downloads/">ruby-1.8.6.tar.gz</a>.<br /></p>Un-tar the source code<br /><pre><tt><br /> $ tar -xvzf ruby-1.8.6.tar.gz<br /></tt></pre><br /><br /><p>To install, cd into the resulting library just do the usual three step:<br /><br /><pre><tt><br /> $ configure; make; make install<br /></tt></pre><br /><p></p><br /><hr /><br /><h1>Your First Ruby Program</h1><br /><p>Use your favorite text editor to create a file called ruby_hello.rb. Type this one line in the file:<br /><pre><tt><br /> puts 'Hello World!'<br /></tt></pre><br />save the file and run it at the command line with the command:<br /><pre><tt><br /> $ ruby ruby_hello.rb<br /> Hello World!<br /></tt></pre><br /><br /><p>You can also run the ruby code directly from the command line with the -e switch, just like in perl:<br /><pre><tt><br /> $ ruby -e "puts 'Hello world'"<br /></tt></pre><br /><br /><p>Or use <a href="http://www.rubycentral.com/book/html/irb.html">irb</a>, the ruby interactive shell:<br /><pre><tt><br /> $ irb<br /> >> puts 'Hello World!'<br /> Hello World!<br /> => nil<br /></tt></pre><br /><br /><p>Going back to our text editor, let's add some comments. Ruby single line comments begin with a #. Everything on the line after the # is a comment:<br /><pre><tt><br /> <b># the classic first program</b><br /><br /> puts 'Hello World!' <b>#print a greeting</b><br /></tt></pre><br /><br /><p>Multi-line comments are rarely used in Ruby. Multi-line or block comments are delimited with '=begin' and '=end':<br /><pre><tt><br /> # the classic first program<br /> <br /> puts 'Hello World!' #print a greeting<br /><br /> <b>=begin<br /> This ruby program is<br/><br /> © copyrighted by me, 2007.<br/><br /> Or it would be if there<br/><br /> weren't already millions <br/><br /> of other programs exactly<br/><br /> like it, many of which are<br/><br /> in the public domain already.<br /> =end</b><br /></tt></pre><br /><p>save the file and run it at the command line and you'll see the exact same result as before:<br /><pre><tt><br /> $ ruby ruby_hello.rb<br /> Hello World!<br /></tt></pre><br /><hr><br /><p>So that's lesson one. Installing Ruby, writing and running the obligatory 'Hello World!' program to see if the installation went well. If you had any problems, check out the <a href="http://www.ruby-lang.org/">Ruby language page</a>, or join the <a href="http://www.ruby-lang.org/en/community/">Ruby community</a> and check in the mailing lists, chat rooms or with the local Ruby Users Group for help.Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com2tag:blogger.com,1999:blog-1525178018811356129.post-11979579604518988922007-06-05T14:52:00.000-05:002007-06-05T15:35:31.623-05:00Ruby Yield<p>Yield is one of the most powerful concepts implemented in the Ruby programming language. Yield lets you branch from within a method and execute some external code, then return to the original code in the first method.<br /><br /><p>What's so special about yield in Ruby? You could get the same branch and return flow by just executing a method call in java, or a function call in C. <br /><br /><p>Heck, COBOL's PERFORM verb implements branch and return behavior. So what's up with yield?<br /><br /><p>Well, the behavior of what you branch to is set in stone with all those other techniques, but is undetermined until coded in Ruby. Yield is kind of like a place holder that says "I'm going to branch off and do something here, but I don't know what I'm going to do yet".<br /><br /><p>Maybe some examples will help make it more clear. Here is a Ruby method with some yields coded in it, then the code to invoke the method and the block of code to invoke when the yield is encountered:<br /><pre><blockquote><br /><tt>def block1<br /> puts "Start of block1..."<br /> yield<br /> yield<br /> puts "End of block1."<br />end<br /><br />block1 {puts "yielding..."}<br /></tt></blockquote></pre><br /><p>Running this code would produce the following output:<br /><pre><blockquote><br /><tt>Start of block1...<br />yielding...<br />yielding...<br />End of block1.<br /></tt></blockquote></pre><br /><p>So block1 executes it's first line and prints "Start of block1...", then it executes the yields which branch to the block of code outside block1 but associated with it at run time, then comes back and prints "End of block1."<br /><br /><p>OK that's, fine but isn't that functionally the same as the following code:<br /><pre><blockquote><br /><tt>def block2<br /> puts "Start of block2..."<br /> put_it("in put_it called method...")<br /> put_it("still in put_it called method...")<br /> puts "End of block2."<br />end<br /><br />def put_it(text)<br /> puts text<br />end<br /><br />block2<br /></tt></blockquote></pre><br /><p>Running this second set of code produces the following:<br /><pre><blockquote><br /><tt>Start of block2...<br />in put_it called method...<br />still in put_it called method...<br />End of block2.<br /></tt></blockquote></pre><br /><p>For the most part, these are pretty much the same. However without having to redefine any methods I could immediately execute the block1 method with a different block associated with it. The yield would branch and execute this newly associated logic:<br /><pre><blockquote><br /><tt>block1 {require 'time' <br /> puts Time.now.httpdate}<br /></tt></blockquote></pre><br /><p>This produces the output:<br /><pre><blockquote><br /><tt>Start of block1...<br />Tue, 05 Jun 2007 19:20:35 GMT<br />Tue, 05 Jun 2007 19:20:35 GMT<br />End of block1.<br /></tt></blockquote></pre><br /><p>The hard coded function call in block2 forever ties the branching logic to the put_it function. To get different behavior you would need to either change the function call in block2 to call a different function, or change the behavior of the function put_it. This second way is brittle because it could break code elsewhere that calls put_it. The first is cumbersome and possibly brittle.<br /><br /><p>Ruby's yield is a wonderful construct.<br /><br /><p>What about when you don't want to branch, but want the other functionality in the block1 code to be executed? Can you just run the code without the associated block?<br /><br /><p>Let's see what happens. Running block1 without an attached block for the yield to associate to:<br /><pre><blockquote><br /><tt>block1<br /></tt></blockquote></pre><br /><p>This produces the result:<br /><pre><blockquote><br /><tt>Start of block1...<br />LocalJumpError: no block given<br /> from <irb>:3:in 'block1'<br /> from <irb>:7<br /> from :0<br /></tt></blockquote></pre><br /><p>We get a 'no block given' error at line 3 in method 'block1'. Line 3 is our first yield in the block1 method. <br /><br /><p>What to do?<br /><br /><p>We can wrap the yield in an if statement and check for the presence of a block using the block_given? conditional. It returns true if a block was given with the method call, or false if not.<br /><br /><p>For this example I'll use a slightly more idiomatic way of checking for the presence of a block in ruby:<br /><pre><blockquote><br /><tt>def block3<br /> puts "Start of block3..."<br /> yield if block_given?<br /> puts "End of block3."<br />end<br /></tt></blockquote></pre><br /><p>now if we run the code with a block:<br /><pre><blockquote><br /><tt>block3 { puts "yielding" }<br /></tt></blockquote></pre><br /><p>or without:<br /><pre><blockquote><br /><tt>block3<br /></tt></blockquote></pre><br /><p>It works both times producing:<br /><pre><blockquote><br /><tt>Start of block3...<br />yielding...<br />End of block3.<br /></tt></blockquote></pre><br /><p>and<br /><pre><blockquote><br /><tt>Start of block3...<br />End of block3.<br /></tt></blockquote></pre><br /><br /><p>This will make your methods less brittle and more agile. <br /><br /><p>Ruby's yield is worth getting to know. You can learn more <a href="http://www.rubycentral.com/book/tut_containers.html">here</a> and <a href="http://lxer.com/module/newswire/view/61805/index.html">here</a>. Many of Ruby's built in methods contain yields that allow you to associate blocks with them producing added functionality at run time.Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com4tag:blogger.com,1999:blog-1525178018811356129.post-4434346555144389472007-06-04T12:47:00.000-05:002007-06-05T08:29:02.259-05:00The Beauty of Ruby<h1>The Beauty of Ruby</h1><br /><br /><p>I've been working more and more with Ruby on Rails. I'm hoping to be able to work full time with it in the next few years, but for now I'll just have to keep sneaking it into some of the bigger things I get paid to do.<br /><br /><p>Its too bad because Rails and Ruby could really help some of the clients I work for. I really haven't been this excited about a programming language since I learned C back in the Eighties!<br /><br /><p>One of the main benefits of Ruby on Rails is how <a href="http://gettingreal.37signals.com/ch04_Make_Opinionated_Software.php">opinionated</a> Rails is. Rails does not <a href="http://www.linuxjournal.com/article/8686">try to be everything to everyone</a>. It is trying to meet most of the needs of the average web app, but not trying to give into everyone's slightest whim. The coding needed to provide for most of what you need will be simple and straightforward with Rails. If you want more esoteric fluff, you can use J2EE. There are plenty of alternative solutions, but if 8 out of 10 apps you write fit in the middle, why are you forced to carry the luggage and infrastructure to support those few times the exotic stuff is needed.<br /><br /><p>Working with Rails is like working with a framework that imposes the KISS principle on your apps. It really results in savings and efficiency.<br /><br /><p>As I've worked more with Rails, I've begun to truly appreciate Ruby. Like many people in the last few years I came to Ruby through Rails. I started using Ruby as just another language. Most of what you know in any given language is available in any other. The biggest differences are between the procedural and the object oriented languages, but you might be surprised and how similar even these are in practice. Take Java for example. It is a fairly object oriented language. Its not pure OO, and it doesn't claim to be. Java's basic types are not objects. You know strings, floats, characters, and such. However Java is a pretty good example of a modern OO language. However you'll notice that quite a bit of Java was written by people who think like procedural programmers. take a walk through Java's network classes and you'll see the same kind of coding I was doing back when I learned C in the 1980's.<br /><br /><p>I shouldn't complain because I certainly wouldn't have done a better job. Heck, I wouldn't have done nearly as good a job as the people at Sun did.<br /><br /><h3>Objectification</h3><br /><p>With Ruby everything is an object. You cannot cheat. You have to code in OO style. Better yet Ruby truly embraces its Object Oriented-ness! You often don't call a method on an object, the method invokes its own method on itself. For Java's class Math one of the methods is abs, a function that lets you compute the absolute value of a number. For example for an integer the function looks like:<br /><br /><pre><blockquote><br /><h3>Java code:</h3><br /><tt>public final class Math {<br />...<br /> public static int abs(int a);<br /> public static long abs(long a);<br /> public static float abs(float a);<br /> public static double abs(double a);<br />...<br />}<br /></tt></blockquote></pre><br /><br /><p>You would use this method on an integer like this:<br /><pre><blockquote><br /><h3>Java code:</h3><br /><tt>public class MathExample{<br /> public static void main(String[] args) {<br /><br /> int i = -7;<br /> System.out.println("i is " + i);<br /> System.out.println("" + i + " is " + Math.abs(i));<br /> }<br />}<br /></tt></blockquote></pre><br /><br /><p>This is pretty standard stuff. It should be easy enough for any programmer to understand. For output you would get something like:<br /><pre><blockquote><tt>i is -7<br />|-7| is 7<br /></tt></blockquote></pre><br /><br /><br /><p>What's not object oriented about that? Math is a class. abs is a method of class Math. Heck abs is even multiply defined so the same method can be applied to multiple data types! Math.abs() that is object oriented!<br /><br /><p>Yes it is.<br /><br /><p>So what's Ruby got?<br /><br /><p>Let's just look at How Ruby would do it first:<br /><pre><blockquote><br /><h3>Ruby code:</h3><tt>puts 'i is ' + (-7).to_s<br />puts 'i is ' (-7.abs).to_s<br /></tt></blockquote></pre><br /><br /><p>The heart of that is when negative seven calls its method abs on itself<br /><pre><blockquote><tt>puts -7.abs<br /></tt></blockquote></pre><br /><br /><p>Yep, that's all folks. Remember Ruby is a pure object oriented language, so the integer '-7' is an object. The object '-7' is of type int and has a method called abs. -7 is calling its own method on itself! Lucky number seven.<br /><br /><p>The puts (for put string) looks like a normal function call with a function name followed by the object to perform the function on, but we could give objects a 'puts' themself method. You can see how we used the numeric object's 'to_s' method on itself to turn it into a string. The object that the puts function was operating on was not enclosed in parentheses as they are optional in ruby. <br /><br /><p>If you don't believe me, <a href="http://tryruby.hobix.com/">give it a try yourself</a>. If you follow that link you will be on a site that lets you try out Ruby code at an irb prompt, thanks to <a href="http://whytheluckystiff.net/">Why the Lucky Stiff</a>.<br /><br /><h3>How does Ruby do it?</h3><br /><p>Well, lets look into the class definitions in the <a href="http://www.ruby-doc.org/">Ruby api</a> and look up how abs is <a href="http://www.ruby-doc.org/core/classes/Fixnum.src/M001083.html">implemented in Ruby</a> (remember Ruby is written is C):<br /><pre><blockquote><tt>/*<br />* call-seq:<br />* fix.abs -> aFixnum<br />* <br />* Returns the absolute value of fix.<br />*<br />* -12345.abs #=> 12345<br />* 12345.abs #=> 12345<br />*<br />*/<br /><br /> static VALUE<br /> fix_abs(fix)<br /> VALUE fix;<br /> {<br /> long i = FIX2LONG(fix);<br /><br /> if (i < 0) i = -i;<br /><br /> return LONG2NUM(i);<br /> } </blockquote></tt></pre><br /><br /><p>That's the implementation of the absolute value behavior for <a ref="http://www.ruby-doc.org/core/classes/Fixnum.html#M001083">fixnums</a>. All of Ruby's numeric types get an appropriate form of this behavior. Every numeric type in Ruby has the ability to calculate its own absolute value. As I use Ruby more and more, I am starting to truly appreciate the joys of object oriented programming.<br /><br /><p>There is truth in beauty.<br /><hr/><br /></p>Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com2tag:blogger.com,1999:blog-1525178018811356129.post-41506632043687545702007-05-31T08:51:00.001-05:002007-05-31T10:46:08.221-05:00<p>I attended <a href="http://conferences.oreillynet.com/rails/">RailsConf 2007</a> in Portland Oregon and had a great time. The Rails community is growing so large its unbelievable. Its starting to get all 'enterprisey' as well.<br /><br /><p>I wrote <a href="http://lxer.com/module/newswire/view/87286/index.html">an article</a> for Lxer summing up some of the events. I'll reproduce it here:<br /><hr /><br /><h2>Railsconf 2007</h2><br /><ul><br /><li>"Make no small plans. They have no magic to stir men's blood and probably will not themselves be realized." -Daniel Burnham<br /><br /><li>"Form, ever, follows function." -Louis Sullivan<br /><br /><li>"Less is more." -Mies van der Rohe<br /></li></ul><br /><p>What do these three have to do with <a href="http://rubyonrails.com/">Ruby on Rails</a> and the second annual <a href="http://conferences.oreillynet.com/rails/">Rails conference</a> in Portland?<br /><br /><p>Daniel Burnham and Louis Sullivan made their names designing and re building the city of Chicago after the great fire. Mies van der Rohe, later, gave the ultimate expression to the modernist style inspired by Sullivan. Their work was given life because of the development of a new disruptive technology, structural steel. This was the same steel developed to make the rails. The rails carried the goods, and the goods paid for their works.<br /><br /><p>Ruby on Rails was also born in Chicago. Rails was extracted from a working application because its creator, <a href="http://www.loudthinking.com/">David Heinemeier Hansson (DHH)</a>, saw that he could re use the framework for other projects just as the steel rails were extracted from their original application and used to build skyscrapers. David and the team at <a href="http://www.37signals.com/">37Signals</a> released Rails as an open source project and the Rails community has been building outward and upward ever since.<br /><ul><br /><li>Rails lets you make big plans<br /><li>Rails projects follow a form based on the MVC framework (their function)<br /><li>With Rails 'convention over configuration' philosophy, less really is more<br /></li></ul><br /><p>Rails is proving to be a disruptive technology in the development community, but the main disruption is due to the fact that web development does not have to be so difficult, and so barroque.<br /><br /><p>As with the first conference in Chicago, 2006, there was a pre-conference day of tutorials. The money raised for the pre-conference tutorials is <a href="http://pragmaticstudio.com/donate/">donated to various charities</a>. By the end of the conference more than $33,000 had been donated by the Rails community for various charities.<br /><br /><p>The highlights of the show included keynotes by Rails notables David Heinemeier Hansson, Dave Thomas, Avi Bryant, Michael Koziarski, Jamis Buck, David Black, Chad Fowler, Rich Kilmer and others. The two Davids were the bookends beginning and ending the conference. The keynote by DHH outlined some of the <a href="http://blog.nicksieger.com/articles/2007/05/18/railsconf-2007-opening-keynote-david-heinemeier-hansson">changes coming in Rails 2.0</a>.<br /><br /><p>Tim Bray of Sun gave an interesting keynote. Sun has noticed Rails and is no longer ignoring or laughing. They don't intend to fight because they can sell servers for Rails clients just as well as for Java clients. The <a href="http://jruby.codehaus.org/">JRuby</a> implementation should open some interesting new opportunities for developers.<br /><br /><p>Many of the other Rails community members, as well as Rails based companies gave keynotes and regular talks. There were four main tracks of talks each day with alternate tracks, BOF's, lightning talks and reject conferences day and night. <a href="http://en.wikipedia.org/wiki/Ze_Frank">Ze</a> Frank's keynote Friday night showed that the Rails community is unique for its mix of developers and designers, and that the Rails community still maintains its irreverence even for all of the new ‘enterprisey'-ness.<br /><br /><p>A summary of the talks, coverage as well as photos and movies can be found:<br /><ul><br /><li><a href="http://www.web2expo.com/pub/w/51/presentations.html">Talks</a><br /><li><a href="http://www.oreillynet.com/conferences/blog/railsconf/">News and Coverage</a><br /><li><a href="http://www.flickr.com/photos/x180/sets/72157600225783815/">Photos</a><br /></li></ul><br /><p>Many of the talks feature the slides used. A quick trip to <a href="http://www.youtube.com/results?search_query=railsconf&search=Search">youtube</a> or <a href="http://technorati.com/tag/railsconf">technorati</a> and a search on Railsconf will show <a href="http://www.youtube.com/watch?v=UzZHLbwjIz0">many</a> <a href="http://www.youtube.com/watch?v=H6eZQwVUARg">more</a> highlights showing up. (Some of the shots from Saturday's lunchtime <a href="http://www.youtube.com/watch?v=k9vYXlahRFU">marching</a> band may not be suitable for the office).<br /><br /><p>Portland, Oregon is a beautiful city and the conference facilities are top notch. O'Reilly and the other major sponsors provided a fantastic venue. Last year's Railsconf was bursting at the seams and the team at <a href="http://www.rubycentral.com/">Ruby Central</a> and <a href="http://www.nofluffjuststuff.com/">No Fluff Just Stuff</a> did their best to accomodate, but the Rails community is growing too fast. This year's conference had three times the attendance of last year's.<br /><br /><p>The Rails community is thinking big and moving fast, but they are keeping Rails agile and light. If you are unfamiliar with Rails watch the <a href="http://www.rubyonrails.org/screencasts">videos</a> available at the Ruby on Rails site. Rails is released under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.<br /></p>Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com0tag:blogger.com,1999:blog-1525178018811356129.post-31665790360972826612007-05-30T12:39:00.000-05:002007-05-30T13:09:18.633-05:00fairleads blog<p><a href="http://en.wikipedia.org/wiki/Fairlead">Fairleads</a> are part of a ship's rigging. A fairlead is usually a block or a pully that helps to keep the jib sheets running smooth so you can control the jib. If this doesn't mean much to you it didn't to me either before last year. My wife and kids gave me <a href="http://chicagosailing.com/ibasic.html">sailing lessons</a> for a Christmas present and I've been learning ever since.<br /><br /><p>In trying to think up a name for a blog the term fairlead popped into my mind. Its nice to have titles with more meaning to them.<br /><br /><p>On most sloop rigged boats the fairleads are mounted on rails so they can be adjusted back and forth on the boat. For the last year or so I've been working on Rails as well, <a href="http://www.rubyonrails.org">Ruby on Rails</a>. Since most of my work is done for client's internal use, I don't get any kudos for showing off my web apps. I hope to chronicle some of my adventures on Rails here.<br /><br /><p>I've had a <a href="http://www.sean-lynch.com">web site</a> since the late 90's, but I'm lucky if I update the thing every year or so. I've got to get back there and fix all the broken links. I'll get to that RSN, I'm sure :)<br /><br /><p>I'm hoping that with a blog I'll be a little more likely to keep things up to date. Maybe I'll post every three or four months! I'll try to keep up with new posts about sailing, Rails and my life in Linux as well as any other worthless things that happen to me and my friends and family.<br /><br /><p>Thanks for stopping by!</p>Sean Lynchhttp://www.blogger.com/profile/16196715129586398563noreply@blogger.com1