How To Follow Along with Agile Web Development with Rails Second Edition

Posted by Brian in Rails, tips (January 1st, 2008)

This is merely for reference for anyone out there new to Rails or Ruby and trying to work with the Agile book. Version 2.0.2 of Rails is out now and it’s just way too difficult to follow along with the great AWDWR book from Pragmatic. To be successful with that book, you need to use Rails 1.2.3. Here’s how you do it:

Mac

If you have a brand new macbook pro, you’re done. It comes equipped with Rails 1.2.3. Start following along with the first Hello World program.

If you’ve accidentally installed Rails 2.0, you can start a Rails 1.2.3 project like this:

sudo gem update --system
sudo gem install rails -v=1.2.3
rails _1.2.3_ depot

where depot is the name of your project.

Windows

If you’ve got a Windows machine, start from scratch. Grab The one click ruby installer (Windows installer) and install it.

Next, open up a command prompt and install Rails 1.2.3, and Mongrel

gem update --system
gem install rails -v '1.2.3'
gem install mongrel
gem install mysql

Now just go ahead and follow along with the book. When you’re done, you can update to Rails 2.0 by doing

gem install rails

which will install the latest version of Rails. Your current Rails apps are tied to the version of Rails they are created on. You change the version of Rails the app uses by “freezing gems” (placing a copy of Rails in the app’s vendor/rails folder, or by editing the app’s config/environment.rb file and changing the version specified there. Do a web search for more info on this.

You can specify the version of Rails you want to use by passing it along on the commandline

rails _1.2.3_ old_rails_app
rails _1.2.6_ ready_to_update_app
rails _1.1.6_ legacy app
rails _2.0.2_ new_rails_app

Just make sure you have all of the Rails versions that you want to use on your machine.

reverse_proxy_fix 1.0.4.1 released with Rails 2.0 support

Posted by Brian in News (December 18th, 2007)

I’ve been testing this release for about two months but had not released it yet. A friendly email from a user of this plugin alerted me to the fact that I should really push this release out, especially as it’s featured in Deploying Rails Applications

Reverse_proxy_fix is a plugin that prepends the base url of your choice to any of the URLs generated by Rails’ URL helpers. It’s primarily designed to allow you to hide your application behind a reverse proxy like ISAPI_Rewrite for IIS, though I’ve heard that people have used it elsewhere.

Say you have an app that you want to host on an IIS machine at http://www.myexample.com/fun/application

You’d install this plugin and configure it to use http://www.myexample.com/fun/application as your base URL. When you run your application in production mode, all of your URLS will be prepended with http://www.myexample.com/fun/application.

To install, you need to do the plugin install thingy:

ruby script/plugin install http://svn.napcsweb.com/public/reverse_proxy_fix

When the plugin installs, you then get to configure it with an interactive script.

########################################################
# reverse_proxy_fix plugin                             #
# Configureation                                       #
########################################################
 
Enter the base url you wish to use without the trailing slash (example: http://e
xternal.mycompany.com/myapp)
http://www.project.com/app1
Please select your Rails version from the list of supported versions:
 1 : Rails 1.1.6
 2 : Rails 1.2.X
 3 : Rails 2.0
3
The file C:/projects/rscrum/vendor/plugins/reverse_proxy_fix/lib/config.rb has b
een modified. The plugin will be activated when you run your application in prod
uction mode.
Plugin successfully installed and configured

ScaffoldForm Generator

Posted by Brian in News, Rails, Products (November 4th, 2007)

I’m happy to announce the release of the ScafoldForm Generator plugin for Rails. This plugin takes the most useful piece of scaffolding, the form creation, ad makes it available as a separate generator.

You can install it with

  sudo gem install scaffold_form_generator

Then just generate the forms for your models

ruby script/generate scaffold_form Project project
ruby script/generate scaffold_form User accounts

You can read more at http://scaffoldform.rubyforge.org/
.

There are a few neat tweaks I made to it to make the forms a bit more useful.

Simple site-wide configuration in Rails

Posted by Brian in Rails, Products (October 25th, 2007)

After about three months of testing, I’m releasing the Rails Config Model gem. It’s been available on RubyForge for some time but I’ve never advertised it.

The generator will create a configuration table and a form for a system admin to modify system settings for an app. Here’s an example:

ruby script/generate rails_config_model setup logo_url:string welcome_message:text contact_email:string

That will generate a Setup model and a setup_controller complete with unit and functional tests. Developers can use this like so:

@setup = Setup.load

Then display the welcome message on the homepage

<%=@setup.welcome_message %>

You can read more at http://rconfig.rubyforge.org/

Deploying Multiple apps on one IP with Apache’s ProxyPass

Posted by Brian in Rails, tips (October 24th, 2007)

Say you’re poor and only have one IP address. If you have the ability to control your own DNS, there’s an easy fix.

  • Install Apache on one of your servers on Port 80
  • Add this to the bottom of the Apache httpd.conf file
  • NameVirtualHost 192.168.1.5
    <VirtualHost 192.168.1.5>
         ServerName myapp.mydomain.com
         ProxyPass / http://internal.mydomain.com/
         #TransferLog /net/www/logs/sun.docs.access
         #ErrorLog    /net/www/logs/sun.docs.errror
    </VirtualHost>
    
  • Point the myapp.mydomain.com DNS entry to your IP.
  • Start up Apache and you should be able to rock and roll.

This will work to forward requests to many backend servers. Just keep in mind that the IP addresses from the outside won’t show up in your logs. There are ways around that though.

Creating a new Edge Rails project in Windows (and *nix / OSX too!)

Posted by Brian in Rails, Howto, snacks (September 20th, 2007)

Rails has moved to Git so the scripts here no longer work! Visit the updated article instead.

I’ve been working with Edge Rails a lot lately, in preparation for a book I’m working on. Creating a new Rails project with Edge is a bit tricky—you need to have Edge Rails in your app’s vendor/rails folder before you can create your app. It usually involves the following steps:

  • Create the project’s folder
  • Create the vendor folder
  • Export Edge Rails to the vendor/rails folder
  • Create the Rails project using the vendor/rails/railities/bin/rails script instead of the normal one.

It seems that every time I want to do this, I have to go look at my notes and remember how. Not any more.

edge_rails

On Windows, paste this script into a new file and save the file to c:\ruby\bin\edge_rails.

@echo off
goto endofruby
#!/bin/ruby
 
require 'fileutils'
dir = ARGV[0]
dbtype = ARGV[1] rescue nil
FileUtils::mkdir(dir)
FileUtils::mkdir("#{dir}/vendor")
 
puts "Exporting EdgeRails from http://svn.rubyonrails.org/rails/trunk"
system "svn export http://svn.rubyonrails.org/rails/trunk #{dir}/vendor/rails"
 
system "ruby #{dir}/vendor/rails/railties/bin/rails #{dir} #{dbtype}"
 
__END__
:endofruby
"%~d0%~p0ruby" -x "%~f0" %*
 

Now, to create a new Edge Rails project, simply do

edge_rails my_app_name

or

edge_rails my_app_name --database=sqlite3

Right now, I’m not supporting any of the other command line options. If you want them, figure out how to do it. It’ll be a good exercise for you.

If you want to do this on a non-Windows system, just save the script below to a file called edge_rails, place the file on your path, and be sure to make it executable. You may need to change the first line of the script to correctly point to your ruby installation. Use

which ruby

to locate your Ruby path.

Here’s the script with all the Windows goodness removed.

#!/bin/ruby
 
require 'fileutils'
dir = ARGV[0]
dbtype = ARGV[1] rescue nil
FileUtils::mkdir(dir)
FileUtils::mkdir("#{dir}/vendor")
 
puts "Exporting EdgeRails from http://svn.rubyonrails.org/rails/trunk"
system "svn export http://svn.rubyonrails.org/rails/trunk #{dir}/vendor/rails"
 
system "ruby #{dir}/vendor/rails/railties/bin/rails #{dir} #{dbtype}"
 

Hope that makes someone else’s life easier too.

Adding RSS to your Rails application

Posted by Brian in Rails, snacks, tips (September 8th, 2007)

Rails makes it really simple to expose your data as XML. It also makes it pretty easy to support any other type of format.

While you can do this in Rails 1.2, this writeup will focus on doing it with Edge Rails.

Assume I have a Project model, a Projects controller, and I’m using a RESTful design…

  rails my_projects_rss --database=sqlite3
  cd my_projects_rss
  ruby scriptgenerate scaffold Project title:string description:string
  rake db:migrate
  ruby script/server

Create a new file at apps/views/projects called index.rss.builder.

Place this code in that file:

xml.rss('version' => '2.0') do
  xml.channel do 
    xml.title(@page_title)
    xml.link(projects_url)
    xml.description(@page_title)
    @projects.each { |project|
      xml.item do 
        xml.title(project.title)
        xml.link(project_url(project))
        xml.description(project.description)
        xml.pubDate(project.updated_at.rfc822)
      end
    }
  end
end

Now… take the index action in your projects controller and change it from this:

  # GET /projects
  # GET /projects.xml
  def index

    @projects = Project.find :all
 
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @projects}
    end
 
  end

to this:

  # GET /projects
  # GET /projects.xml
  # get /projects.rss
  def index
  
    @projects = Project.find :all, :order => "update_at desc"
 
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @projects}
      format.rss do 
        @page_title = "Journal entries"
        render :layout=>false
      end
 
    end
 
  end

Start up your server and add some projects. You can then navigate to http://localhost:3000/projects.rss and see the feed.

Now we’re not going to talk about how to cache the feed, but that’s easy enough to figure out.

How do I do this right now, without using Edge rails

The steps are simple.

  1. Use this to generate your resource scaffold:
          ruby scriptgenerate scaffold_resource Project title:string description:string
      
  2. Name the above mentioned RSS template file projects_rss.rxml
  3. Use this for your controller action.
      # GET /projects
      # GET /projects.xml
      # get /projects.rss
      def index
      
        @projects = Project.find :all, :order => "update_at desc"
     
        respond_to do |format|
          format.html # index.html.erb
          format.xml  { render :text => @projects.to_xml}
          format.rss do 
            @page_title = "Projects"
            render :action=>"projects_rss", :layout=>false
          end
     
        end
     
      end
    

Eclipse for Rails updates

Posted by Brian in News, Rails, Products (August 27th, 2007)

We’re gearing up to release one more version of Eclipse for Rails. It should be available this week. It will include support for some Rails 2.0 features such as the new scaffold generator, updated templates, and updated templates. Of course, there’ll also be an update to the Eclipse core.

The space for Windows-based IDEs is filling out nicely. The folks behind the NetBeans Ruby IDE really have something they can be proud of and I am considering ceasing further development of the standalone Eclipse For Rails package. What do you think?

We’re sponsoring the Rails Rumble

Posted by Brian in News, Rails (August 27th, 2007)

The Rails Rumble (http://www.railsrumble.com/) is coming up. Flex your development muscles and create an application in 48 hours. Go it alone or get a team of four together to build something incredible. The contest takes place September 8th and 9th, 2007. Registration opens at 12:00 EDT on August 28th, 2007.

We’re giving away a 30GB Ipod choice of an 80GB iPod classic or an 8GB iPod Touch to the person who develops the best app all by themselves.

Rails Functional testing with Stubs and BDD

Posted by Brian in Rails, snacks, tips (July 26th, 2007)

One of the things that bothers many people about functional tests with Rails is the seemingly unnecessary duplication of test coverage.

Consider this test, a very common “create new user” functional test:

def test_create
   post :create, {:user=>{:username => "brian",
                         :password =>"1234", 
                         :password_confirmation=>"1234", 
                         :email=>"hoganbp@uwec.edu"}}
   assert assigns(:user)
   assert_redirected_to :action=>"list"
   
   
end
 

This is an example of test-driven development at the controller level. You pass in the POST parameters so that the controller can create the user object and save it to the database. This then triggers the redirect.

But this is really kinda bad. You already know that you can save records, you’ve got unit tests that prove that your validation works. You’re really interested in how the controller responds when it creates a valid record.

Behaviors

Behavioral driven development (BDD) is a technique receiving a lot of attention lately in the Rails community. The idea is to write your tests looking at the behavior you’re trying to test, as opposed to just testing methods.

Take a look at the behavior of the controller. What’s it supposed to do?

When a new user is created successfully, it should go to the list action.

So… let’s rename that scaffolded functional test to

   def test_should_redirect_to_list_when_user_is_created
 
   end

In BDD, you use words like should to specify what should happen. See, already your test is less ambiguous. Eventually you’re going to have to test that it “should_render_registration_form_when_creation_fails” or something like that.

Stubs

We already know from unit tests we wrote that we can save user records. We don’t need to test that again. Good tests don’t cover more than one piece of functionality anyway. How do we get around to it?

Enter http://rubyforge.org/projects/mocha/. Mocha is a mocking library. You can read more about it in the documentation, but I’ll show you how to use the stubbing features to bypass creating records.

Install mocha.

  gem install mocha

Open up your test/test_helper.rb and add

  require 'mocha'

to the top of the file.

This simple bit of code added to our test makes it all work:

   User.any_instance.stubs(:save).returns(true)

You would read that as “Any instance I create of User should have its save method always return true when I call it.”

That means our functional test becomes

def test_should_redirect_to_list_when_user_is_created
   User.any_instance.stubs(:save).returns(true)
   post :create
   assert_redirected_to :action=>"list"
   
end

Wrapping up

Stubbing helps you decouple your methods, and BDD helps you think about your process rather than your code. I encourage you to read more about both. Keep in mind you still want to test other aspects of your controllers, and sometimes you might want to ensure that certain things work certain ways. For example, you might still need @user to contain real data when you do searches so your views will render properly. This is just an example of the power of stubbing.

« Previous PageNext Page »