<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2911377234335400421</id><updated>2012-01-11T01:16:33.372-06:00</updated><category term='ruby'/><category term='flash'/><category term='activerecord'/><category term='attachment_fu'/><category term='DRY'/><category term='AJAX'/><category term='rails host snippet'/><category term='open source'/><category term='slightlycoded'/><category term='typecast'/><category term='blob'/><category term='Forum'/><category term='console'/><category term='rails 2.0 tutorial forum restful_authentication'/><category term='rails'/><category term='push server'/><category term='chat'/><category term='RecordNotFound'/><category term='video'/><category term='video app'/><category term='juggernaut'/><category term='ActiveScaffold'/><category term='rubyplus'/><category term='same name'/><category term='Newbie'/><category term='helpers'/><category term='flowplayer'/><category term='no text field'/><category term='tinyint'/><category term='begin rescue'/><category term='awdr'/><category term='mysql'/><category term='override'/><category term='tutorial'/><category term='nested partial'/><category term='flv'/><category term='ffmpeg'/><category term='depot'/><category term='video tutorial'/><category term='links'/><category term='symbols'/><category term='rails 2.0'/><category term='obama'/><category term='ruby on rails'/><category term='2.0'/><category term='partial layout'/><category term='view'/><category term='&quot;TypeError: $(&quot;current_item&quot;) has no properties&quot;'/><category term='hoedown vertebra cloud'/><category term='boolean'/><category term='beginner'/><title type='text'>Rails on Edge</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-3434465097869198042</id><published>2009-03-30T04:25:00.003-05:00</published><updated>2009-03-31T12:57:57.139-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ffmpeg'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='video app'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><title type='text'>Rails Video Application</title><content type='html'>EDIT: Demo up and running, the URL is &lt;a href = "http://videoapp.railsonedge.com/"&gt;http://videoapp.railsonedge.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Earlier this semester, I decided I wanted to keep working on my Video Application(see the &lt;a href = "http://railsonedge.blogspot.com/2009/01/flash-video-tutorial-with-rails-ffmpeg.html"&gt;Flash Video Tutorial&lt;/a&gt;).  So when my databases teacher let us decide what our semester project would be, I signed up to do a YouTube-like site.&lt;br /&gt;&lt;br /&gt;Since the tutorial, I've added a lot of things: User Authentication(authlogic), Video Thumbnails(using ffmpeg), Pagination(will_paginate), Tags/Tag Cloud(acts_as_taggable_on_steroids), and I wrote up some quick code to take care of user replies.  I also added a little bit of CSS to the application so it didn't look so plain.  It looks a lot better, but I'm still working on some of it.  You can checkout the code for it on GitHub(&lt;a href = "http://github.com/balgarath/video-app/tree/master"&gt;http://github.com/balgarath/video-app/tree/master&lt;/a&gt;).  The code from the previous tutorial is in the 'Tutorial' branch.&lt;br /&gt;&lt;br /&gt;Anyway, I will have a demo of the application up sometime the next couple days.  I'll get the URL posted here.  Feel free to fork the repo and play around with the app.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-3434465097869198042?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/3434465097869198042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=3434465097869198042' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3434465097869198042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3434465097869198042'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2009/03/rails-video-application.html' title='Rails Video Application'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-6698005958746608628</id><published>2009-03-18T17:22:00.002-05:00</published><updated>2009-03-18T17:41:11.478-05:00</updated><title type='text'>Yehuda Katz talks about Rails 3.0</title><content type='html'>&lt;p&gt;Just got through watching &lt;a href = "http://yehudakatz.com/"&gt;Yehuda Katz's&lt;/a&gt; talk about Rails 3.0 he gave at &lt;a href = "http://mtnwestrubyconf.org/2009/"&gt;MountainWest RubyConf 2009&lt;/a&gt;.  Lots of good stuff about where Rails is headed, as well as the ORM-abstraction that Yehuda is working on, ActionORM.  ActionORM is a layer built to make any ORM look just like it is ActiveRecord, to Rails.  Yehuda also talks a little bit about how he is working to change rails so that it will be easier to do things such as changing out ORMs, or even something like replacing ActionController with your own Controller code.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Towards the end he talks about how some people have said that by Merb merging with Rails, there will be less competition, and there will be less competition.  Yehuda points out that by making rails modular, competition will be more between different parts of the framework(ActiveRecord vs. Datamapper).  I agree with him and think that this will be a huge benefit to the community as a whole.  Heres the video:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;embed src='http://mwrc2009.confreaks.com/player.swf' height='380' width='640' allowscriptaccess='always' allowfullscreen='true' flashvars='image=images%2F13-mar-2009-11-55-the-great-rails-refactor-yehuda-katz-preview.jpg&amp;file=http%3A%2F%2Fmwrc2009.confreaks.com%2Fvideos%2F13-mar-2009-11-55-the-great-rails-refactor-yehuda-katz-small.mp4&amp;plugins=viral-1'&gt;&lt;/embed&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This video brought to you by &lt;a href = "http://www.confreaks.com"&gt;ConFreaks&lt;/a&gt;.  Lots of great videos at the website from many other Ruby-related conferences.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-6698005958746608628?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/6698005958746608628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=6698005958746608628' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/6698005958746608628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/6698005958746608628'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2009/03/yehuda-katz-talks-about-rails-30.html' title='Yehuda Katz talks about Rails 3.0'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-3300261362987589228</id><published>2009-01-22T21:39:00.009-06:00</published><updated>2009-03-30T04:25:07.141-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ffmpeg'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='attachment_fu'/><category scheme='http://www.blogger.com/atom/ns#' term='flowplayer'/><category scheme='http://www.blogger.com/atom/ns#' term='video tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='flv'/><title type='text'>Flash Video Tutorial with Rails, ffmpeg, FlowPlayer, and attachment_fu</title><content type='html'>&lt;p&gt;Quick Tutorial today to get a simple Video Model setup and going with Flowplayer today.  We want to be able to upload videos and convert them to flash .flv files.  For this I'll be using ffmpeg.  Other plugins in this tutorial include &lt;a href = "http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk/README"&gt;acts_as_state_machine&lt;/a&gt; and &lt;a href = "http://techno-weenie.net/"&gt;Rick Olsen's&lt;/a&gt; attachment_fu.  Lets get started!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Note: You can find the source code for this app on github at &lt;a href = "http://github.com/balgarath/video-app/tree/master"&gt;http://github.com/balgarath/video-app/tree/master&lt;/a&gt;.  EDIT: I've been working on this, so if you want to see the code specific to the tutorial, click on the Tutorial branch on github.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;1. Setup&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;First, lets create an empty app &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;rails videoapp -d mysql&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Do all your basic setup...(edit database.yml, remove public/index, ...).  In routes.rb, add this line:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;  map.root :controller =&gt; "videos"&lt;br /&gt; map.resources :videos&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The first line maps '/' to the videos controller, and the next establishes RESTful routes for videos.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now we need to figure out what flash video player we want to use.  For this tutorial, I will be using &lt;a href = "www.flowplayer.org"&gt;FlowPlayer&lt;/a&gt;, an open-source flash video player.  You will need to download flowplayer.zip from &lt;a href = "http://flowplayer.org/download/index.html"&gt;http://flowplayer.org/download/index.html&lt;/a&gt;.  Unzip it to /public.  Grab the /example/flowplayer-3.0.2.min.js file and put it in /public/javascripts/flowplayer.js.  Put example/style.css in /public/stylesheets.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Next we need to install attachment_fu to handle file downloads.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;./script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu/&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And you will need ffmpeg for converting uploaded file to .swf.  This works for me in Ubuntu...&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;sudo apt-get install ffmpeg&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And last, lets install the acts_as_state_machine plugin.  We will be using it to keep track of the current state of conversion for the video:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt; ./script/plugin install http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk/&lt;/pre&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;2. Database/Model Setup&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now we are ready to set up the model.  First, run this command to generate the files for you:&lt;/p&gt;&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;  ./script/generate model Video&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This last line will also generate a create_video migration in db/migrate/.  Open up that file and put this in it:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class CreateVideos &lt; ActiveRecord::Migration&lt;br /&gt;  def self.up&lt;br /&gt;    create_table :videos do |t|&lt;br /&gt;      t.string :content_type&lt;br /&gt;      t.integer :size&lt;br /&gt;      t.string :filename&lt;br /&gt;      t.string :title&lt;br /&gt;      t.string :description&lt;br /&gt;      t.string :state&lt;br /&gt;      t.timestamps&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.down&lt;br /&gt;    drop_table :videos&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Content_type, size, and filename are used by the attachment_fu plugin.  The state field will be used by the act_as_state_machine plugin to keep track of video converting. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Lets move on to the model; open up /app/model/video.rb and add this into it:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  has_attachment :content_type =&gt; :video, &lt;br /&gt;                 :storage =&gt; :file_system, &lt;br /&gt;                 :max_size =&gt; 300.megabytes&lt;br /&gt;&lt;br /&gt;  #turn off attachment_fu's auto file renaming &lt;br /&gt;  #when you change the value of the filename field&lt;br /&gt;  def rename_file&lt;br /&gt;    true&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This is for the attachment_fu plugin.  I came across a feature of attachment_fu: when you change the filename of an attachment, the old file automatically gets moved to whatever the new filename is.  Since I am creating a new file and changing the filename attribute of the video the reflect that, I don't need this on...so I just overrode the method in the Model.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Since we will be using the acts_as_state_machine plugin to keep track of the state of conversion for videos, lets go ahead and add in the states we will be using.  Add this to video.rb:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  #acts as state machine plugin&lt;br /&gt;  acts_as_state_machine :initial =&gt; :pending&lt;br /&gt;  state :pending&lt;br /&gt;  state :converting&lt;br /&gt;  state :converted, :enter =&gt; :set_new_filename&lt;br /&gt;  state :error&lt;br /&gt;&lt;br /&gt;  event :convert do&lt;br /&gt;    transitions :from =&gt; :pending, :to =&gt; :converting&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  event :converted do&lt;br /&gt;    transitions :from =&gt; :converting, :to =&gt; :converted&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  event :failure do&lt;br /&gt;    transitions :from =&gt; :converting, :to =&gt; :error&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;small&gt;Note: I got some of this part from Jim Neath's &lt;a href = "http://jimneath.org/2008/06/03/converting-videos-with-rails-converting-the-video/"&gt;tutorial&lt;/a&gt;.&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now we can use @video.convert!, @video.converted!, @video.failed! to change the state of a particular Video.  The last code we need to add to the model is this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;  # This method is called from the controller and takes care of the converting&lt;br /&gt;  def convert&lt;br /&gt;    self.convert!&lt;br /&gt;    success = system(convert_command)&lt;br /&gt;    if success &amp;&amp; $?.exitstatus == 0&lt;br /&gt;      self.converted!&lt;br /&gt;    else&lt;br /&gt;      self.failure!&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  protected&lt;br /&gt;  &lt;br /&gt;  def convert_command&lt;br /&gt;  &lt;br /&gt;  #construct new file extension&lt;br /&gt;    flv =  "." + id.to_s + ".flv"&lt;br /&gt;&lt;br /&gt;  #build the command to execute ffmpeg&lt;br /&gt;    command = &lt;&lt;-end_command&lt;br /&gt;     ffmpeg -i #{ RAILS_ROOT + '/public' + public_filename }  -ar 22050 -ab 32 -s 480x360 -vcodec flv -r 25 -qscale 8 -f flv -y #{ RAILS_ROOT + '/public' + public_filename + flv }&lt;br /&gt;      &lt;br /&gt;    end_command&lt;br /&gt;    &lt;br /&gt;    logger.debug "Converting video...command: " + command&lt;br /&gt;    command&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  # This updates the stored filename with the new flash video file&lt;br /&gt;  def set_new_filename&lt;br /&gt;    update_attribute(:filename, "#{filename}.#{id}.flv")&lt;br /&gt;    update_attribute(:content_type, "application/x-flash-video")&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A lot of stuff going on here.  Convert will be called from the create action.  When called, it sets the state of the video to 'convert' and runs ffmpeg to convert the file to flash(.flv).  It will then mark the file as either 'converted' or 'failed'.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now that that is all done, we can create our database and run the migrations:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rake db:create&lt;br /&gt;rake db:migrate&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;3. Controller/Views&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now we can generate our controller, model, and view files:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt; ./script/generate controller videos index show new&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Open up /app/controllers/videos_contoller.rb and put in this code:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class VideosController &lt; ApplicationController&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;  def index&lt;br /&gt;    @videos = Video.find :all&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def new&lt;br /&gt;    @video = Video.new&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def create&lt;br /&gt;    @video = Video.new(params[:video])&lt;br /&gt;    if @video.save&lt;br /&gt;      @video.convert&lt;br /&gt;      flash[:notice] = 'Video has been uploaded'&lt;br /&gt;      redirect_to :action =&gt; 'index'&lt;br /&gt;    else&lt;br /&gt;      render :action =&gt; 'new'&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def show&lt;br /&gt;    @video = Video.find(params[:id])&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def delete&lt;br /&gt;    @video = Video.find(params[:id])&lt;br /&gt;    @video.destroy&lt;br /&gt;    redirect_to :action =&gt; 'index'&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the create method, notice that if the video save is true, @video.convert gets called, which convert the video to .flv.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Views&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Create the file /app/views/layouts/application.html.erb and put this in it:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01 Transitional//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/loose.dtd&amp;quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;head&amp;gt;&lt;br /&gt;    &amp;lt;title&amp;gt;Video Tutorial&amp;lt;/title&amp;gt;&lt;br /&gt;      &amp;lt;%= stylesheet_link_tag 'style' %&amp;gt;&lt;br /&gt;    &amp;lt;%= javascript_include_tag 'flowplayer' %&amp;gt;   &lt;br /&gt;  &amp;lt;/head&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;h1&amp;gt;Video Tutorial&amp;lt;/h1&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;% flash.each do |key,value| %&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;div id=&amp;quot;flash&amp;quot; class=&amp;quot;flash_&amp;lt;%= key %&amp;gt;&amp;quot; &amp;gt;&lt;br /&gt;        &amp;lt;span class=&amp;quot;message&amp;quot;&amp;gt;&amp;lt;%= value %&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;      &amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;% end -%&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;%= yield :layout %&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;/body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now for our index view (/app/views/videos/index.html.erb)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;h2&amp;gt;Videos&amp;lt;/h2&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= link_to 'New Video', new_video_url %&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;% for video in @videos do %&amp;gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&amp;lt;%= link_to video.title, video %&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;% end %&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;/app/views/videos/new.html.erb:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;h2&amp;gt;New Video&amp;lt;/h2&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;% form_for(@video, :html =&amp;gt; { :multipart =&amp;gt; true }) do |f| %&amp;gt;&lt;br /&gt;  &amp;lt;%= f.error_messages %&amp;gt;&lt;br /&gt;  &amp;lt;table&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;      &amp;lt;td&amp;gt;&amp;lt;%= f.label :title %&amp;gt;: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;%= f.text_field :title %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;      &amp;lt;td&amp;gt;&amp;lt;%= f.label :description %&amp;gt;: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;%= f.text_area :description %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;      &amp;lt;td&amp;gt;&amp;lt;%= f.label :video %&amp;gt;: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;%= f.file_field :uploaded_data %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;    &lt;br /&gt;    &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;%= f.submit 'Submit' %&amp;gt; - &amp;lt;%= link_to 'Back', videos_path %&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;  &amp;lt;/table&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;% end %&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This is the upload form.  Notice I used f.file_field :uploaded_data...this is for attachment_fu to work. Next is /app/views/videos/show.html.erb:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;h1&amp;gt;&amp;lt;%= @video.title %&amp;gt;&amp;lt;/h1&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;%= @video.description %&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;a  &lt;br /&gt;    href=&amp;quot;&amp;lt;%= @video.public_filename %&amp;gt;&amp;quot;  &lt;br /&gt;    style=&amp;quot;display:block;width:400px;height:300px&amp;quot;  &lt;br /&gt;    id=&amp;quot;player&amp;quot;&amp;gt; &lt;br /&gt;  &amp;lt;/a&amp;gt; &lt;br /&gt;   &lt;br /&gt;  &amp;lt;!-- this will install flowplayer inside previous A- tag. --&amp;gt;&lt;br /&gt;  &amp;lt;script&amp;gt;&lt;br /&gt;   flowplayer(&amp;quot;player&amp;quot;, &amp;quot;/flowplayer/flowplayer-3.0.3.swf&amp;quot;);&lt;br /&gt;  &amp;lt;/script&amp;gt;&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And that should do it.  ./script/server and try uploading a movie file and see if it works.  Also, you could probably mess around some with the call to ffmpeg and increase video quality.  There are some good posts if you search for 'ffmpeg' over at the &lt;a href = "http://flowplayer.org/forum/index.html"&gt;FlowPlayer Forums&lt;/a&gt;, and if you purchase a commercial license for the player, you can remove the advertising and get some new features, as well as support.  Thanks for reading!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Update:&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;For a quick way to put the video conversion on a background process, I was able to use Tom Anderson's &lt;a href = "http://github.com/tra/spawn"&gt;Spawn&lt;/a&gt; plugin.  Note that this wouldn't be a very efficient way to scale it if you expect to have a lot of users uploading at the same time, as it forks another process to handle the conversion.  This does work well if there aren't a bunch of videos getting uploaded at the same time.  If you do need to scale the uploading, I recommend using &lt;a href = "http://ap4r.rubyforge.org/wiki/wiki.pl?HomePage"&gt;Ap4r&lt;/a&gt;(Asynchronous Processing for Ruby). Here we go!&lt;/p&gt;&lt;br /&gt;&lt;p&gt;First, lets install the Spawn plugin from github:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;./script/plugin install git://github.com/tra/spawn.git&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And next, change the convert method in Video.rb to this:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  # This method is called from the controller and takes care of the converting&lt;br /&gt;  def convert&lt;br /&gt;    self.convert!&lt;br /&gt;&lt;br /&gt;  #spawn a new thread to handle conversion&lt;br /&gt;  spawn do&lt;br /&gt;&lt;br /&gt;     success = system(convert_command)&lt;br /&gt;     logger.debug 'Converting File: ' + success.to_s&lt;br /&gt;     if success &amp;&amp; $?.exitstatus == 0&lt;br /&gt;       self.converted!&lt;br /&gt;     else&lt;br /&gt;       self.failure!&lt;br /&gt;     end&lt;br /&gt;  end #spawn&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And thats it!  Now when you upload a video, you don't have to wait for the server to convert the video file over to flash.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-3300261362987589228?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/3300261362987589228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=3300261362987589228' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3300261362987589228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3300261362987589228'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2009/01/flash-video-tutorial-with-rails-ffmpeg.html' title='Flash Video Tutorial with Rails, ffmpeg, FlowPlayer, and attachment_fu'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-154205395628339747</id><published>2009-01-22T21:27:00.004-06:00</published><updated>2009-01-22T21:50:14.353-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open source'/><category scheme='http://www.blogger.com/atom/ns#' term='obama'/><title type='text'>Obama to Save Money by Investing in Open Source?</title><content type='html'>Came across an &lt;a href = "http://news.bbc.co.uk/2/hi/technology/7841486.stm"&gt;interesting article&lt;/a&gt; on BBC news today, and thought I would share it.  President Obama's staff, in their quest to make budget cuts, have asked Scott McNealy, a co-founder of Sun Microsystems, to prepare a paper on the subject of using Open Source Software as a way to cut costs.  Mr. McNealy told BBC that he wanted to make sure the government doesn't get 'locked in' to any specific vendor or company. &lt;br /&gt;&lt;br /&gt;I believe it would be a great idea for the government to invest money in Open Source, and would be glad to see some of my tax money being invested in it..as long as the Ruby Community gets its chunk ;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-154205395628339747?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/154205395628339747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=154205395628339747' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/154205395628339747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/154205395628339747'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2009/01/obama-to-save-money-by-investing-in.html' title='Obama to Save Money by Investing in Open Source?'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-4797370435109321419</id><published>2008-08-15T19:54:00.004-05:00</published><updated>2008-08-16T20:29:53.674-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='push server'/><category scheme='http://www.blogger.com/atom/ns#' term='juggernaut'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='chat'/><category scheme='http://www.blogger.com/atom/ns#' term='slightlycoded'/><title type='text'>Juggernaut Push Server</title><content type='html'>&lt;img src = "http://www.slashfilm.com/wp/wp-content/images/juggernaut.jpg" /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://juggernaut.rubyforge.org/"&gt;Juggernaut&lt;/a&gt; is a Rails plugin that allows you to push information out to the client, without them having to specifically request it.  For certain domains, a push server is an excellent solution.  Juggernaut uses a small bit of Flash to open up a flashxmlsocket from the browser to the push server, and it subscribes to the service.  My roommate &lt;a href="http://www.slightlycoded.com"&gt;Taelor&lt;/a&gt; has been playing around with it for a little while, and has put together a chat application that creates rooms off of Digg topics.  Its called &lt;a href="http://www.ShovelChat.com"&gt;Shovel Chat&lt;/a&gt;. He has also made a few blog posts about Juggernaut and using it to create a chatroom with rails at his &lt;a href="http://www.slightlycoded.com/blog"&gt;blog&lt;/a&gt;, and has posted the source code on &lt;a href="http://github.com/taelor/chat_sandbox/tree/master"&gt;GitHub&lt;/a&gt;(note that you will need to go through his blog posts and edit some of the gem's files...)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So, the way the chat app works is that when you request the show action for a chatroom, some flash gets sent to subscribe to the channel on Juggernaut.  Juggernaut will then send you a list of all the people in the room.  If you type in a message and hit enter, the message gets posted to your Rails app.  Inside the controller, the message gets sent to the Juggernaut server, which then pushes the message out to anyone subscribe to that channel.  You could achieve a similar effect using AJAX, but you would have to have each client polling the server for updates to the chatroom, but this would be really difficult to scale.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Anyway, I've gotten his source code installed on my machine and have begun playing around with it, and hope to start contributing to his chat_sandbox on github soon.  Feel free to make your own fork of his code on github and start contributing, and stay tuned for more updates!&lt;br /&gt;&lt;br /&gt;-Ralph&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-4797370435109321419?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/4797370435109321419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=4797370435109321419' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/4797370435109321419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/4797370435109321419'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/08/juggernaut-push-server.html' title='Juggernaut Push Server'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-8160469648741872538</id><published>2008-08-12T02:31:00.001-05:00</published><updated>2008-08-12T02:43:48.721-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hoedown vertebra cloud'/><title type='text'>The Ruby Hoedown</title><content type='html'>&lt;p&gt;Last Thursday, my roommate and I packed and headed 3 hours south to the &lt;a href="http://rubyhoedown.com"&gt;Ruby Hoedown&lt;/a&gt; in Huntsville, AL.  It was held at the Shelby Center at UAH on Friday and Saturday.  This was my first programming conference, so I thought I might jot down a little bit about how it went.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The first presentation was by the guys at &lt;a href="http://railsenvy.com"&gt;Rails Envy&lt;/a&gt;.  They talked about innovation in Ruby over the past year.  I'm a big fan of these guys' podcasts and tutorials, and they gave a great presentation.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Next up was Robert Dempsey, who talked about Cloud Computing with Rails.  He made a great argument against all the folks who say that Rails can't scale.  He gave us very detailed explanations of what a Cloud is, and what scalability is.  He showed us what it takes to use Amazon Web Services to scale a site up, and then gave us a brief descriptions of different utilities out there for scaling with a cloud: Amazon Web Services, Heroku, Joyent, Accelerator, Morph.  One particularly intresting platform was Vertebra, which is being developed by the folks at Engineyard.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Vertebra is a "Next Generation Cloud Computing/Automation Framework".  Ezra Zygmuntowicz has some slides posted at &lt;a href="http://brainspl.at/articles/2008/06/02/introducing-vertebra"&gt;his blog&lt;/a&gt;.  The backbone of the system runs on horizontally scalable erlang XMPP servers.  XMPP is an IM/chat protocol this is very efficient.  Ezra posted this tidbit on his blog: "Just to answer the question about Vertebra being open source or not. Yes vertebra will be open source, the ruby framework, the protocols and security stuff will all be open source. We may go with a commercial license on the workflow engine as that is a large piece of engineering but we have not decided yet. We want to get this out there and see what people do with it as I think there are limitless possibilities here. But we need to lock down the protocol and document everything and we are still experimenting with different parts of the system. I'd hope to have something to release in 4-6 weeks."  Yehuda Katz gave a talk about Vertebra on saturday, and I had a chance to chat with him for a few minutes.  He mentioned that some of the folks from Heroku were helping out on the project.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://onestepback.org"&gt;Jim Weirich&lt;/a&gt; and &lt;a href="http://objo.com"&gt;Joe O'Brien&lt;/a&gt; gave a great talk about mocking.  This was an interesting talk because they acted it all out like they were 2 developers working on different problems that involved using mocks.  The first one involved using a mock object to log in during testing, and in another one, they showed how you can refactor code so that you will be able to use a mock with it.  I chatted with these guys at lunch on Saturday for a while.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Rein Henrich gave a very entertaining talk on Ruby Best Practice Patterns.  He started off with a comical presentation on code unfactoring.  He showed us different methods of making your code so unreadable that you are the only person able to reasonably maintain it.  "Job security through code obscurity."  Some of the methods he showed us were: un-DRYing your code; naming methods and variables in pig latin; and taking code that is abstracted into several small functions, and dumping it all into one huge one.  After the talk on code unfactoring, he went on into his real presentation on best practice patterns.  One of my favorites was the execute around method.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Some other notable talks at the conference included: bryanl(blog &lt;a href="http://smartic.us"&gt;smartic.us&lt;/a&gt;), who talked about why you should "Test all the fucking time"; the truthy gem; Obie Fernandez's great talk on running a successful company; keynote talks by Chris Wanstrath and David Black; Troy Davis did a presentation on Adhearsion, a ruby framework for making and recieving phone calls; Giles Bowkett used Ruby and his program Archaeopteryx, to create music with code;  Being a guitar player, Giles presentation was very interesting to me..unfortunately, Archaeopteryx is only availible for the Mac right now.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I had a great time at the conference.  It was cool to be around so many other Ruby enthusiasts, and everybody was really nice.  I definitely plan on going next year.  Jeremy mentioned that he is planning on holding the Hoedown at Opryland Hotel in Nashville(only an hour away!), and that he hopes to get enough sponsors to host it for free.  Even if it isn't free next year, I will gladly pay out another $200 to go again.  If you've never been to a conference before, I highly recommend it.  It was a very gratifying experience.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Well, thats all for now, I know I promised a post about my Google Summer of Code project, but I don't have it all together yet.  If you are interested, it is a c-extension to speed up some of Ruby's CGI functions.  You can check out the repo on github &lt;a href="http://github.com/balgarath/cgi-ext/tree/master"&gt;here&lt;/a&gt;.  Farewell until next time!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Edit: Also, you can get videos of all the talks at &lt;a href="http://rubyhoedown2008.confreaks.com/"&gt;ConFreaks&lt;/a&gt;.  I spent a while chatting with both of the guys there, and one of them let me plug in my laptop to their powerstrip for the majority of the conference(I need a new battery...).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-8160469648741872538?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/8160469648741872538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=8160469648741872538' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/8160469648741872538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/8160469648741872538'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/08/ruby-hoedown.html' title='The Ruby Hoedown'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-6410099215302459666</id><published>2008-07-27T13:41:00.004-05:00</published><updated>2008-07-27T14:19:45.024-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails host snippet'/><title type='text'>Been a little while...</title><content type='html'>&lt;p&gt;Hi all, thought I would make a post and update things.  I've been busy working on a couple of different gigs: My Place Media, and the Google Summer of Code.  Anyway, My Place Media just ran out of money(lots of bad decisions by the guy calling the shots), so I've got a lot more time to concentrate on my GSoC project.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;My GSoC project is to working on extending parts of Ruby's CGI class in C (mainly the query string parsing and multipart form parsing).  My mentor for the project is &lt;a href="http://m.onkey.org"&gt;Pratik Naik&lt;/a&gt;, a Rails Core member.  I'll have some more info on how the project is coming along in another post.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Anyway, I've got some ideas for expanding RailsonEdge out a little.  The first is that I've purchsed the domain name railsonedge.com, and I have a shared host server.  What I would like to do is to use my server to provide hosting for a few open source Rails apps, and let the developers of them either post to the blog, or just put in a feed from their blog.  So if there is anyone out there that would like free hosting for your Rails project, to show it to the world, shoot me an email at rledge21 -at- gmail -dot- com, and tell me a little about yourself and your project.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I'm planning on posting some new tutorials very soon (maybe even doing a screencast, but I've not decided whether my voice would scare everybody off or not), and putting up a code snippet repository (similar to snippets.dzone.com)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Anyway, that is what is going on.  Expect some posts over the next couple weeks with a couple tutorials, as well as an update to my GSoC project...later all.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-6410099215302459666?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/6410099215302459666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=6410099215302459666' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/6410099215302459666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/6410099215302459666'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/07/been-little-while.html' title='Been a little while...'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-8280617711231960911</id><published>2008-05-02T16:15:00.000-05:00</published><updated>2008-05-02T16:16:43.986-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='symbols'/><title type='text'>Using Symbols</title><content type='html'>&lt;p&gt;If you all are anything like me, symbols confuse the hell out of you.  You may use them, but you don't really understand them.  I decided to research it out a little today and see what I could figure out.  It turns out that there are a lot of different viewpoints of symbols out there.  Here are some articles I came across:&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.troubleshooters.com/codecorn/ruby/symbols.htm"&gt;The Ruby_Newbie Guide to Symbols&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://glu.ttono.us/articles/2005/08/19/understanding-ruby-symbols"&gt;Gluttonous: Understanding Ruby Symbols&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;The first is a detailed overview of symbols, the second shows some of the way Rails uses symbols.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So, as a quick summary, here is what I know about symbols:&lt;br /&gt;A symbol is used to represent strings, without the overhead of actually creating a string.  They don't have the functionality that you get with a string, and the value of them can't be changed, but they are much more efficient than using a string.  Here is part of the example from the Gluttonous article:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; patient1 = { "ruby" =&gt; "red" }&lt;br /&gt;&gt; patient2 = { "ruby" =&gt; "programming" }&lt;br /&gt;&gt; patient1.each_key {|key| puts key.object_id.to_s}&lt;br /&gt;211006&lt;br /&gt;&gt; patient2.each_key {|key| puts key.object_id.to_s}&lt;br /&gt;203536&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The key in both hashes creates(string "ruby") has a string object created each time.  So, in this example, we have 2 seperate string objects with the same name.  You can achieve the same result with symbols:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; patient1 = { :ruby =&gt; "red" }&lt;br /&gt;&gt; patient2 = { :ruby =&gt; "programming" }&lt;br /&gt;&gt; patient1.each_key {|key| puts key.object_id.to_s}&lt;br /&gt;3918094&lt;br /&gt;&gt; patient2.each_key {|key| puts key.object_id.to_s}&lt;br /&gt;3918094&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The difference here is that the same symbol is referenced in both of these.  Not only is symbol a smaller object, but it gets reused.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So I am curious, what ways do you all use symbols?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;-Ralph&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-8280617711231960911?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/8280617711231960911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=8280617711231960911' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/8280617711231960911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/8280617711231960911'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/05/using-symbols.html' title='Using Symbols'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-5766494438172492571</id><published>2008-05-01T22:58:00.005-05:00</published><updated>2008-05-01T23:06:46.090-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='console'/><title type='text'>Intro to the Rails Console</title><content type='html'>&lt;p&gt;Hi all.  Today I'm going to give you a bit of an introduction to the Rails console.  Using it will make your life a lot easier.  To open it up, type ./script/console from your project directory.  From here you can play around, test out commands, add objects to the database if you haven't created an page to do it yet.  I'll be using the console from my Forum tutorial to give you examples, so here we go!&lt;/p&gt;&lt;br /&gt;&lt;p&gt;First, let's load all of our topics from the database into a variable:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; @topics = Topic.find(:all)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Which outputs the following:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;=&gt; [#&amp;lt;Topic id: 1, forum_id: 1, user_id: nil, &lt;br /&gt;subject: "My Rails 2.0 Forum Tutorial", &lt;br /&gt;body: "Check it out, http://railsonedge.blogspot.com",&lt;br /&gt; created_at: "2008-03-06 11:11:07",&lt;br /&gt; updated_at: "2008-03-06 11:11:07"&amp;gt;, &lt;br /&gt;#&amp;lt;Topic id: 2, &lt;br /&gt;.......&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Easy stuff.  Now lets take that hash, and make it into something useful:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;y @topics&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The 'y' function outputs everything in yaml format, much more readable:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;--- &lt;br /&gt;- !ruby/object:Topic &lt;br /&gt;  attributes: &lt;br /&gt;    updated_at: 2008-03-06 11:11:07&lt;br /&gt;    body: Check it out, http://railsonedge.blogspot.com&lt;br /&gt;    subject: My Rails 2.0 Forum Tutorial&lt;br /&gt;    id: "1"&lt;br /&gt;    forum_id: "1"&lt;br /&gt;    user_id: &lt;br /&gt;    created_at: 2008-03-06 11:11:07&lt;br /&gt;  attributes_cache: {}&lt;br /&gt;&lt;br /&gt;- !ruby/object:Topic &lt;br /&gt;  attributes: &lt;br /&gt;    updated_at: 2008-03-06 11:11:37&lt;br /&gt;    body: Check it out! http://railsonedge.blogspot.com&lt;br /&gt;    subject: New Blog Post Today!!&lt;br /&gt;    id: "2"&lt;br /&gt;    forum_id: "1"&lt;br /&gt;    user_id: &lt;br /&gt;    created_at: 2008-03-06 11:11:37&lt;br /&gt;  attributes_cache: {}&lt;br /&gt;&lt;br /&gt;- !ruby/object:Topic &lt;br /&gt;  attributes: &lt;br /&gt;    updated_at: 2008-03-09 00:35:44&lt;br /&gt;    body: Welcome to the new forum.&lt;br /&gt;    subject: Welcome!&lt;br /&gt;    id: "3"&lt;br /&gt;    forum_id: "2"&lt;br /&gt;    user_id: &lt;br /&gt;    created_at: 2008-03-09 00:35:44&lt;br /&gt;  attributes_cache: {}&lt;br /&gt;&lt;br /&gt;- !ruby/object:Topic &lt;br /&gt;  attributes: &lt;br /&gt;    updated_at: 2008-03-09 00:36:04&lt;br /&gt;    body: What time is it?&lt;br /&gt;    subject: "Question:"&lt;br /&gt;    id: "4"&lt;br /&gt;    forum_id: "2"&lt;br /&gt;    user_id: &lt;br /&gt;    created_at: 2008-03-09 00:36:04&lt;br /&gt;  attributes_cache: {}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now, lets grab just one of the topics and play around with that:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@topic = Topic.find(1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;You can use the 'y' function on this also.  Try this to display certain attributes of @topic:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; @topic.body&lt;br /&gt;=&gt; "Check it out, http://railsonedge.blogspot.com"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And you can change these attributes pretty easily also:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; @topic.body = "And now the body says this."&lt;br /&gt;=&gt; "And now the body says this."&lt;br /&gt;&gt;&gt; @topic.body&lt;br /&gt;=&gt; "And now the body says this."&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;When you change an attribute, it doesn't automatically save it to the database.  But not to worry, it is easy enough:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; @topic.save&lt;br /&gt;=&gt; true&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Additionally, if you are working on a project and don't have a create page set up yet for an object yet, you can just create one from the console:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; topic = Topic.new :body =&gt; "Lorem Ipsum", &lt;br /&gt;:subject =&gt; "This Subject", :forum_id =&gt; 1, :user_id =&gt; 1&lt;br /&gt;=&gt; #&amp;lt;Topic id: nil, forum_id: 1, user_id: 1, &lt;br /&gt;subject: "This Subject", body: "Lorem Ipsum", &lt;br /&gt;created_at: nil, updated_at: nil&amp;gt;&lt;br /&gt;&gt;&gt; topic.save&lt;br /&gt;=&gt; true&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;That is enough for some basic manipulation of things in your database, but what other things can you do with the console?  What if you wanted to see all of the functions that can be used on a specific object?  Well, just like when you are using bash, you can use tab to auto-complete:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;String.to_        [press tab not enter]&lt;br /&gt;&lt;br /&gt;String.to_a                String.to_s&lt;br /&gt;String.to_enum             String.to_yaml&lt;br /&gt;String.to_json             String.to_yaml_properties&lt;br /&gt;String.to_param            String.to_yaml_style&lt;br /&gt;String.to_query      &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Another good thing to use the rails console for is to test out little bits of code to see how they run.  Here is a simple example using a loop in the console:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;@topics = Topic.find(:all)&lt;br /&gt;&gt;&gt; for topic in @topics do&lt;br /&gt;?&gt; puts topic.subject + " - append this"&lt;br /&gt;&gt;&gt; end&lt;br /&gt;&lt;br /&gt;My Rails 2.0 Forum Tutorial - append this&lt;br /&gt;New Blog Post Today!! - append this&lt;br /&gt;Welcome! - append this&lt;br /&gt;Question: - append this&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;As with most terminals, you can access your command history by using the up arrow.  &lt;br /&gt;Another cool thing, when you are messing around with routing, you can check things out quickly with app.url_for and app.get:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; app.url_for(:controller =&gt; 'forums', :action =&gt; 'index')&lt;br /&gt;=&gt; "http://www.example.com/forums"&lt;br /&gt;&lt;br /&gt;&gt;&gt; app.get '/forums/1/topics'&lt;br /&gt;=&gt; 200&lt;br /&gt;&lt;br /&gt;&gt;&gt; app.get '/invalid/url'&lt;br /&gt;=&gt; 404&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The underscore('_') character will return the value of the last statement:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt; 5 + 9&lt;br /&gt;=&gt; 14&lt;br /&gt;&gt;&gt; _&lt;br /&gt;=&gt; 14&lt;br /&gt;&gt;&gt; _ + 6&lt;br /&gt;=&gt; 20&lt;br /&gt;&gt;&gt; _&lt;br /&gt;=&gt; 20&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Well, that is it for now.  Let me know what other uses you guys (and girls?) have for the console.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Later,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;-Ralph&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-5766494438172492571?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/5766494438172492571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=5766494438172492571' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/5766494438172492571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/5766494438172492571'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/05/intro-to-rails-console.html' title='Intro to the Rails Console'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-6745697729927584892</id><published>2008-04-25T16:25:00.002-05:00</published><updated>2008-04-25T19:22:09.939-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='partial layout'/><category scheme='http://www.blogger.com/atom/ns#' term='view'/><category scheme='http://www.blogger.com/atom/ns#' term='DRY'/><title type='text'>DRY Up Your Views With Layouts For Your Partials</title><content type='html'>&lt;p&gt;I got comments on my previous post, &lt;a href="http://railsonedge.blogspot.com/2008/04/dry-up-your-views-with-nested-partials.html"&gt;DRY up your views with nested partials&lt;/a&gt;, letting me know that there is a better way.  So here is the same thing, done the proper way:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;First, I've got this cool set of divs that gives me a nice looking window I will be reusing:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt; &lt;br /&gt;  &amp;lt;div id="window-top"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window"&amp;gt;&lt;br /&gt;    &amp;lt;%= render :partial =&amp;gt; 'mypartial' %&gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window-bottom"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;div id="window-top"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window"&amp;gt;&lt;br /&gt;    &amp;lt;%= render :partial =&amp;gt; 'myotherpartial' %&gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window-bottom"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The goal here is to be able to re-use the code for the window multiple times.  First, lets create a partial called '_lorem.html.erb':&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;p&amp;gt;"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do &lt;br /&gt;eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim &lt;br /&gt;veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo&lt;br /&gt; consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse &lt;br /&gt; cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat &lt;br /&gt; non proident, sunt in culpa qui officia deserunt mollit anim id est &lt;br /&gt; laborum." &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And another called '_blah.html.erb':&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;p&amp;gt;blah blah blah blah blah blah blah blah blah blah blah blah blah &lt;br /&gt;blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah &lt;br /&gt;blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah &lt;br /&gt;blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah &lt;br /&gt;blah blah blah &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Alright! Now, make one last partial, which will be used for the layout, called '_window.html.erb'.  Note that it needs to be created in the same directory as the other partials.  This is where you put the code for the cool window you just made.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;div id="window-container"&amp;gt;&lt;br /&gt;  &amp;lt;div id="window-top-left"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div id="window-top"&amp;gt;Window Title&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div id="window-top-right"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window"&amp;gt;&lt;br /&gt;    &amp;lt;%= yield %&gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window-bottom-left"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div id="window-bottom"&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&amp;lt;div id="window-bottom-right"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And now, when you want to render a partial that is inside your window, all you need to do is set the layout to window:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;h1&amp;gt;Test of nested partials&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= render :partial =&amp;gt; 'blah', :layout =&gt; 'window' %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= render :partial =&amp;gt; 'lorem', :layout =&gt; 'window' %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen17.jpg" /&gt;&lt;br /&gt;&lt;p&gt;And thats it!  Enjoy DRYing up your views.  Later&lt;br /&gt;&lt;br /&gt;-Ralph&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;EDIT: if you use :layout =&gt; 'layouts/window', you can put '_window.html.erb' in /views/application and reuse it throughout the site.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-6745697729927584892?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/6745697729927584892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=6745697729927584892' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/6745697729927584892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/6745697729927584892'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/04/dry-up-your-views-with-layouts-for-your.html' title='DRY Up Your Views With Layouts For Your Partials'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-5101787548612594400</id><published>2008-04-16T23:19:00.002-05:00</published><updated>2008-04-25T16:29:16.271-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nested partial'/><category scheme='http://www.blogger.com/atom/ns#' term='rails 2.0'/><title type='text'>DRY up your views with nested partials</title><content type='html'>&lt;p&gt;NOTE: I got a couple of comments letting me know that the proper way to do this is  to use a layout with your partial.  Please see &lt;a href="http://railsonedge.blogspot.com/2008/04/dry-up-your-views-with-layouts-for-your.html"&gt;this&lt;/a&gt; post for instructions.  Since making this post, I've been told the partial nesting is generally a bad idea, so use at your own risk.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Got a good one for you today that should help clean up your views and DRY things out.  How many times, when building a website, do you use the same code over and over again to build this cool looking window that is re-used over and over?&lt;/p&gt;&lt;br /&gt;&lt;pre&gt; &lt;br /&gt;  &amp;lt;div id="window-top"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window"&amp;gt;&lt;br /&gt;    &amp;lt;%= render :partial =&amp;gt; 'mypartial' %&gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window-bottom"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;div id="window-top"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window"&amp;gt;&lt;br /&gt;    &amp;lt;%= render :partial =&amp;gt; 'myotherpartial' %&gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window-bottom"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Well, you can use nested partials to achieve the same effect and re-use your window code.  First, lets create a partial called '_lorem.html.erb':&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;p&amp;gt;"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do &lt;br /&gt;eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim &lt;br /&gt;veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo&lt;br /&gt; consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse &lt;br /&gt; cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat &lt;br /&gt; non proident, sunt in culpa qui officia deserunt mollit anim id est &lt;br /&gt; laborum." &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And another called '_blah.html.erb':&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;p&amp;gt;blah blah blah blah blah blah blah blah blah blah blah blah blah &lt;br /&gt;blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah &lt;br /&gt;blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah &lt;br /&gt;blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah &lt;br /&gt;blah blah blah &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Alright! Now, make one last partial, '_window.html.erb'.  This is where you put the code for the cool window you just made. &lt;br /&gt;Inside of it, you want to render a partial, and pass in the variable 'name':&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;div id="window-container"&amp;gt;&lt;br /&gt;  &amp;lt;div id="window-top-left"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div id="window-top"&amp;gt;Window Title&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div id="window-top-right"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window"&amp;gt;&lt;br /&gt;    &amp;lt;%= render :partial =&amp;gt; name %&gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="window-bottom-left"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div id="window-bottom"&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&amp;lt;div id="window-bottom-right"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And now, when you want to render a partial that is inside your window, all you need to do is render the 'window' partial, and as a local&lt;br /&gt;variable named 'name', pass in the name of the partial you want rendered inside of it:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;h1&amp;gt;Test of nested partials&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= render :partial =&amp;gt; 'window', :locals =&gt; {:name =&gt; 'lorem' } %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= render :partial =&amp;gt; 'window', :locals =&gt; {:name =&gt; 'blah' } %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen17.jpg" /&gt;&lt;br /&gt;&lt;p&gt;And thats it!  Enjoy DRYing up your views with nested partials.  Later&lt;br /&gt;&lt;br /&gt;-Ralph&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-5101787548612594400?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/5101787548612594400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=5101787548612594400' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/5101787548612594400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/5101787548612594400'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/04/dry-up-your-views-with-nested-partials.html' title='DRY up your views with nested partials'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-5330895441077291051</id><published>2008-04-09T16:29:00.004-05:00</published><updated>2008-04-09T16:39:59.684-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='helpers'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveScaffold'/><category scheme='http://www.blogger.com/atom/ns#' term='same name'/><category scheme='http://www.blogger.com/atom/ns#' term='override'/><title type='text'>ActiveScaffold - Helpers for columns with same name overwrite each other - FIX</title><content type='html'>&lt;p&gt;Really quick one today.  I was working on my ActiveScaffold project, and came across the following problem:&lt;br /&gt;My Events table has a column called schools, and so does my Schools table.  For the Events, I needed a dropdown box listing all schools...while for Schools, I needed a text box to show up to type in the name of the school.  Since textboxes are the default for activescaffold, I shouldn't need to do anything with schools in it, however, when I wrote a form override for Events in event_helper.rb to give it a dropdown box...the dropdown showed up in Schools also.  So first, I tried doing a form override in the school_helper.rb.  No luck, the event helper method has the same name, and overrides whatever method I put in school with the same name.  So to fix it, I removed my helper methods from the event and school helpers.  In application_helper.rb, I made a function with the same name as the form override function I had been trying to use, and then used an if to determine which model the helper was being called from.  Here is the code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Methods added to this helper will be available to all templates in the application.&lt;br /&gt;module ApplicationHelper&lt;br /&gt;&lt;br /&gt;  #hack to make activescaffold form overrides work when 2 models have a field that is the same name&lt;br /&gt;  def school_form_column(record, input_name)&lt;br /&gt;    if record.class.name == "Event"&lt;br /&gt;      select_tag input_name, options_for_select(aschools, selected = record.school)&lt;br /&gt;    else  #record.class.name =="School"&lt;br /&gt;      text_field :record, :school, :name =&gt; input_name&lt;br /&gt;    end  &lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  private&lt;br /&gt;  #used in case of Event&lt;br /&gt;  def aschools&lt;br /&gt;    @schools = School.find(:all, :order =&gt; 'school')&lt;br /&gt;    @schooloptions = Hash.new&lt;br /&gt;    for school in @schools&lt;br /&gt;      @schooloptions[school.school] = school.abbrv&lt;br /&gt;    end&lt;br /&gt;    @schooloptions = @schooloptions.sort.each { |e| puts "#{e[0]} =&gt; #{e[1]}" }&lt;br /&gt;&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Me: 2&lt;br /&gt;ActiveScaffold: 0&lt;br /&gt;&lt;br /&gt;Done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-5330895441077291051?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/5330895441077291051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=5330895441077291051' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/5330895441077291051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/5330895441077291051'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/04/activescaffold-helpers-for-columns-with.html' title='ActiveScaffold - Helpers for columns with same name overwrite each other - FIX'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-748385036903008964</id><published>2008-04-02T12:37:00.008-05:00</published><updated>2008-04-09T16:17:32.533-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails 2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='links'/><title type='text'>Rails 2.0 Links</title><content type='html'>&lt;p&gt;Decided to make a post with links to all the good resources I have come across so far.   I'll be putting a permanent link to it on the sidebar. Feel free to leave a comment if you have any links you would like me to add.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.rubyplus.org"&gt;RubyPlus.org&lt;/a&gt; - Lots of good screencasts; Restful Authentication, AWDR's Depot app for Rails 2.0&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.railsenvy.com"&gt;Rails Envy&lt;/a&gt; - They have a great ActiveRecord intro video here, among other things&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.railscasts.com"&gt;Railscasts&lt;/a&gt; - Should need no introduction :)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.planetrubyonrails.com"&gt;Planet Ruby on Rails&lt;/a&gt; - Has feeds from many different Rails blogs all in one convenient place&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://instantrails.rubyforge.org/wiki/wiki.pl"&gt;InstantRails&lt;/a&gt; - For you Windows users, this program is a quick way to get up and going with Rails&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.danielfischer.com/2008/01/09/how-to-use-gmail-as-your-mail-server-for-rails/"&gt;DanielFischer.com&lt;/a&gt;Tutorial for using Gmail as a mail server for a Rails project.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.jonathansng.com/ruby-on-rails/rails-send-email-tutorial/"&gt;Jonathan s ng&lt;/a&gt; - ActionMailer Tutorial&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://railsapi.org/actioncontroller-base-render"&gt;Render Examples&lt;/a&gt; - Great render examples, helps when needing to render things with AJAX&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://softiesonrails.com/2008/3/21/absolute-moron-s-guide-to-forms-in-rails-part-1"&gt;Absolute Moron's Guide to Forms in Rails&lt;/a&gt; - Great form tutorial&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Will be adding many more links in the days to come, this is just a preliminary list.  Also, I would like to get some links for setting up Rails for development on several OS's(Linux flavors, MAC, ...), so if you have any please leave a comment.&lt;/p&gt;&lt;br /&gt;Later.&lt;br /&gt;&lt;br /&gt;-Ralph&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-748385036903008964?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/748385036903008964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=748385036903008964' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/748385036903008964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/748385036903008964'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/04/rails-20-links.html' title='Rails 2.0 Links'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-563159750116800936</id><published>2008-03-25T23:37:00.004-05:00</published><updated>2008-03-25T23:42:36.372-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='activerecord'/><title type='text'>Found a nice ActiveRecord Tutorial</title><content type='html'>&lt;p&gt;Wish I had found this a couple of months ago, it would have moved me along a lot.  I still learned a good deal from it though.&lt;br /&gt;Check it out at:&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.railsenvy.com/2007/8/8/activerecord-tutorial"&gt;Rails Envy&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;-Ralph&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-563159750116800936?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/563159750116800936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=563159750116800936' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/563159750116800936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/563159750116800936'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/03/found-nice-activerecord-tutorial.html' title='Found a nice ActiveRecord Tutorial'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-1530360871170219605</id><published>2008-03-24T10:58:00.003-05:00</published><updated>2008-03-24T11:04:29.542-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='typecast'/><category scheme='http://www.blogger.com/atom/ns#' term='tinyint'/><category scheme='http://www.blogger.com/atom/ns#' term='boolean'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>Legacy MySQL Database - TinyInt</title><content type='html'>&lt;p&gt;Apparently Rails typecasts MySQL tinyint's as booleans.  I was working on a Rails app for a legacy database today when I realized that I couldn't pull the value out of my 'terms' column.  All it would read is a true or false, and not the actual value.  After a bit of research, I discovered before_type_cast accessor.  So instead of using report.terms, in order to get the value out, I had to use report.terms_before_type_cast.  &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Short post, but I'm sure someone will have the same problem at some point and will find it helpful.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Later.&lt;br /&gt;&lt;br /&gt;-Ralph&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-1530360871170219605?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/1530360871170219605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=1530360871170219605' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/1530360871170219605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/1530360871170219605'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/03/legacy-mysql-database-tinyint.html' title='Legacy MySQL Database - TinyInt'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-4149241729794470215</id><published>2008-03-21T20:08:00.005-05:00</published><updated>2008-04-09T09:54:01.222-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AJAX'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='rails 2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='beginner'/><title type='text'>Tutorial: Beginning AJAX with Rails 2.0</title><content type='html'>&lt;p&gt;Today, I'm going to go over a quick tutorial of some basic AJAX functions.  Rails has a great implementation with AJAX right out of the box, with the Prototype library.  It also includes the Scriptaculous library with some special effects.  We are just going to do some basic writing text into the site without page reloading.  Lets get started.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Set up the application:&lt;/h3&gt;&lt;br /&gt;&lt;pre&gt; &lt;br /&gt;  rails ajaxtest -d mysql&lt;br /&gt;  cd ajaxtest&lt;br /&gt;  ./script/generate model Foobar foo:string bar:string&lt;br /&gt;  ./script/generate Controller Foobars&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This is our first project that doesn't use scaffolding - I decided against it because scaffolding would have generated all kinds of views we aren't going to need for this.  Notice that when you created the model, it automatically generated your DB migration file.  Now, lets open up app/controllers/foobars_controller.rb and do this:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  class FoobarsController &lt; ApplicationController&lt;br /&gt;    def index&lt;br /&gt;      @foobars = Foobar.find(:all)&lt;br /&gt;      &lt;br /&gt;      respond_to do |format|&lt;br /&gt;        format.html # index.html.erb&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Next, create app/views/foobars/index.html.erb:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;h3&amp;gt;Foobars!&amp;lt;/h3&amp;gt;&lt;br /&gt;  &amp;lt;table&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Foo&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Bar&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;  &amp;lt;% for foobar in @foobars do %&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;      &amp;lt;td&amp;gt;&amp;lt;%= foobar.foo %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;      &amp;lt;td&amp;gt;&amp;lt;%= foobar.bar %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;  &amp;lt;% end %&amp;gt;&lt;br /&gt;  &amp;lt;/table&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now lets add our routing.  In config/routes.rb add:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;  map.resources :foobars&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;In your console, lets get our db created and foobars table setup:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rake db:create&lt;br /&gt;rake db:migrate&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And one last thing.  We need to populate our table with a few foobars.  This is a good time to show you the rails interactive console:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;./script/console&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;From here, we can give commands directly to our project. Lets try one:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;Foobar.find(:all)&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &gt;&gt; Foobar.find(:all)&lt;br /&gt;  =&gt; []&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;So it returned an empty array.  The interactive console is great for playing around with bits of code to see what they do or even testing out bits of code.  Lets try another command:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &gt;&gt; myfoobar = Foobar.new&lt;br /&gt;  =&gt; #&amp;lt;Foobar id: nil, foo: nil, bar: nil, created_at: nil, updated_at: nil&amp;gt;&lt;br /&gt;  &gt;&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Creates a new foobar object...&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &gt;&gt; myfoobar.foo = "This is a test."&lt;br /&gt;  =&gt; "This is a test."&lt;br /&gt;  &gt;&gt; myfoobar.bar = "This is only a test."&lt;br /&gt;  =&gt; "This is only a test."&lt;br /&gt;  &gt;&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;We can set the values of foo and bar for our new foobar, and...&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &gt;&gt; myfoobar.save&lt;br /&gt;  =&gt; true&lt;br /&gt;  &gt;&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;We can save it to the database.  Lets try looking it up with find...&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &gt;&gt; Foobar.find(:all)&lt;br /&gt;  =&gt; [#&amp;lt;Foobar id: 1, foo: "This is a test.", bar: "This is only a test.", created_at: "2008-03-21 18:24:46", updated_at: "2008-03-21 18:24:46"&amp;gt;]&lt;br /&gt;  &gt;&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Great - so far so good.  Now lets create a few more foobars:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  myfoobar = Foobar.new&lt;br /&gt;  myfoobar.foo = "Foo of foobar #2"&lt;br /&gt;  myfoobar.bar = "Bar of foobar #2"&lt;br /&gt;  myfoobar.save&lt;br /&gt;&lt;br /&gt;  myfoobar = Foobar.new&lt;br /&gt;  myfoobar.foo = "Foo of foobar #3"&lt;br /&gt;  myfoobar.bar = "Bar of foobar #3"&lt;br /&gt;  myfoobar.save&lt;br /&gt;  &lt;br /&gt;  myfoobar = Foobar.new&lt;br /&gt;  myfoobar.foo = "Foo of foobar #4"&lt;br /&gt;  myfoobar.bar = "Bar of foobar #4"&lt;br /&gt;  myfoobar.save&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And done.  You can type exit to leave the interactive console.  Start the server, browse to localhost:PORT/foobars&lt;/p&gt;&lt;br /&gt;&lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen15.jpg" /&gt;&lt;br /&gt;&lt;h3&gt;Tablespoon of AJAX&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;First thing, I'm going to tell you that if you don't have Firebug yet, go ahead and get it.  It is a plugin for Firefox(you are using firefox, right? nothing against you Safari/Opera lovers..if you are using IE you have no excuses, get Firefox and get Firebug...now). Firebug is a great tool for design as well as for AJAX.  The inspect mode will highlight divs under your mouse and show the corresponding html/css code in the panel below.  You can also take a look at Javascript AJAX responses and more quickly debug your code. Lets create app/views/layouts/application.html.erb:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;      &amp;lt;%= javascript_include_tag :defaults %&amp;gt;      &lt;br /&gt;    &amp;lt;/head&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;      &amp;lt;%= yield :layout %&amp;gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;  &amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The include tag will include (among other things) the prototype library that you need to make the AJAX calls.  Now, lets head back to app/views/foobars/index.html.erb and set it up for our AJAX.  Change it to this:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;h3&amp;gt;Foobars!&amp;lt;/h3&amp;gt;&lt;br /&gt;  &amp;lt;table&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;      &amp;lt;th&amp;gt;Foo&amp;lt;/th&amp;gt;&lt;br /&gt;      &amp;lt;th&amp;gt;Bar&amp;lt;/th&amp;gt;&lt;br /&gt;      &amp;lt;th&amp;gt;Which?&amp;lt;/th&amp;gt;&lt;br /&gt;      &amp;lt;th&amp;gt;Links&amp;lt;/th&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;  &amp;lt;% for foobar in @foobars do %&amp;gt;&lt;br /&gt;    &amp;lt;% idstring = "foobar-" + foobar.id.to_s %&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;      &amp;lt;td&amp;gt;&amp;lt;%= foobar.foo %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;      &amp;lt;td&amp;gt;&amp;lt;%= foobar.bar %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;      &amp;lt;td id="&amp;lt;%= idstring %&amp;gt;"&gt;&amp;lt;/td&amp;gt;&lt;br /&gt;      &amp;lt;td&amp;gt;&lt;br /&gt;        &amp;lt;%= link_to_remote "Foo", :url =&amp;gt;{ :action =&gt; :set, :updatewith =&gt; foobar.foo }, &lt;br /&gt;                                     :update =&gt; idstring %&gt; &lt;br /&gt;        &amp;nbsp;&amp;nbsp;&lt;br /&gt;        &amp;lt;%= link_to_remote "Bar", :url =&amp;gt;{ :action =&gt; :set, :updatewith =&gt; foobar.bar }, &lt;br /&gt;                                     :update =&gt; idstring %&gt;&lt;br /&gt;      &amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;  &amp;lt;% end %&amp;gt;&lt;br /&gt;  &amp;lt;/table&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;We have 2 more columns in our table now - Which? will be updated by AJAX with either the foo or the bar of our current Foobar depending on the link clicked from the Links column.  In the Links column, we have 2 link_to_remote 's.  link_to_remote generates all the javascript calls to send an AJAX request back to our controller on the server.  The first argument is what will be displayed for the link.  In :url, we define the action to send the request to (:set), as well as the string we want to pass into the function (:updatewith).  Last, :update will be the name of the div we will be updating.  You can also add another parameter, :position.  For example, :position =&gt; :before would insert whatever you are sending before the td tag, :after would be after it, :top would insert it inside the td, above anything else, and :bottom inserts it inside the td, at the bottom.  If you do not specify a position(like we are doing), it will simply over-write what is inside the div.  One more thing to do; lets open up app/controllers/foobars_controller.rb and add in our :set action:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def set&lt;br /&gt;    render :text  =&gt; params[:updatewith]&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Go back to the page and try clicking the links&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Update: I found &lt;a href="http://railsapi.org/actioncontroller-base-render"&gt;this&lt;/a&gt; link to be very helpful with different ways of using render with AJAX.&lt;/p&gt;&lt;br /&gt;&lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen16.jpg" /&gt;&lt;br /&gt;&lt;p&gt;And we are done!  Thanks for visiting, and see you next time.&lt;/p&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;digg_url = 'http://railsonedge.blogspot.com/2008/03/tutorial-beginning-ajax-with-rails-20.html';&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-4149241729794470215?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/4149241729794470215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=4149241729794470215' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/4149241729794470215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/4149241729794470215'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/03/tutorial-beginning-ajax-with-rails-20.html' title='Tutorial: Beginning AJAX with Rails 2.0'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-3908636897596432633</id><published>2008-03-12T12:44:00.004-05:00</published><updated>2008-03-12T12:48:39.311-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ActiveScaffold'/><category scheme='http://www.blogger.com/atom/ns#' term='no text field'/><category scheme='http://www.blogger.com/atom/ns#' term='blob'/><title type='text'>Using a 'blob' with ActiveScaffold</title><content type='html'>&lt;p&gt;So I'm using ActiveScaffold to create an admin interface for a site, using a legacy database.  It has a table called 'Events', one of the column names is event, of type medium blob, which will only contain text.  ActiveScaffold will display the contents of the blob field correctly, but when you go to create a new Event or edit an existing one, it will not give you a text field to enter anything in.  Here is the fix:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In app/helpers, I created a file event_helper.rb and put this code in it:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;module EventHelper&lt;br /&gt;&lt;br /&gt;  def event_form_column(record, input_name)&lt;br /&gt;    text_field :record, :event, :name =&gt; input_name&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;And everything worked fine.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-3908636897596432633?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/3908636897596432633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=3908636897596432633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3908636897596432633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3908636897596432633'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/03/using-blob-with-activescaffold.html' title='Using a &apos;blob&apos; with ActiveScaffold'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-3718759120432896339</id><published>2008-03-12T09:30:00.003-05:00</published><updated>2008-03-12T09:41:33.275-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='begin rescue'/><category scheme='http://www.blogger.com/atom/ns#' term='rails 2.0 tutorial forum restful_authentication'/><category scheme='http://www.blogger.com/atom/ns#' term='RecordNotFound'/><title type='text'>Begin Rescue Else End</title><content type='html'>&lt;p&gt;So today I was working on a project.  This project will be an admin interface for an application that has already been running for a while(which was written in PHP).  So I am having to use a legacy database(tutorial coming soon for making admin interface for a legacy DB!) Anyway, I have an employee, and a department.  The employee references which department he is in by the ID.  However, some employees have an ID that is not used in the department table(department got deleted at some point, never existed, who knows?).  &lt;/p&gt;&lt;br /&gt;In my employee model, I am making a function to take the department id from the employee tables(thisdept), and look up the number in the department table to get the name of the department, all pretty standard stuff.&lt;/p&gt;&lt;br /&gt;&lt;p&gt; Here is what I tried first:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def deptname&lt;br /&gt;    dept = Department.find(thisdept)&lt;br /&gt;    dept.name      &lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; ActiveRecord::RecordNotFound in Employees#index&lt;br /&gt;&lt;br /&gt;Showing vendor/plugins/active_scaffold/frontends/default/views/_list_record.rhtml where line #10 raised:&lt;br /&gt;&lt;br /&gt;Couldn't find Department with ID=13&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So we are going to need something along the lines of a try - catch.  Ruby's equivalent is the begin-rescue-else-end.  Begin is the code that might throw an error.  Rescue is the code to excute if there is an error.  Else is executed if there is no error.  You can also add an ensure block, which will be run after everything, regardless.  Here is my fix:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def deptname&lt;br /&gt;    begin&lt;br /&gt;      dept = Department.find(thisdept)&lt;br /&gt;    rescue&lt;br /&gt;      "No Department"&lt;br /&gt;    else&lt;br /&gt;      dept.name&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Works like a charm!  See you next time.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-3718759120432896339?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/3718759120432896339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=3718759120432896339' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3718759120432896339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3718759120432896339'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/03/begin-rescue-else-end.html' title='Begin Rescue Else End'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-1604846062643818850</id><published>2008-03-10T01:42:00.011-05:00</published><updated>2008-04-25T19:02:13.178-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails 2.0 tutorial forum restful_authentication'/><title type='text'>Rails Forum - Restful Authentication(Part 3 of 3)</title><content type='html'>So here is part 3 of 3 for my Rails 2.0 Forum Tutorial for Beginners.  Today we are going to put authentication on top of our application, using the restful_authentication and acts_as_state_machine plugins.  &lt;br /&gt;&lt;b&gt;&lt;br /&gt;NOTE: If you don't want to do Parts 1 and 2, you can download the code for them &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/myforum.tar.gz"&gt;here&lt;/a&gt;, and use this as a stand-alone tutorial.  Please note that our Topic and Reply models both belongs_to a user.&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;I got a lot of this stuff from &lt;a href="www.rubyplus.org"&gt;RubyPlus&lt;/a&gt;'s RESTful Authentication tutorial.  Let's get started!&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    cd myforum&lt;br /&gt;    &lt;small&gt;&lt;br /&gt;      ruby script/plugin install http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk&lt;br /&gt;      ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication&lt;br /&gt;      ruby script/generate authenticated user sessions --include-activation --stateful&lt;br /&gt;    &lt;/small&gt;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;To break down that last command - authenticated is part of the restful_authentication.  user is the model to be generated for the user.  sessions will be the controller to handle logging in/out, --include-activation will help with creating the stuff needed to mail an activation link to the user's email, and --stateful is for support for acts_as_state_machine plugin.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Now that our files are generated, let's head to /config/routes.rb and make a couple of changes. Notice that the map.resources :users and map.resources :session lines have already been generated by the generate authenticated call.  The version of restful_authentication used in the tutorial on &lt;a href="rubyplus.org"&gt;RubyPlus&lt;/a&gt; did not automatically generate them.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;So in routes.rb:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  #CHANGE THIS LINE&lt;br /&gt;    map.resources :users&lt;br /&gt; &lt;br /&gt;  #TO THIS&lt;br /&gt;    map.resources :users, :member =&gt; { :suspend =&gt; :put,&lt;br /&gt;                                        :unsuspend =&gt; :put,&lt;br /&gt;                                        :purge =&gt; :delete }&lt;br /&gt;&lt;br /&gt;  #AND THEN ADD THE FOLLOWING LINES&lt;br /&gt;    map.activate '/activate/:activation_code', :controller =&gt; 'users', &lt;br /&gt;                                               :action =&gt; 'activate'&lt;br /&gt;    map.signup '/signup', :controller =&gt; 'users', :action =&gt; 'new'&lt;br /&gt;    map.login  '/login', :controller =&gt; 'sessions', :action =&gt; 'new'&lt;br /&gt;    map.logout '/logout', :controller =&gt; 'sessions', :action =&gt; 'destroy'&lt;br /&gt;    map.forgot_password '/forgot_password', :controller =&gt; 'users', &lt;br /&gt;                                            :action =&gt; 'forgot_password'&lt;br /&gt;    map.reset_password '/reset_password/:id', :controller =&gt; 'users', &lt;br /&gt;                                              :action =&gt; 'reset_password'                                      &lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;The :member =&amp;gt; part sets up some restful actions for the users controller.  All the lines that we added sets up named routes for user and session controller/action pairs.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Now, open up /config/environment.rb:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  #BELOW THE LINE&lt;br /&gt;  Rails::Initializer.run do |config|&lt;br /&gt;&lt;br /&gt;  #ADD THIS&lt;br /&gt;    config.active_record.observers = :user_observer&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;The observer watches the user model and will be used to send an EMail whenever a new user is created.  Next, lets open up /db/migrate/004_create_users.rb and do this.&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  #OLD 004_create_users.rb&lt;br /&gt;  class CreateUsers &lt; ActiveRecord::Migration&lt;br /&gt;    def self.up&lt;br /&gt;      create_table "users", :force =&gt; true do |t|&lt;br /&gt;        t.column :login,                     :string&lt;br /&gt;        t.column :email,                     :string&lt;br /&gt;        t.column :crypted_password,          :string, :limit =&gt; 40&lt;br /&gt;        t.column :salt,                      :string, :limit =&gt; 40&lt;br /&gt;        t.column :created_at,                :datetime&lt;br /&gt;        t.column :updated_at,                :datetime&lt;br /&gt;        t.column :remember_token,            :string&lt;br /&gt;        t.column :remember_token_expires_at, :datetime&lt;br /&gt;        t.column :activation_code, :string, :limit =&gt; 40&lt;br /&gt;        t.column :activated_at, :datetime&lt;br /&gt;        t.column :state, :string, :null =&gt; :no, :default =&gt; 'passive'&lt;br /&gt;        t.column :deleted_at, :datetime&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def self.down&lt;br /&gt;      drop_table "users"&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  #NEW 004_create_users.rb&lt;br /&gt;  class CreateUsers &lt; ActiveRecord::Migration&lt;br /&gt;    def self.up&lt;br /&gt;      create_table "users", :force =&gt; true do |t|&lt;br /&gt;        t.string :login, :email, :remember_token&lt;br /&gt;        t.string :crypted_password,          :limit =&gt; 40&lt;br /&gt;        t.string :password_reset_code,       :limit =&gt; 40&lt;br /&gt;        t.string :salt,                      :limit =&gt; 40      &lt;br /&gt;        t.string :activation_code,           :limit =&gt; 40&lt;br /&gt;        t.datetime :remember_token_expires_at, :activated_at, :deleted_at&lt;br /&gt;        t.string :state, :null =&gt; :no, :default =&gt; 'passive'&lt;br /&gt;&lt;br /&gt;        t.timestamps&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def self.down&lt;br /&gt;      drop_table "users"&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;There we are just cleaning up the code a little bit.  We did add a :password_reset_code column - will be used if a user forgets their password(more on that later). Now just run the migration to create our new tables...&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;rake db:migrate&lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;Next, open up app/controllers/sessions_controller and copy the line include AuthenticatedSystem to /app/controllers/application.rb.  Also, in users_controller, remove the same line.  This will make sure that the restful_authentication functions are included on every page.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Now, remove these lines from users_controller in the create function:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;        self.current_user = @user&lt;br /&gt;        redirect_back_or_default('/')&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;We removed the first line because we do not want to log the user in when they register, we want to verify their EMail.  The second line was removed so that Rails would look for create.html.erb after running the create action.  Now, create a file /app/views/users/create.html.erb and put something like this in it:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    &amp;lt;fieldset&amp;gt;&lt;br /&gt;      &amp;lt;legend&amp;gt;Your forum account&amp;lt;/legend&amp;gt;&lt;br /&gt;      &lt;br /&gt;      &amp;lt;p&amp;gt;&lt;br /&gt;        An EMail has been sent to &amp;lt;%= @user.email %&amp;gt; with instructions to activate &lt;br /&gt;        your account.&lt;br /&gt;        &amp;lt;li&amp;gt;&lt;br /&gt;          If your email is not valid, you must &amp;lt;%= link_to "signup", signup_path %&amp;gt; &lt;br /&gt;          again and provide a valid email address.&lt;br /&gt;        &amp;lt;/li&amp;gt;&lt;br /&gt;        &amp;lt;li&amp;gt;&lt;br /&gt;          If you don't recieve an email, check your bulk or trash folder, as your spam &lt;br /&gt;          filter may have inadvertantly caught the registration email.&lt;br /&gt;        &amp;lt;/li&amp;gt;&lt;br /&gt;      &amp;lt;/p&amp;gt;&lt;br /&gt;    &amp;lt;/fieldset&amp;gt;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;Also, create the files app/views/users/change_password.html.erb, app/views/users/forgot_password.html.erb, app/views/users/reset_password.html.erb:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  #change_password.html.erb&lt;br /&gt;    &lt;br /&gt;         &amp;lt;% form_for :action =&amp;gt; 'change_password' do |f| %&gt;&lt;br /&gt;      &amp;lt;fieldset&amp;gt;&lt;br /&gt;          &amp;lt;dl&amp;gt;           &lt;br /&gt;              &amp;lt;dt&amp;gt;&amp;lt;label for="old_password" class="block"&amp;gt;Old Password&amp;lt;/label&amp;gt;&amp;lt;/dt&amp;gt;&lt;br /&gt;              &amp;lt;dd&amp;gt;&amp;lt;%= password_field_tag 'old_password', @old_password, :size =&amp;gt; 45, :class =&gt; 'text' %&gt;&amp;lt;/dd&amp;gt;&lt;br /&gt;&lt;br /&gt;              &amp;lt;dt&amp;gt;&amp;lt;label for="password" class="block"&amp;gt;New Password&amp;lt;/label&amp;gt;&amp;lt;/dt&amp;gt;&lt;br /&gt;              &amp;lt;dd&amp;gt;&amp;lt;%= password_field_tag 'password', {}, :size =&amp;gt; 45, :class =&gt; 'text' %&gt;&lt;br /&gt;              &amp;lt;div&amp;gt;&amp;lt;small&amp;gt;Between 4 and 40 characters&amp;lt;/small&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/dd&amp;gt;&lt;br /&gt;&lt;br /&gt;              &amp;lt;dt&amp;gt;&amp;lt;label for="password_confirmation"  class="block"&amp;gt;Confirm new password&amp;lt;/label&amp;gt;&amp;lt;/dt&amp;gt;&lt;br /&gt;              &amp;lt;dd&amp;gt;&amp;lt;%= password_field_tag 'password_confirmation', {}, :size =&amp;gt; 45, :class =&gt; 'text' %&gt;&amp;lt;/dd&amp;gt;&lt;br /&gt;&lt;br /&gt;          &amp;lt;/dl&amp;gt;&lt;br /&gt;          &amp;lt;%= submit_tag 'Change password' %&amp;gt;&lt;br /&gt;      &amp;lt;/fieldset&amp;gt;&lt;br /&gt;  &amp;lt;%end%&amp;gt;&lt;br /&gt;&lt;br /&gt;  #forgot_password.html.erb&lt;br /&gt;      &lt;br /&gt;    &amp;lt;% form_for :user, :url =&amp;gt; {:action =&gt; 'forgot_password'} do |form| %&gt;&lt;br /&gt;        &amp;lt;fieldset&amp;gt;&lt;br /&gt;     &amp;lt;legend&amp;gt;Password Reset Request&amp;lt;/legend&amp;gt;&lt;br /&gt;         &amp;lt;p&amp;gt;Enter your email address that we have on our file and click send. We will send you a&lt;br /&gt;         password reset link email to your email address.&amp;lt;/p&amp;gt;&lt;br /&gt;            &amp;lt;p&amp;gt;&lt;br /&gt;                &amp;lt;label for="user_email" &amp;gt;Email Address:&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;                &amp;lt;%= form.text_field :email, :size =&amp;gt; 35, :class =&gt; 'text' %&gt;&lt;br /&gt;            &amp;lt;/p&amp;gt;&lt;br /&gt;            &amp;lt;%= submit_tag 'Send' %&amp;gt;&lt;br /&gt;        &amp;lt;/fieldset&amp;gt;&lt;br /&gt;    &amp;lt;% end %&amp;gt;&lt;br /&gt;&lt;br /&gt;  #reset_password.html.erb&lt;br /&gt;  &lt;br /&gt;    &amp;lt;% form_for :user, :url =&amp;gt; {:action =&gt; "reset_password"} do |form| %&gt;&lt;br /&gt;        &amp;lt;fieldset&amp;gt;&lt;br /&gt;     &amp;lt;legend&amp;gt;Reset Password&amp;lt;/legend&amp;gt;&lt;br /&gt;     &lt;br /&gt;            &amp;lt;p&amp;gt;&lt;br /&gt;                &amp;lt;label for="user_password" &amp;gt;Password&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;                &amp;lt;%= form.password_field :password, :size =&amp;gt; 45, :class =&gt; 'text' %&gt;&lt;br /&gt;      &amp;lt;/p&amp;gt;&lt;br /&gt;      &amp;lt;p&amp;gt;&lt;br /&gt;                &amp;lt;label for="user_password_confirmation" &amp;gt;Confirm Password&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;                &amp;lt;%= form.password_field :password_confirmation, :size =&amp;gt; 45, :class =&gt; 'text' %&gt;&lt;br /&gt;            &amp;lt;/p&amp;gt;&lt;br /&gt;            &amp;lt;%= submit_tag "Reset your password" %&amp;gt;&lt;br /&gt;        &amp;lt;/fieldset&amp;gt;&lt;br /&gt;    &amp;lt;% end %&amp;gt;&lt;br /&gt;  &amp;lt;/pre&amp;gt;&lt;br /&gt;  &amp;lt;p&amp;gt;Standard stuff there.&amp;lt;/p&amp;gt;&lt;br /&gt;  &amp;lt;p&amp;gt;Now, open up app/helpers/application_helper.rb and add this code:&amp;lt;/p&amp;gt;&lt;br /&gt;  &amp;lt;pre&amp;gt;&lt;br /&gt;    def user_logged_in?&lt;br /&gt;      session[:user_id]&lt;br /&gt;    end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;We can use this in our views to see if the user is logged in.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Create app/views/layouts/application.html.erb:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;     &amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"&lt;br /&gt;        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-US"&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;      &amp;lt;title&amp;gt;&amp;lt;%= @page_title || 'Rails 2.0 Forum' %&amp;gt;&amp;lt;/title&amp;gt;&lt;br /&gt;      &amp;lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/&amp;gt;&lt;br /&gt;      &amp;lt;%= stylesheet_link_tag 'style' %&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;%= javascript_include_tag :defaults %&amp;gt;&lt;br /&gt;    &amp;lt;/head&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- ##### Header ##### --&amp;gt;    &lt;br /&gt;     &amp;lt;div id="header"&amp;gt;&lt;br /&gt;      &amp;lt;div class="superHeader"&amp;gt;&lt;br /&gt;         &amp;lt;% if user_logged_in? %&amp;gt;&lt;br /&gt;              &amp;lt;span&amp;gt;You are logged in as: &amp;lt;/span&amp;gt;&lt;br /&gt;         &amp;lt;%= current_user.login %&amp;gt;&lt;br /&gt;         &amp;lt;% else %&amp;gt;&lt;br /&gt;         &amp;lt;span&amp;gt;Welcome Guest&amp;lt;/span&amp;gt;&lt;br /&gt;         &amp;lt;% end %&amp;gt;&lt;br /&gt;       &amp;lt;/div&amp;gt;&lt;br /&gt;       &lt;br /&gt;          &amp;lt;div class="midHeader"&amp;gt;&lt;br /&gt;            &amp;lt;h1 class="headerTitle" lang="la"&amp;gt;Rails 2.0 Forum&amp;lt;/h1&amp;gt;&lt;br /&gt;          &amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;       &amp;lt;div class="subHeader"&amp;gt;&lt;br /&gt;      &amp;lt;span class="doNotDisplay"&amp;gt;Navigation:&amp;lt;/span&amp;gt;&lt;br /&gt;      &amp;lt;% if user_logged_in? %&amp;gt; &lt;br /&gt;         &amp;lt;%= link_to 'Logout', logout_url  %&amp;gt; &lt;br /&gt;      &amp;lt;% else %&amp;gt;&lt;br /&gt;       &amp;lt;%= link_to "Signup", signup_url  %&amp;gt;&lt;br /&gt;       | &amp;lt;%= link_to 'Login', login_url  %&amp;gt;&lt;br /&gt;       &amp;lt;% end %&amp;gt; &lt;br /&gt;      | &amp;lt;%= link_to 'Contact Us', 'contact'  %&amp;gt;&lt;br /&gt;       &amp;lt;/div&amp;gt;&lt;br /&gt;     &lt;br /&gt;        &amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!-- ##### Main Copy ##### --&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;div id="main-copy"&amp;gt;&lt;br /&gt;         &amp;lt;% flash.each do |key,value| %&amp;gt;&lt;br /&gt;         &amp;lt;div id="flash" class="flash_&amp;lt;%= key %&amp;gt;" &amp;gt;&lt;br /&gt;          &amp;lt;span class="message"&amp;gt;&amp;lt;%= value %&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;         &amp;lt;/div&amp;gt;&lt;br /&gt;         &amp;lt;% end -%&amp;gt;&lt;br /&gt;&lt;br /&gt;         &amp;lt;%= yield :layout %&amp;gt;&lt;br /&gt;        &amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;/body&amp;gt;&lt;br /&gt;    &amp;lt;/html&amp;gt;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;And then delete forums.html.erb, replies.html.erb, and topics.html.erb so that only the application.html.erb will show.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;Lets go ahead and get some different styling in this.  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/style.css"&gt;Download this&lt;/a&gt; stylesheet and toss it in /public/stylesheets.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Alright! Now we should be able to fire up the server and have a look at what we've got.&lt;/p&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen9.jpg"&gt;&lt;br /&gt;    &lt;img class="wide" src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen9.jpg" width="600"/&gt;&lt;br /&gt;  &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen10.jpg"&gt;&lt;br /&gt;    &lt;img class="wide" src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen10.jpg" width="600"/&gt;&lt;br /&gt;  &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen11.jpg"&gt;&lt;br /&gt;    &lt;img class="wide" src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen11.jpg" width="600"/&gt;&lt;br /&gt;  &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;Next, open up app/views/sessions/new.html.erb.  Uncomment the 'Remember me' section, and then next to the submit button, add:&lt;/p&gt; &lt;br /&gt;  &lt;pre&gt;&lt;%= link_to 'Forgot Password?', forgot_password_url %&gt;&lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;Create /app/views/users/change_password.html.erb:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    &amp;lt;% form_for :action =&amp;gt; 'change_password' do |f| %&gt;&lt;br /&gt;        &amp;lt;fieldset&amp;gt;&lt;br /&gt;            &amp;lt;dl&amp;gt;           &lt;br /&gt;                &amp;lt;dt&amp;gt;&amp;lt;label for="old_password" class="block"&amp;gt;Old Password&amp;lt;/label&amp;gt;&amp;lt;/dt&amp;gt;&lt;br /&gt;                &amp;lt;dd&amp;gt;&amp;lt;%= password_field_tag 'old_password', @old_password, :size =&amp;gt; 45, &lt;br /&gt;                            :class =&gt; 'text' %&gt;&amp;lt;/dd&amp;gt;&lt;br /&gt;&lt;br /&gt;                &amp;lt;dt&amp;gt;&amp;lt;label for="password" class="block"&amp;gt;New Password&amp;lt;/label&amp;gt;&amp;lt;/dt&amp;gt;&lt;br /&gt;                &amp;lt;dd&amp;gt;&amp;lt;%= password_field_tag 'password', {}, :size =&amp;gt; 45, :class =&gt; 'text' %&gt;&lt;br /&gt;                &amp;lt;div&amp;gt;&amp;lt;small&amp;gt;Between 4 and 40 characters&amp;lt;/small&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/dd&amp;gt;&lt;br /&gt;&lt;br /&gt;                &amp;lt;dt&amp;gt;&amp;lt;label for="password_confirmation"  class="block"&amp;gt;&lt;br /&gt;                        Confirm new password&amp;lt;/label&amp;gt;&amp;lt;/dt&amp;gt;&lt;br /&gt;                &amp;lt;dd&amp;gt;&amp;lt;%= password_field_tag 'password_confirmation', {}, :size =&amp;gt; 45, &lt;br /&gt;                                  :class =&gt; 'text' %&gt;&amp;lt;/dd&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;/dl&amp;gt;&lt;br /&gt;            &amp;lt;%= submit_tag 'Change password' %&amp;gt;&lt;br /&gt;        &amp;lt;/fieldset&amp;gt;&lt;br /&gt;    &amp;lt;%end%&amp;gt;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;Create /app/views/users/forgot_password.html.erb&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    &amp;lt;% form_for :user, :url =&amp;gt; {:action =&gt; 'forgot_password'} do |form| %&gt;&lt;br /&gt;        &amp;lt;fieldset&amp;gt;&lt;br /&gt;     &amp;lt;legend&amp;gt;Password Reset Request&amp;lt;/legend&amp;gt;&lt;br /&gt;         &amp;lt;p&amp;gt;Enter your email address that we have on our file and click send. We will &lt;br /&gt;         send you a password reset link email to your email address.&amp;lt;/p&amp;gt;&lt;br /&gt;            &amp;lt;p&amp;gt;&lt;br /&gt;                &amp;lt;label for="user_email" &amp;gt;Email Address:&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;                &amp;lt;%= form.text_field :email, :size =&amp;gt; 35, :class =&gt; 'text' %&gt;&lt;br /&gt;            &amp;lt;/p&amp;gt;&lt;br /&gt;            &amp;lt;%= submit_tag 'Send' %&amp;gt;&lt;br /&gt;        &amp;lt;/fieldset&amp;gt;&lt;br /&gt;    &amp;lt;% end %&amp;gt; &lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;And create /app/views/users/reset_password.html.erb&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    &amp;lt;% form_for :user, :url =&amp;gt; {:action =&gt; "reset_password"} do |form| %&gt;&lt;br /&gt;        &amp;lt;fieldset&amp;gt;&lt;br /&gt;     &amp;lt;legend&amp;gt;Reset Password&amp;lt;/legend&amp;gt;&lt;br /&gt;     &lt;br /&gt;            &amp;lt;p&amp;gt;&lt;br /&gt;                &amp;lt;label for="user_password" &amp;gt;Password&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;                &amp;lt;%= form.password_field :password, :size =&amp;gt; 45, :class =&gt; 'text' %&gt;&lt;br /&gt;      &amp;lt;/p&amp;gt;&lt;br /&gt;      &amp;lt;p&amp;gt;&lt;br /&gt;                &amp;lt;label for="user_password_confirmation" &amp;gt;Confirm Password&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;                &amp;lt;%= form.password_field :password_confirmation, :size =&amp;gt; 45, :class =&gt; 'text' %&gt;&lt;br /&gt;            &amp;lt;/p&amp;gt;&lt;br /&gt;            &amp;lt;%= submit_tag "Reset your password" %&amp;gt;&lt;br /&gt;        &amp;lt;/fieldset&amp;gt;&lt;br /&gt;    &amp;lt;% end %&amp;gt; &lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;We are moving kind of fast here, but most of this stuff should make sense to you, you just need to see it in action.  If you have any questions over how anything works, leave a comment and I will get back to you.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Now, in app/controllers/users_controller.rb, lets add in the actions for forgot_password, reset_password, and change_password:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    def change_password&lt;br /&gt;      return unless request.post?&lt;br /&gt;      if User.authenticate(current_user.login, params[:old_password])&lt;br /&gt;        if ((params[:password] == params[:password_confirmation]) &amp;&amp; &lt;br /&gt;                              !params[:password_confirmation].blank?)&lt;br /&gt;          current_user.password_confirmation = params[:password_confirmation]&lt;br /&gt;          current_user.password = params[:password]&lt;br /&gt;&lt;br /&gt;          if current_user.save&lt;br /&gt;            flash[:notice] = "Password successfully updated" &lt;br /&gt;            redirect_to profile_url(current_user.login)&lt;br /&gt;          else&lt;br /&gt;            flash[:alert] = "Password not changed" &lt;br /&gt;          end&lt;br /&gt;&lt;br /&gt;        else&lt;br /&gt;          flash[:alert] = "New Password mismatch" &lt;br /&gt;          @old_password = params[:old_password]&lt;br /&gt;        end&lt;br /&gt;      else&lt;br /&gt;        flash[:alert] = "Old password incorrect" &lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    #gain email address&lt;br /&gt;    def forgot_password&lt;br /&gt;      return unless request.post?&lt;br /&gt;      if @user = User.find_by_email(params[:user][:email])&lt;br /&gt;        @user.forgot_password&lt;br /&gt;        @user.save&lt;br /&gt;        redirect_back_or_default('/')&lt;br /&gt;        flash[:notice] = "A password reset link has been sent to your email address" &lt;br /&gt;      else&lt;br /&gt;        flash[:alert] = "Could not find a user with that email address" &lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    #reset password&lt;br /&gt;    def reset_password&lt;br /&gt;      @user = User.find_by_password_reset_code(params[:id])&lt;br /&gt;      return if @user unless params[:user]&lt;br /&gt;&lt;br /&gt;      if ((params[:user][:password] &amp;&amp; params[:user][:password_confirmation]) &amp;&amp; &lt;br /&gt;                              !params[:user][:password_confirmation].blank?)&lt;br /&gt;        self.current_user = @user #for the next two lines to work&lt;br /&gt;        current_user.password_confirmation = params[:user][:password_confirmation]&lt;br /&gt;        current_user.password = params[:user][:password]&lt;br /&gt;        @user.reset_password&lt;br /&gt;        flash[:notice] = current_user.save ? "Password reset success." : "Password reset failed." &lt;br /&gt;        redirect_back_or_default('/')&lt;br /&gt;      else&lt;br /&gt;        flash[:alert] = "Password mismatch" &lt;br /&gt;      end  &lt;br /&gt;    end&lt;br /&gt;  &lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;In config/environments/development.rb you need to add SITE="http://localhost:3000" at the bottom, we will get to this in just a sec.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Now we will take a look at the user_mailer views.  They are used to format emails sent out to users.  In app/views/user_mailer/activation.html.erb, remove the part where it says "You may now start adding your plugins:".  Now lets create app/views/user_mailer/forgot_password.html.erb, and app/views/user_mailer/reset_password.html.erb:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    #forgot_password.html.erb&lt;br /&gt;          &lt;br /&gt;      Dear &lt;%= @user.login %&gt;,&lt;br /&gt;&lt;br /&gt;      We have had a request to reset your password, please visit&lt;br /&gt;      &lt;%= @url %&gt;    &lt;br /&gt;      &lt;br /&gt;    #reset_password.html.erb&lt;br /&gt;          &lt;br /&gt;      Your have reset the password for your account successfully.&lt;br /&gt;&lt;br /&gt;        Username: &lt;%= @user.login %&gt;&lt;br /&gt;        Password: &lt;%= @user.password %&gt;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;Now lets edit app/models/user.rb.  Near the bottom, somewhere after the protected keyword, add the follow function:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    def make_password_reset_code&lt;br /&gt;      self.password_reset_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )&lt;br /&gt;    end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;And then above protected, add these functions:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    def forgot_password&lt;br /&gt;      @forgotten_password = true&lt;br /&gt;      self.make_password_reset_code&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def reset_password&lt;br /&gt;      # First update the password_reset_code before setting the &lt;br /&gt;      # reset_password flag to avoid duplicate email notifications.&lt;br /&gt;      update_attributes(:password_reset_code =&gt; nil)&lt;br /&gt;      @reset_password = true&lt;br /&gt;    end  &lt;br /&gt;&lt;br /&gt;    #used in user_observer&lt;br /&gt;    def recently_forgot_password?&lt;br /&gt;      @forgotten_password&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    def recently_reset_password?&lt;br /&gt;      @reset_password&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    def recently_activated?&lt;br /&gt;      @recent_active&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;p&gt;And now we need to set up the user_mailer model to use all of this. Change app/models/user_mailer.rb to look like this:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    class UserMailer &lt; ActionMailer::Base&lt;br /&gt;      def signup_notification(user)&lt;br /&gt;        setup_email(user)&lt;br /&gt;        @subject    += 'Please activate your new account'&lt;br /&gt;      &lt;br /&gt;        @body[:url]  = "#{SITE}/activate/#{user.activation_code}"&lt;br /&gt;      &lt;br /&gt;      end&lt;br /&gt;      &lt;br /&gt;      def activation(user)&lt;br /&gt;        setup_email(user)&lt;br /&gt;        @subject    += 'Your account has been activated!'&lt;br /&gt;        @body[:url]  = "#{SITE}/"&lt;br /&gt;      end&lt;br /&gt;      &lt;br /&gt;      def forgot_password(user)&lt;br /&gt;        setup_email(user)&lt;br /&gt;        @subject    += 'You have requested to change your password'&lt;br /&gt;        @body[:url]  = "#{SITE}/reset_password/#{user.password_reset_code}" &lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      def reset_password(user)&lt;br /&gt;        setup_email(user)&lt;br /&gt;        @subject    += 'Your password has been reset.'&lt;br /&gt;      end&lt;br /&gt;      &lt;br /&gt;      protected&lt;br /&gt;      &lt;br /&gt;      def setup_email(user)&lt;br /&gt;       recipients "#{user.email}"&lt;br /&gt;       from       %("Rails Forum Admin" &lt;admin@myrailsforum.com&gt;) # Sets the User FROM Name and Email&lt;br /&gt;       subject    "[Rails Forum] New account information "&lt;br /&gt;       body       :user =&gt; user&lt;br /&gt;        sent_on    Time.now&lt;br /&gt;      end&lt;br /&gt;    end  &lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;Note where we used the SITE constant that we set in development.rb earlier.  Lets stop the server and then restart it since we changed the development.rb.  Now, we should be able to go back and sign up.&lt;/p&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen12.jpg"&gt;&lt;br /&gt;    &lt;img class="wide" src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen12.jpg"/&gt;&lt;br /&gt;  &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen13.jpg"&gt;&lt;br /&gt;    &lt;img class="wide" src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen13.jpg"/&gt;&lt;br /&gt;  &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;If you check the console running your server, you will see SQL queries adding the new user to the database, and the email being sent(it won't actually send an email since we are in development)&lt;/p&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen14.jpg"&gt;&lt;br /&gt;    &lt;img class="wide" src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen14.jpg"/&gt;&lt;br /&gt;  &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;Go to think link from the console(localhost:3000/activate/whatever) and you will get a message saying 'Signup complete' and you will be logged in.  It will also send an email saying that your account has been activated.  You can test everything by logging out and logging back in again.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Alright, we are almost done!  Next, open up app/models/user_observer.rb and change the after_save function to this:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    def after_save(user)&lt;br /&gt;      UserMailer.deliver_activation(user) if user.recently_activated?&lt;br /&gt;      UserMailer.deliver_forgot_password(user) if user.recently_forgot_password?&lt;br /&gt;      UserMailer.deliver_reset_password(user) if user.recently_reset_password?&lt;br /&gt;    end  &lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;Just more setting up for the mailer.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;So, now we have a Signup, a few ways for taking care of forgotten passwords, and email authentication.  But how do we block the adding posts and replies to only people logged in? How do we restrict creating forums and deleting posts to only an admin?  Open up the file vendor/plugins/restful_authentication/generators/authenticated/templates/authenticated_system.rb and read through some of the comments about the functions:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;      # Returns true or false if the &lt;%= file_name %&gt; is logged in.&lt;br /&gt;      # Preloads @current_&lt;%= file_name %&gt; with the &lt;%= file_name %&gt; model if they're logged in.&lt;br /&gt;      def logged_in?&lt;br /&gt;        current_&lt;%= file_name %&gt; != :false&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      # Accesses the current &lt;%= file_name %&gt; from the session.  Set it to :false if login fails&lt;br /&gt;      # so that future calls do not hit the database.&lt;br /&gt;      def current_&lt;%= file_name %&gt;&lt;br /&gt;        @current_&lt;%= file_name %&gt; ||= (login_from_session || login_from_basic_auth || login_from_cookie || :false)&lt;br /&gt;      end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt; logged_in? checks the value of current_user and returns true if it does not equal :false.  current_user tries to login from a session, from basic auth, and from a cookie.  If it is unable to log them in, it will return :false and cause the value of logged_in to be false.&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;&lt;br /&gt;    # Check if the &lt;%= file_name %&gt; is authorized&lt;br /&gt;    #&lt;br /&gt;    # Override this method in your controllers if you want to restrict access&lt;br /&gt;    # to only a few actions or if you want to check if the &lt;%= file_name %&gt;&lt;br /&gt;    # has the correct rights.&lt;br /&gt;    #&lt;br /&gt;    # Example:&lt;br /&gt;    #&lt;br /&gt;    #  # only allow nonbobs&lt;br /&gt;    #  def authorized?&lt;br /&gt;    #    current_&lt;%= file_name %&gt;.login != "bob"&lt;br /&gt;    #  end&lt;br /&gt;    def authorized?&lt;br /&gt;      logged_in?&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    # Filter method to enforce a login requirement.&lt;br /&gt;    #&lt;br /&gt;    # To require logins for all actions, use this in your controllers:&lt;br /&gt;    #&lt;br /&gt;    #   before_filter :login_required&lt;br /&gt;    #&lt;br /&gt;    # To require logins for specific actions, use this in your controllers:&lt;br /&gt;    #&lt;br /&gt;    #   before_filter :login_required, :only =&gt; [ :edit, :update ]&lt;br /&gt;    #&lt;br /&gt;    # To skip this in a subclassed controller:&lt;br /&gt;    #&lt;br /&gt;    #   skip_before_filter :login_required&lt;br /&gt;    #&lt;br /&gt;    def login_required&lt;br /&gt;      authorized? || access_denied&lt;br /&gt;    end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;We can use before_filter :login_required to stop people from going to /topic/1/posts/2/edit and being able to edit the post.  logged_in? can be used in forum and topic's show views, to stop the form for new topics and replies from being shown.  This can all be setup however you want, there are plenty of possibilities.  What I am going to do is show you how to display different things based on who is logged in, and how to limit certain actions in your controllers.  That should give you enough to figure out what you want to do for your specific application.  First, open up app/views/forums/show.html.erb:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;         #find these 3 lines&lt;br /&gt;    &lt;br /&gt;  &amp;lt;h2&amp;gt;New Post&amp;lt;/h2&amp;gt;&lt;br /&gt;  &amp;lt;%= render :partial =&amp;gt; @topic = Topic.new, :locals =&gt; { :button_name =&gt; 'Create' } %&gt;&lt;br /&gt;  &amp;lt;%= link_to 'New Topic', new_forum_topic_path(@forum) %&amp;gt; |&lt;br /&gt;  &lt;br /&gt;    #and put this around them&lt;br /&gt;    &lt;br /&gt;    &amp;lt;% if logged_in? %&amp;gt;&lt;br /&gt;      &amp;lt;h2&amp;gt;New Post&amp;lt;/h2&amp;gt;&lt;br /&gt;      &amp;lt;%= render :partial =&amp;gt; @topic = Topic.new, :locals =&gt; { :button_name =&gt; 'Create' } %&gt;&lt;br /&gt;      &amp;lt;%= link_to 'New Topic', new_forum_topic_path(@forum) %&amp;gt; |&lt;br /&gt;    &amp;lt;%end&amp;gt;&lt;br /&gt;    &lt;br /&gt;    #and then change this line&lt;br /&gt;    &amp;lt;%= link_to 'Edit', edit_forum_path(@forum) %&amp;gt; |&lt;br /&gt;    &lt;br /&gt;    #to this&lt;br /&gt;    &amp;lt;% if is_admin? %&amp;gt;&lt;br /&gt;      &amp;lt;%= link_to 'Edit', edit_forum_path(@forum) %&amp;gt; |&lt;br /&gt;    &amp;lt;% end %&amp;gt;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;And now, go to app/controllers/application.rb.  In this file we can write functions that will be available to all controllers.  Add this to it:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    helper_method :is_admin?&lt;br /&gt;    def is_admin? &lt;br /&gt;        if logged_in? &amp;&amp; current_user.login == "admin"&lt;br /&gt;          true&lt;br /&gt;        else&lt;br /&gt;          false&lt;br /&gt;        end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    def admin_required&lt;br /&gt;      is_admin? || admin_denied&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    def admin_denied&lt;br /&gt;      respond_to do |format|&lt;br /&gt;        format.html do&lt;br /&gt;          store_location&lt;br /&gt;          flash[:notice] = 'You must be an admin to do that.'&lt;br /&gt;          redirect_to forums_path&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;The first line, helper_method :is_admin? will let this function be used in the view.  current_user.login is the username for the person logged in.  You can change this method however you want to determine whether or not a user is an admin.  admin_required and admin_denied will be used in our controllers to restrict access to actions - lets go to our app/controllers/forums_controller.rb and put that in:&lt;/p&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    #at the very top, right after class ForumsController &lt; ApplicationController, add this line:&lt;br /&gt;&lt;br /&gt;    before_filter :admin_required, :only =&gt; [ :edit, :update, :create, :new, :destroy ]&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;  &lt;p&gt;Now, when you try to access edit, update, create, new, or destroy actions in your controller, if your username is not 'admin', it will go to the show forums page and have a flash saying 'You must be an admin to do that'.&lt;/p&gt;&lt;br /&gt;  &lt;p&gt;Well, I guess that is it for now.  We've added the ability to create users, reset passwords, verify email, and restrict actions to admins.  This isn't a completely finished web app.  We didn't look into any kind of input validation and we didn't go over all the things we would need to limit to users logged in(create post and create reply), and we didn't limit a lot of things to admins that we should have(such as editing and destroying posts/replies).  Hopefully, you've learned enough from this to be able to figure it out yourself, but if you have any trouble feel free to leave a comment.  Also, let me know if there are any typos, mistakes, or questions about the tutorial, as well if you have any suggestions.  Thanks for reading!&lt;br /&gt;-Ralph&lt;/p&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;digg_url = 'http://railsonedge.blogspot.com/2008/03/rails-forum-restful-authenticationpart.html';&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-1604846062643818850?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/1604846062643818850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=1604846062643818850' title='44 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/1604846062643818850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/1604846062643818850'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/03/rails-forum-restful-authenticationpart.html' title='Rails Forum - Restful Authentication(Part 3 of 3)'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>44</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-5424497371976458051</id><published>2008-02-25T15:43:00.004-06:00</published><updated>2008-03-05T16:04:15.917-06:00</updated><title type='text'>Rails Forum Tutorial for Beginners(Part 2 of 3)</title><content type='html'>This is part 2 of my Rails 2.0 Forum tutorial for beginners.  You can find part 1 &lt;a href="http://railsonedge.blogspot.com/2008/02/rails-forum-tutorial-for-beginners-part.html" title="Rails Forum Tutorial Part 1"&gt;here&lt;/a&gt;.  Last time, we created our Forum, Topic, and Reply objects.  We nested topics inside of forums and adjusted the views/controllers to allow for the nesting.  This time, we will take care of replies being nested in a topic.&lt;br /&gt;&lt;br /&gt;The nesting in /config/routes.rb has already been taken care of in the first tutorial:&lt;br /&gt;&lt;pre&gt;  map.resources :topics, :has_many =&gt; :replies&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first thing we are going to do is to create partials for /app/views/replies/new.html.erb and /app/views/replies/edit.html.erb.  Create the file /app/views/replies/_reply.html.erb&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#/app/views/replies/_reply.html.erb&lt;br /&gt;&lt;br /&gt;&amp;lt;% form_for([@topic, @reply]) do |f| %&amp;gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&lt;br /&gt;    &amp;lt;b&amp;gt;Subject&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;    &amp;lt;%= f.text_field :subject %&amp;gt;&lt;br /&gt;  &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&lt;br /&gt;    &amp;lt;b&amp;gt;Body&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;    &amp;lt;%= f.text_area :body %&amp;gt;&lt;br /&gt;  &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&lt;br /&gt;    &amp;lt;%= f.submit button_name %&amp;gt;&lt;br /&gt;  &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;% end %&amp;gt;&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;And now change edit and new to:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#/app/views/replies/edit.html.erb&lt;br /&gt;&lt;br /&gt;&amp;lt;h1&amp;gt;Editing reply&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= error_messages_for :reply %&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= render :partial =&amp;gt; @reply, :locals =&gt; { :button_name =&gt; "Submit" } %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= link_to 'Show', [@topic, @reply] %&amp;gt; |&lt;br /&gt;&amp;lt;%= link_to 'Back', replies_path %&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#/app/views/replies/new.html.erb&lt;br /&gt;&lt;br /&gt;&amp;lt;h1&amp;gt;New reply&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= error_messages_for :reply %&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= render :partial =&amp;gt; @reply, :locals =&gt; { :button_name =&gt; "Reply" } %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= link_to 'Back', replies_path %&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Same stuff we did last time...&lt;br /&gt;Now lets go to /app/controllers/replies_controller.rb&lt;br /&gt;Add this at the top, to make sure a topic gets loaded everytime the replies controller is used:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  before_filter :load_topic&lt;br /&gt;  &lt;br /&gt;  def load_topic&lt;br /&gt;    @topic = Topic.find(params[:topic_id])&lt;br /&gt;  end  &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;inside the new function change the line:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    @reply = Reply.new&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;to this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    @reply = @topic.replies.build&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Change the edit function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#old edit function&lt;br /&gt;&lt;br /&gt;  def edit&lt;br /&gt;    @reply = Reply.find(params[:id])&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#new edit function&lt;br /&gt;&lt;br /&gt;  def edit&lt;br /&gt;    @reply = @topic.replies.find(params[:id])&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Change the create function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#old create&lt;br /&gt;&lt;br /&gt;  def create&lt;br /&gt;    @reply = Reply.new(params[:reply])&lt;br /&gt;&lt;br /&gt;    respond_to do |format|&lt;br /&gt;      if @reply.save&lt;br /&gt;        flash[:notice] = 'Reply was successfully created.'&lt;br /&gt;        format.html { redirect_to(@reply) }&lt;br /&gt;        format.xml  { render :xml =&gt; @reply, :status =&gt; :created, :location =&gt; @reply }&lt;br /&gt;      else&lt;br /&gt;        format.html { render :action =&gt; "new" }&lt;br /&gt;        format.xml  { render :xml =&gt; @reply.errors, :status =&gt; :unprocessable_entity }&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#new create&lt;br /&gt;&lt;br /&gt;  def create&lt;br /&gt;    @reply = @topic.replies.build(params[:reply])&lt;br /&gt;&lt;br /&gt;    respond_to do |format|&lt;br /&gt;      if @reply.save&lt;br /&gt;        flash[:notice] = 'Reply was successfully created.'&lt;br /&gt;        format.html { redirect_to([Forum.find(@topic.forum_id), @topic]) }&lt;br /&gt;        format.xml  { render :xml =&gt; @reply, :status =&gt; :created, :location =&gt; @reply }&lt;br /&gt;      else&lt;br /&gt;        format.html { render :action =&gt; "new" }&lt;br /&gt;        format.xml  { render :xml =&gt; @reply.errors, :status =&gt; :unprocessable_entity }&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice the change in redirect_to...after a reply to a topic is submitted, I want to send the user back to the forum the topic was in, to get the forum, I had to use the find function and pass it the forum_id of the topic and the topic.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the update and destroy functions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#old update and destroy&lt;br /&gt;&lt;br /&gt;  def update&lt;br /&gt;    @reply = Reply.find(params[:id])&lt;br /&gt;&lt;br /&gt;    respond_to do |format|&lt;br /&gt;      if @reply.update_attributes(params[:reply])&lt;br /&gt;        flash[:notice] = 'Reply was successfully updated.'&lt;br /&gt;        format.html { redirect_to(@reply) }&lt;br /&gt;        format.xml  { head :ok }&lt;br /&gt;      else&lt;br /&gt;        format.html { render :action =&gt; "edit" }&lt;br /&gt;        format.xml  { render :xml =&gt; @reply.errors, :status =&gt; :unprocessable_entity }&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def destroy&lt;br /&gt;    @reply = Reply.find(params[:id])&lt;br /&gt;    @reply.destroy&lt;br /&gt;&lt;br /&gt;    respond_to do |format|&lt;br /&gt;      format.html { redirect_to(replies_url) }&lt;br /&gt;      format.xml  { head :ok }&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#new update and destroy&lt;br /&gt;&lt;br /&gt;  def update&lt;br /&gt;    @reply = @topic.replies.find(params[:id])&lt;br /&gt;&lt;br /&gt;    respond_to do |format|&lt;br /&gt;      if @reply.update_attributes(params[:reply])&lt;br /&gt;        flash[:notice] = 'Reply was successfully updated.'&lt;br /&gt;        format.html { redirect_to(@topic) }&lt;br /&gt;        format.xml  { head :ok }&lt;br /&gt;      else&lt;br /&gt;        format.html { render :action =&gt; "edit" }&lt;br /&gt;        format.xml  { render :xml =&gt; @reply.errors, :status =&gt; :unprocessable_entity }&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  def destroy&lt;br /&gt;    @reply = @topic.replies.find(params[:id])&lt;br /&gt;    @reply.destroy&lt;br /&gt;&lt;br /&gt;    respond_to do |format|&lt;br /&gt;      format.html { redirect_to(@topic) }&lt;br /&gt;      format.xml  { head :ok }&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now that we have all of that done...lets head over to /app/views/topics/show.html.erb so we can display our replies and the form for a new reply.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In addition to showing replies and a form for a new one, I changed the formatting a little, so here are the contents on show.html.erb&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  &amp;lt;h3&amp;gt;Forum: - &amp;lt;%=h @forum.name %&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  &amp;lt;b&amp;gt;&amp;lt;%=h @topic.subject %&amp;gt;&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  &amp;lt;%=h @topic.body %&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;% unless @topic.replies.empty? %&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;% @topic.replies.each do |reply| %&amp;gt;&lt;br /&gt;      &amp;lt;p&amp;gt;&lt;br /&gt;        &amp;lt;b&amp;gt;&amp;lt;%= reply.subject %&amp;gt;&amp;lt;/b&amp;gt;    &lt;br /&gt;      &amp;lt;/p&amp;gt;&lt;br /&gt;      &amp;lt;p&amp;gt;&lt;br /&gt;        &amp;lt;%=h reply.body %&amp;gt;&lt;br /&gt;      &amp;lt;/p&amp;gt;&lt;br /&gt;    &lt;br /&gt;  &amp;lt;% end %&amp;gt;&lt;br /&gt;&amp;lt;% end %&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;h2&amp;gt;Reply&amp;lt;/h2&amp;gt;&lt;br /&gt;&amp;lt;%= render :partial =&amp;gt; @reply = Reply.new, :locals =&gt; { :button_name =&gt; 'Reply' } %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;%= link_to 'Edit', edit_forum_topic_path(@forum, @topic) %&amp;gt; |&lt;br /&gt;&amp;lt;%= link_to 'Back', topics_path %&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since this is the same stuff we were doing in the first tutorial, I won't bother explaining any of it...you should be able to tell what is going on.  Feel free to leave a comment if you do have any questions. &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Now, fire up the web server and head to localhost:3000/forums/1/topics/1 (assuming you have a topic already created).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src = "http://users.csc.tntech.edu/~rledge21/blog/screens/screen7.jpg" /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And create a couple of replies:&lt;br /&gt;&lt;br /&gt;&lt;img src = "http://users.csc.tntech.edu/~rledge21/blog/screens/screen8.jpg" /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And thats it! (10 points go to anyone who catches the video game reference in reply #2 in the screenshot).&lt;br /&gt;&lt;br /&gt;In this tutorial, we nested replies inside of a topic, and set the views/controllers accordingly.  Next time, we will take a look at authentication using the RESTful authentication plug-in and acts_as_state_machine plugin.&lt;br /&gt;&lt;br /&gt;Feel free to leave comments, and link me from your site.  See you next time!&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;digg_url = 'http://railsonedge.blogspot.com/2008/02/rails-forum-tutorial-for-beginnerspart.html';&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-5424497371976458051?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/5424497371976458051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=5424497371976458051' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/5424497371976458051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/5424497371976458051'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/02/rails-forum-tutorial-for-beginnerspart.html' title='Rails Forum Tutorial for Beginners(Part 2 of 3)'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-496460517045196442</id><published>2008-02-22T12:53:00.006-06:00</published><updated>2008-03-16T21:11:35.249-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='Forum'/><category scheme='http://www.blogger.com/atom/ns#' term='Newbie'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='beginner'/><title type='text'>Rails Forum Tutorial for Beginners (Part 1 of 3)</title><content type='html'>This is my first tutorial, so bear with me.  I am writing it as if trying to teach someone brand new to rails what is going on.  We are going to be creating a forum site in Ruby on Rails(2.0).  I plan on this to be a several-part series, so keep coming back and checking for updates.&lt;br /&gt;&lt;br /&gt;So here we go!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  rails myforum -d mysql&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will create the project folder 'myforum' and force the database used to mysql(the newest version of rails default to sqlite3).  All kinds of files and folders are created, but don't let them overwhelm you.  Rails is an application framework, so by creating all this stuff it will force you to keep everything organized according to Rails' conventions.&lt;br /&gt;&lt;br /&gt;Now, the general layout I decided on for the forums is this: The site will have multiple forums, each forums is going to have multiple topics, and each topic will have multiple replies.  To get this going, lets try this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  cd myforum&lt;br /&gt;  ruby script/generate scaffold Forum name:string description:text&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;More files and directories are created, setting up migration files for the database, a model, a controller, and views for the Forum class.  Lets analyze the command we just gave:&lt;br /&gt;ruby script/generate - on a mac or on linux, it would be script/generate(I'm on windows).  You will be using script/generate for a lot of things in rails, so get used to typing that one.&lt;br /&gt;scaffold Forum - This tells rails that you want to generate a scaffold for the class 'Forum&lt;br /&gt;name:string description:text - in the forums table that will be created, it will have 2 columns: name, and description.  the :string and :text are the type of data, with string being a small 1 liner used for naming, and text being something that can be much longer.  Moving on....&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  rake db:create&lt;br /&gt;  rake db:migrate&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;rake db:create will create your mySQL database for you (called myforum_development).  rake db:migrate will create the table for the forum class.&lt;br /&gt;&lt;br /&gt;Now lets fire up the server and see what we've got!&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  ruby script/server&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And point your web browser(and you better not be using IE!) to http://localhost:3000&lt;br /&gt;  &lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen1.jpg" /&gt; &lt;br /&gt;&lt;br /&gt;So the server is working fine, now go to http://localhost:3000/forums&lt;br /&gt;&lt;br /&gt;  &lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen2.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;If you click on New forum, it will give you a form with fields for Name and Description.&lt;br /&gt;&lt;br /&gt;  &lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen3.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen4.jpg"&gt;&lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen4.jpg" class="wide"/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And then click back:&lt;br /&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen5.jpg"&gt;&lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen5.jpg" class="wide" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;Thats right! With only 4 lines of code, rails was able to generate all of this! The scaffolding will create everything you need to Create, Read, Update, and Delete(CRUD).&lt;br /&gt;&lt;br /&gt;Moving on, lets set things up so that rails will show the list of forums page by just going to http://localhost:3000, and get rid of that rails info page.  Delete the file public/index.html, and then in config/routes.rb do this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#In config/routes.rb&lt;br /&gt;&lt;br /&gt;ActionController::Routing::Routes.draw do |map|&lt;br /&gt;  map.resources :forums&lt;br /&gt;  map.root :controller =&gt; 'forums', :action =&gt; 'index' # &lt;-------add this line&lt;br /&gt;&lt;br /&gt;  ..........&lt;br /&gt;  ..........&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So this is our first editing of a rails file.  routes.rb is very important to the whole rails applications.  They take a request for a URL and turn it into a request from a controller and an action.  In this case, the line we added will take a request for the root(http://localhost:3000) and give us back the index action of the forums controller(which will list all the forums). Save, and again, point the browser to http://localhost:3000:&lt;br /&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen5.jpg"&gt;&lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen5.jpg" class="wide" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Great!  Now, lets go ahead and generate scaffolding for our other 2 classes: Topics and Replies:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;small&gt;&lt;br /&gt;  ruby script/generate scaffold Topic forum:references user:references subject:string body:text&lt;br /&gt;  &lt;br /&gt;  ruby script/generate scaffold Reply topic:references user:references subject:string body:text&lt;br /&gt;  &lt;br /&gt;  rake db:migrate&lt;br /&gt;&lt;/small&gt;&lt;/pre&gt;&lt;br /&gt;We have something new here.  forum:references means that a topic will contain a foreign key to the forum it belongs to.  It will also contain a foreign key for the user the posts it. Additionally, a reply will belong to a certain topic. And again, rake db:migrate will create the additional tables in the database.  Don't worry about the User class yet, that part will be in a later tutorial when we add authentication.&lt;br /&gt;&lt;br /&gt;If you go to http://localhost:3000/topics and http://localhost:3000/topics, you will see similar pages to the forum page that was created earlier.&lt;br /&gt;&lt;br /&gt;Now that we have our scaffolding up, its time to take a look at some of the code that was generated and put it where we want it.  First, lets go to /config/routes.rb and do a few things:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;BEFORE:&lt;br /&gt;  #In config/routes.rb&lt;br /&gt;  &lt;br /&gt;ActionController::Routing::Routes.draw do |map|&lt;br /&gt;&lt;br /&gt;  map.resources :replies&lt;br /&gt;  map.resources :topics&lt;br /&gt;  map.resources :forums&lt;br /&gt;&lt;br /&gt;  map.root :controller =&gt; 'forums', :action =&gt; 'index'  &lt;br /&gt;  ...............&lt;br /&gt;  ...............&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;AFTER:&lt;br /&gt;  #In config/routes.rb&lt;br /&gt;  &lt;br /&gt;ActionController::Routing::Routes.draw do |map|&lt;br /&gt;&lt;br /&gt;  map.resources :forums, :has_many =&gt; :topics&lt;br /&gt;  map.resources :topics, :has_many =&gt; :replies&lt;br /&gt;  map.resources :replies&lt;br /&gt;&lt;br /&gt;  map.root :controller =&gt; 'forums', :action =&gt; 'index'&lt;br /&gt;  ...............&lt;br /&gt;  ................&lt;br /&gt;end  &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This sets up routing so that to view a specific post, you would go to a URL like: /forums/1/posts/3, and to see a reply /posts/1/replies/3.&lt;br /&gt;&lt;br /&gt;Moving on, lets edit the files in /app/models/&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#forum.rb&lt;br /&gt;&lt;br /&gt;class Forum &lt; ActiveRecord::Base&lt;br /&gt;  has_many :topics&lt;br /&gt;  has_many :replies, :through =&gt; :topics&lt;br /&gt;end&lt;br /&gt;------------------------------&lt;br /&gt;#topic.rb&lt;br /&gt;&lt;br /&gt;class Topic &lt; ActiveRecord::Base&lt;br /&gt;  belongs_to :forum&lt;br /&gt;  belongs_to :user&lt;br /&gt;  has_many :replies&lt;br /&gt;end&lt;br /&gt;-------------------------------&lt;br /&gt;#reply.rb&lt;br /&gt;&lt;br /&gt;class Reply &lt; ActiveRecord::Base&lt;br /&gt;  belongs_to :topic&lt;br /&gt;  belongs_to :user&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;All of that should make sense to you, just fleshing out some of the stuff we've already talked about.&lt;br /&gt;&lt;br /&gt;Next, lets check out /app/controllers/topics_controller.rb.  Add these lines to it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  before_filter :load_forum&lt;br /&gt;  &lt;br /&gt;  def load_forum&lt;br /&gt;    @forum = Forum.find(params[:forum_id])&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;before_filter :load_forum will cause the load_forum method to be called anytime the topics controller is accessed.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now, in the index function, change:&lt;br /&gt;&lt;pre&gt;@topics = Topic.find(:all)&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;pre&gt;@topics = @forum.topics&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now change every instance of:&lt;br /&gt;&lt;pre&gt;@topic = Topic.find(params[:id])&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;pre&gt;@topic = @forum.topics.find(params[:id])&lt;/pre&gt;&lt;br /&gt;and in the new function:&lt;br /&gt;&lt;pre&gt;@topic = Topic.new&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;pre&gt;@topic = @forum.topics.build&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Change the create function from:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def create&lt;br /&gt;    @topic = Topic.new(params[:topic])&lt;br /&gt;&lt;br /&gt;    respond_to do |format|&lt;br /&gt;      if @topic.save&lt;br /&gt;        flash[:notice] = 'Topic was successfully created.'&lt;br /&gt;        format.html { redirect_to(@topic) }&lt;br /&gt;        format.xml  { render :xml =&gt; @topic, :status =&gt; :created, :location =&gt; @topic }&lt;br /&gt;      else&lt;br /&gt;        format.html { render :action =&gt; "new" }&lt;br /&gt;        format.xml  { render :xml =&gt; @topic.errors, :status =&gt; :unprocessable_entity }&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def create&lt;br /&gt;    @topic = @forum.topics.build(params[:topic])&lt;br /&gt;&lt;br /&gt;    respond_to do |format|&lt;br /&gt;      if @topic.save&lt;br /&gt;        flash[:notice] = 'Topic was successfully created.'&lt;br /&gt;        format.html { redirect_to(@forum) }&lt;br /&gt;        format.xml  { render :xml =&gt; @topic, :status =&gt; :created, :location =&gt; @topic }&lt;br /&gt;      else&lt;br /&gt;        format.html { render :action =&gt; "new" }&lt;br /&gt;        format.xml  { render :xml =&gt; @topic.errors, :status =&gt; :unprocessable_entity }&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In update, change the line:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  format.html { redirect_to(@topic) }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  format.html { redirect_to(@forum) }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and finally, in destroy, change the line:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;format.html { redirect_to(topics_url) }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;format.html { redirect_to(forum_topics_url(@forum)) }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Alright, lets take a look at all that we just did. With the code that was generated by the scaffold, Rails did not take into account the fact that we need to retrieve our topic classes by a foreign key(forum_id).  The majority of the changes were in setting that up correctly.  The other changes were in the redirect_to function calls.  Whenever I create, update, or destroy a topic, I want it to redirect back to the forum I was on instead of going back to the topic page automatically assigned. &lt;br /&gt;&lt;br /&gt;Now, when we go to look at a specific forum, we want it to list out not just the forum title and description, but all the topics associated with that forum.  Open up /app/views/forums/show.html.erb&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  &amp;lt;b&amp;gt;Name:&amp;lt;/b&amp;gt;&lt;br /&gt;  &lt;%=h @forum.name %&gt;;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  &amp;lt;b&amp;gt;Description:&amp;lt;/b&amp;gt;&lt;br /&gt;  &lt;%=h @forum.description %&gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;%= link_to 'Edit', edit_forum_path(@forum) %&gt; |&lt;br /&gt;&lt;%= link_to 'Back', forums_path %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Since this is our first look at a view, let go over it a bit.&lt;br /&gt;&lt;br /&gt;The &amp;lt;% tags work kind of like &amp;lt;?php tags.  They switch out of normal HTML markup to ruby code.  Inside these tags are where the magic happens.  So a tag with just &amp;lt;% will not display anything, they are useful for doing things like loops.  A tag with &amp;lt;%= will output the result into the HTML markup.  So the line &amp;lt;%=h @forum.name %&amp;gt; will display the name of the forum.  The lowercase 'h' is there escape HTML characters in output.&lt;br /&gt;Change the file to this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  &amp;lt;b&amp;gt;Forum:&amp;lt;/b&amp;gt;&lt;br /&gt;  &lt;%=h @forum.name %&gt; - &lt;%=h @forum.description %&gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;% unless @forum.topics.empty? %&gt;&lt;br /&gt;  &amp;lt;h2&amp;gt;Topics&amp;lt;/h2&amp;gt;&lt;br /&gt;  &lt;% @forum.topics.each do |topic| %&gt;&lt;br /&gt;    &amp;lt;b&amp;gt;&lt;%= link_to topic.subject, [@forum, topic] %&gt;&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;    &lt;br /&gt;  &lt;% end %&gt;&lt;br /&gt;&lt;% end %&gt;&lt;br /&gt;&lt;br /&gt;&lt;%= link_to 'Edit', edit_forum_path(@forum) %&gt; |&lt;br /&gt;&lt;%= link_to 'Back', forums_path %&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now one more thing; I want to have a 'Create New Topic' form at the bottom of the page.  First, lets take a look at /app/views/topics/new.html.erb and /app/views/topics/edit.html.erb.  These 2 files are nearly identical.  This is a good time to use the DRY(Don't Repeat Yourself) that Rails is big on. Lets create a new file called _topic.html.erb in the /app/views/topics/ folder and put the following code into it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;% form_for([@forum, @topic]) do |f| %&gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&lt;br /&gt;    &amp;lt;b&amp;gt;Subject&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;    &lt;%= f.text_field :subject %&gt;&lt;br /&gt;  &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&lt;br /&gt;    &amp;lt;b&amp;gt;Body&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;    &lt;%= f.text_area :body %&gt;&lt;br /&gt;  &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&lt;br /&gt;    &lt;%= f.submit button_name %&gt;&lt;br /&gt;  &amp;lt;/p&amp;gt;&lt;br /&gt;&lt;% end %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And then change edit.html.erb and new.html.erb to look like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#edit.html.erb&lt;br /&gt;&lt;br /&gt;&amp;lt;h1&amp;gt;Editing topic&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;%= error_messages_for :topic %&gt;&lt;br /&gt;&lt;br /&gt;&lt;%= render :partial =&gt; @topic, :locals =&gt; { :button_name =&gt; "Submit" } %&gt;&lt;br /&gt;&lt;br /&gt;&lt;%= link_to 'Show', [@forum, @topic] %&gt; |&lt;br /&gt;&lt;%= link_to 'Back', topics_path %&gt;&lt;br /&gt;&lt;br /&gt;----------------------------&lt;br /&gt;#new.html.erb&lt;br /&gt;&lt;br /&gt;&amp;lt;h1&amp;gt;New topic&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;%= error_messages_for :topic %&gt;&lt;br /&gt;&lt;br /&gt;&lt;%= render :partial =&gt; @topic, :locals =&gt; { :button_name =&gt; "Create" } %&gt;&lt;br /&gt;&lt;br /&gt;&lt;%= link_to 'Back', topics_path %&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That cleaned up a good bit of code. Since the only real difference in the 2 forms for those pages was the button name, we created what is called a partial in the file _topic.html.erb, and then rendered the partial in new.html.erb and edit.html.erb, passing in the value of the button name.  And now, we can also re-use the partial in /app/views/forums/show.html.erb&lt;br /&gt;&lt;br /&gt;Change the file to look like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  &amp;lt;b&amp;gt;Forum:&amp;lt;/b&amp;gt;&lt;br /&gt;  &lt;%=h @forum.name %&gt; - &lt;%=h @forum.description %&gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;% unless @forum.topics.empty? %&gt;&lt;br /&gt;  &amp;lt;h2&amp;gt;Topics&amp;lt;/h2&amp;gt;&lt;br /&gt;  &lt;% @forum.topics.each do |topic| %&gt;&lt;br /&gt;    &amp;lt;b&amp;gt;&lt;%= link_to topic.subject, [@forum, topic] %&gt;&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;    &lt;br /&gt;  &lt;% end %&gt;&lt;br /&gt;&lt;% end %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;h2&amp;gt;New Post&amp;lt;/h2&amp;gt;&lt;br /&gt;&lt;%= render :partial =&gt; @topic = Topic.new, :locals =&gt; { :button_name =&gt; 'Create' } %&gt;&lt;br /&gt;&lt;br /&gt;&lt;%= link_to 'Edit', edit_forum_path(@forum) %&gt; |&lt;br /&gt;&lt;%= link_to 'Back', forums_path %&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;One more thing, open up /app/views/topics/show.html.erb and remove this part:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  &amp;lt;b&amp;gt;User:&amp;lt;/b&amp;gt;&lt;br /&gt;  &lt;%=h @topic.user %&gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since we haven't implemented the authentication yet.&lt;br /&gt;&lt;br /&gt;And change the line:&lt;br /&gt;&lt;pre&gt;&lt;%=h @topic.forum %&gt;&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;pre&gt;&lt;%=h @forum.name %&gt;&lt;/pre&gt;&lt;br /&gt;And then change:&lt;br /&gt;&lt;pre&gt;&lt;%= link_to 'Back', topics_path %&gt;&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;pre&gt;&lt;%= link_to 'Back', forum_path(@forum) %&gt;&lt;/pre&gt;&lt;br /&gt;Save everything, fire up the server, and head back to http://localhost:3000&lt;br /&gt;&lt;pre&gt;ruby script/server&lt;/pre&gt;&lt;br /&gt;  &lt;a href="http://users.csc.tntech.edu/~rledge21/blog/screens/screen5.jpg"&gt;&lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen5.jpg" class="wide" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;  Click Show&lt;br /&gt;&lt;br /&gt;  &lt;img src="http://users.csc.tntech.edu/~rledge21/blog/screens/screen6.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;  And there we go!  You can add a new post, and then click on it to show it.&lt;br /&gt;&lt;br /&gt;  So far in the tutorial, we have generated scaffolding for 3 classes(forum, topic, reply), set up the nested routing for topics to be inside forums, and replies to be inside topics, and modified the controllers and view for forum and topic to work like we need it to. &lt;br /&gt; &lt;br /&gt;  I've decided this will be a 3-part tutorial.  The next part will be to get the Replies working(it will be very similar to what we did with nesting topics inside forums) by modifying the views for topics, and the views and controllers for replies.  The third part will be to set up Authentication and Admin priveleges.&lt;br /&gt;&lt;br /&gt;  Let me know what you think, or if you have any questions.  And tell your friends.&lt;br /&gt;&lt;br /&gt;  See you next time!&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;digg_url = 'http://railsonedge.blogspot.com/2008/02/rails-forum-tutorial-for-beginners-part.html';&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-496460517045196442?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/496460517045196442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=496460517045196442' title='54 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/496460517045196442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/496460517045196442'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/02/rails-forum-tutorial-for-beginners-part.html' title='Rails Forum Tutorial for Beginners (Part 1 of 3)'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>54</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-3359351387274534548</id><published>2008-02-20T00:29:00.000-06:00</published><updated>2008-02-21T14:32:29.465-06:00</updated><title type='text'>Ruby on Rails 2.0 forum</title><content type='html'>I decided to start work on a forum today.  Using the concepts I learned in &lt;a href="http://www.akitaonrails.com/2007/12/12/rolling-with-rails-2-0-the-first-full-tutorial" title="AkitaonRails"&gt;Akita On Rails&lt;/a&gt;'s tutorial to route a comment into a blog post can be similarly used to route a post to a forum and a reply to a post. I might look into something more complicated later such as a reply to a reply(digg style).  I'm going to start by getting it all working regularly and then attempt to add in some AJAX to make it look spiffy.&lt;br /&gt;&lt;br /&gt;Anyway, first I decided that I needed some kind of Authentication for accounts, sessions, and whatnot so I went back to my favorite resource &lt;a href="www.rubyplus.org" title="RubyPlus.org"&gt;RubyPlus.org&lt;/a&gt; and checked out the screencast &lt;a href="http://www.rubyplus.org/episodes/20-Extended-RESTful-Authentication-Rails-2-App.html" title="RESTful Authentication"&gt;RESTful Authentication tutorial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There were a couple small problems I ran into, I'm assuming because there is a new version of act_as_state_machine plugin that has came out since the tutorial that was wrote.  I will add that to the post tomorrow, along with a tutorialized version of all the steps I have taken so far.&lt;br /&gt;&lt;br /&gt;Oh, and here are some beginner resources/tutorials I have found around the net the past few days:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;a href="http://www.rubyplus.org/" title="rubyplus.org"&gt;RubyPlus&lt;/a&gt;&lt;br /&gt;&lt;a href="www.akitaonrails.com/2007/12/12/rolling-with-rails-2-0-the-first-full-tutorial - 121k -" title="akitaonrails"&gt;Akita On Rails&lt;/a&gt;&lt;br /&gt;&lt;a href="http://fairleads.blogspot.com/2007/12/rails-20-and-scaffolding-step-by-step.html" title="fairleads"&gt;Fairleads&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.onlamp.com/pub/a/onlamp/2005/06/09/rails_ajax.html" title="ONLamp.com Rails AJAX Tutorial"&gt;ONLamp.com Rails AJAX Tutorial&lt;/a&gt; - this is an old article but AJAX in rails made a lot more sense to me after I read this one.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Well thats it, will update you on my forum app tomorrow.  Thanks for coming, and feel free to spread the word!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-3359351387274534548?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/3359351387274534548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=3359351387274534548' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3359351387274534548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/3359351387274534548'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/02/ruby-on-rails-20-forum.html' title='Ruby on Rails 2.0 forum'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-7274921245897404987</id><published>2008-02-18T14:48:00.000-06:00</published><updated>2008-02-18T15:59:46.490-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='depot'/><category scheme='http://www.blogger.com/atom/ns#' term='rubyplus'/><category scheme='http://www.blogger.com/atom/ns#' term='awdr'/><category scheme='http://www.blogger.com/atom/ns#' term='&quot;TypeError: $(&quot;current_item&quot;) has no properties&quot;'/><title type='text'>AWDR depot app for Rails 2.0 (RubyPlus.org) - Part 2</title><content type='html'>Here goes part 2.&lt;br /&gt;&lt;br /&gt;I've finished the screencasts for chapter 8, 9, and 10.&lt;br /&gt;&lt;br /&gt;Here are the problems I came across while doing so:&lt;br /&gt;&lt;br /&gt;At the beginning of chapter 8, the top of the screen is cut off when creating sessions in the database, the is the whole line:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  rake db:sessions:create&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And then towards the beginning of chapter 10, a line is cut off in 005_create_line_items.rb&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  t.decimal :total_price, :null =&gt; false, :precision =&gt; 8, :scale =&gt; 2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I had some trouble with the ajax highlight effect in add_to_cart.js.rjs&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  page[:current_item].visual_effect :highlight, &lt;br /&gt;        :startcolor =&gt; "#88ff88", &lt;br /&gt;        :endcolor =&gt; "#114411"      &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and was not able to figure it out.  When I clicked Add to Cart, I would get the error "TypeError: $("current_item") has no properties" and then another popup window with a lot of code in it.  I looked around the internet for a while trying to get it fixed, but nothing I tried worked.  If anyone figures this out, let me know. I ended up commenting out that line in add_to_cart.js.rjs.&lt;br /&gt;&lt;br /&gt;Everything else works great. I really like Bala's screencasts, they are a great resource for learning Rails 2.0.  After finishing them, I believe I know enough to make something that is not too complicated.  For my next post, I believe I am going to start working on a forum in Rails, and AJAX it up(I could use a lot more experience with AJAX).&lt;br /&gt;&lt;br /&gt;See you all next time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-7274921245897404987?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/7274921245897404987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=7274921245897404987' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/7274921245897404987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/7274921245897404987'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/02/awdr-depot-app-for-rails-20-rubyplusorg.html' title='AWDR depot app for Rails 2.0 (RubyPlus.org) - Part 2'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-7930661139455605868</id><published>2008-02-14T10:01:00.000-06:00</published><updated>2008-02-21T14:31:14.604-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='depot'/><category scheme='http://www.blogger.com/atom/ns#' term='rubyplus'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby on rails'/><category scheme='http://www.blogger.com/atom/ns#' term='awdr'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='beginner'/><title type='text'>New Resource for Beginner 2.0 Tutorials</title><content type='html'>Just found a site with some great video tutorials for beginners.  Its &lt;a href="http://www.blogger.com/www.rubyplus.org" title="RubyPlus"&gt;RubyPlus.org&lt;/a&gt;.  You have to create a free account to access the download.&lt;br /&gt;&lt;br /&gt;When I first went to learn Ruby, the book unanimously suggested to me was Agile Web Development with Rails.  After a quick search I had found out that the tutorials, of course, didn't work with 2.0.  A little more searching and I came across &lt;a href="http://www.blogger.com/www.rubyplus.org" title="RubyPlus"&gt;RubyPlus&lt;/a&gt;.  He has the depot app from the book adapted to Rails 2.0, and video tutorials on it.  You will need some of the source that came with the book, which can be downloaded &lt;a href="http://www.pragprog.com/titles/rails2/source_code" title="AWDR Source Code"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;After you create your account at &lt;a href="http://www.blogger.com/www.rubyplus.org" title="RubyPlus"&gt;RubyPlus&lt;/a&gt;, click Archives to see the tutorials. The AWDR depot ones are 19, 22, 27, 28, 29.  It looks like there is a lot of good material on this site besides depot tutorials, I plan to spend a lot of time watching Bala's screencasts.&lt;br /&gt;&lt;br /&gt;Also, you can find his blog &lt;a href="http://bparanj.blogspot.com/" title="bparanj's Blog"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;On to the tutorial:&lt;br /&gt;&lt;br /&gt;I've finished the first 2 screencasts without too much trouble.  He moves pretty fast, and copies/pastes a lot of code when he creates new files, so be ready to pause so you can type everything out.&lt;br /&gt;&lt;br /&gt;In the first screencast, we set up the project, created scaffolding, and played around with the view a little.  In the second, we created an admin namespace, and then nested a product route under it, changing the controllers and views so that only an admin could add, edit, and destroy books.  So far, much like the blog app from the AkitaOnRails site.&lt;br /&gt;&lt;br /&gt;There was a point where you needed some images and css files from the AWDR book (link above), and despite what he says on his page, you don't need to buy the book to download it(although I had the book already).  There is also a segment in the first screencast where he is creating a bootstrap.rake file to set up automatic population of the database, and the screen cuts off some of the code he pastes into the file, the full contents of the file are:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SITE_DIR = File.join(RAILS_ROOT, 'themes/site-' + (ENV['SITE_ID'] || '1'))&lt;br /&gt;namespace :db do&lt;br /&gt;   namespace :bootstrap do&lt;br /&gt;        desc "Load initial database fixtures (in db/bootstrap/*.yml) into the current environment's database.  &lt;br /&gt;                        Load specific fixtures using FIXTURES=x,y"&lt;br /&gt;        task :load =&gt; :environment do&lt;br /&gt;             require 'active_record/fixtures'&lt;br /&gt;             ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)&lt;br /&gt;             (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'db', 'bootstrap',&lt;br /&gt;                       '*.{yml,csv}'))).each do |fixture_file|&lt;br /&gt;                  Fixtures.create_fixtures('db/bootstrap', File.basename(fixture_file, '.*'))&lt;br /&gt;             end&lt;br /&gt;        end&lt;br /&gt;   end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;See you next time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-7930661139455605868?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/7930661139455605868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=7930661139455605868' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/7930661139455605868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/7930661139455605868'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/02/new-resource-for-beginner-20-tutorials.html' title='New Resource for Beginner 2.0 Tutorials'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-1758586991983231582</id><published>2008-02-12T15:15:00.000-06:00</published><updated>2008-02-13T13:16:14.209-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='beginner'/><title type='text'>Akita on Rails Tutorial</title><content type='html'>Before I start, I will note that I tried to do a couple of tutorials before I created this blog and because of them being written for pre-2.0 it didn't work out so well, but I got a little bit of an introduction to Rails with them anyway, so I am not completely vanilla when it comes to Rails, just mostly so.&lt;br /&gt;&lt;br /&gt;For my first tutorial, I decided to try &lt;a href="http://www.akitaonrails.com/2007/12/12/rolling-with-rails-2-0-the-first-full-tutorial" title="Rolling with Rails 2.0 - The First Tutorial"&gt;Rolling with Rails 2.0 - The First Tutorial&lt;/a&gt;  at &lt;a href="http://www.blogger.com/www.akitaonrails.com" title="Akita on Rails"&gt;AkitaonRails.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now this tutorial assumes that you have used Rails before 2.0, but it seems to break everything down enough for me to know whats going on.  I've made it to the section on Namespaced Routes, where I plan to pick back up tomorrow.  So far I've not had any trouble besides a couple of typos I had to go back and fix.&lt;br /&gt;&lt;br /&gt;A couple of notes:&lt;br /&gt;&lt;br /&gt;The newest version of rails defaults to sqlite3 as the database, to force it to use mysql, when you create the project, use:&lt;br /&gt;&lt;br /&gt;rails blog -d mysql&lt;br /&gt;&lt;br /&gt;instead of:&lt;br /&gt;&lt;br /&gt;rails blog&lt;br /&gt;&lt;br /&gt;Also, since I'm on Windows(not by my choice, my computer at home runs Ubuntu), on lines where the tutorial runs something from the script folder:&lt;br /&gt;./script/generate&lt;br /&gt;./script/server&lt;br /&gt;&lt;br /&gt;I had to use:&lt;br /&gt;&lt;br /&gt;ruby script/generate&lt;br /&gt;ruby script/server&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Easy enough.  I'll be updating this post tomorrow with the rest of part one of this tutorial.&lt;br /&gt;&lt;br /&gt;EDIT: Tomorrow&lt;br /&gt;&lt;br /&gt;Just finished up part one, adding in admin functionality using Namespaced Routes.  Basically we set up all the routing for admin, and copied the views of what was already created, so that for admin rights, you would go to /admin/posts as opposed to /posts.  Then we went to the views for the regular posts and stripped out the ability to add/delete/edit posts, and to delete/edit comments.&lt;br /&gt;&lt;br /&gt;Alright now for my opinion of the tutorial:&lt;br /&gt;&lt;br /&gt;While this was aimed for people with a little experience at Rails, Akita did a great job of not assuming we knew too much, making it easy to follow and understand what was going on.&lt;br /&gt;&lt;br /&gt;The amount of effort that it takes to make a small web app such as this is amazing.  This is as complicated as some projects that have taken me weeks to program in PHP (I never did learn CakePHP or any of the like).  If I had known, I would have been using Rails a while ago.  I would have moved on to the 2nd part of the tutorial, but the link seems to be down right now, so I guess it will wait until the next post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-1758586991983231582?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/1758586991983231582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=1758586991983231582' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/1758586991983231582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/1758586991983231582'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/02/akita-on-rails-tutorial.html' title='Akita on Rails Tutorial'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2911377234335400421.post-7630529515444997053</id><published>2008-02-12T13:59:00.000-06:00</published><updated>2008-02-12T14:48:02.986-06:00</updated><title type='text'>New Blog!</title><content type='html'>So this is my first blog.  I'm going to be learning Ruby on Rails 2.0 so I thought I might start up a blog to document the whole process, maybe help out someone else in the process.&lt;br /&gt;&lt;br /&gt;So a quick google tells me that there are several others having my same problem:&lt;br /&gt;PAUSE: while typing this I notice that if you don't capitalize 'google' blogger tells me that it is misspelled - it seems that google(who owns blogger.com) wouldn't mind the name of their company falling under the category of common noun, but back to the problem:&lt;br /&gt;&lt;br /&gt;Rails 2.0 was just released, and while there are some excellent resources for beginners to Rails(Agile Web Development with Rails), they are mostly pre-2.0, and due to some of the major changes, will not work.  So the choices at this point to newcomers to Rails:&lt;br /&gt;&lt;br /&gt;1) Downgrade to an older version and use one of the tutorials.&lt;br /&gt;2) Stick with 2.0 and work through the old tutorials, using internet resources to fix things broken by 2.0&lt;br /&gt;3) Scour the internet for the few 2.0 tutorials for beginners.&lt;br /&gt;&lt;br /&gt;I'm going to go with option 3.  I'll be posting resources, screenshots, and anything else that I find useful in my journey.  Feel free to leave comments if you have any questions, suggestions, or corrections. &lt;br /&gt;&lt;br /&gt;Oh, and welcome to Rails on Edge!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2911377234335400421-7630529515444997053?l=railsonedge.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://railsonedge.blogspot.com/feeds/7630529515444997053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2911377234335400421&amp;postID=7630529515444997053' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/7630529515444997053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2911377234335400421/posts/default/7630529515444997053'/><link rel='alternate' type='text/html' href='http://railsonedge.blogspot.com/2008/02/new-blog.html' title='New Blog!'/><author><name>rledge21</name><uri>http://www.blogger.com/profile/07280624261775331061</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
