Reverse Proxy Fix 1.0.5.0 released

Posted by Brian in News, Products, Rails (March 7th, 2008)

The reverse_proxy_fix plugin allows a Rails application to live behind a proxy like the one provided by HeliconTech’s ISAPI_Rewrite plugin as outlined in Deploying Rails Applications. It allows you to configure the base URL that will be prepended to any URL generated by the Rails link_to method and friends. This is useful if you want to force all requests through a frontend or if you want to graft your Rails application onto an existing IIS URL scheme.

This release fixes an issue with named routes and Rails 2.0. Previous versions of the plugin did not support rewriting of named routes in Rails 2.0 due to the optimization code for named routes. This version of the plugin disables the optimizations.

Installation

Installation is simple:

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

Then provide your base URL, which is the URL you want prepended to all of your URLs. For example, if you are trying to mount your Rails application at http://www.mydomain.com/myapp, you’d enter that as your base URL.

Next you need to specify which version of Rails you are using.

Comments are welcome, and so are patches if you see something that doesn’t make sense.

Mini-CMS for your Rails application

Posted by Brian in Rails, snacks, tips (March 3rd, 2008)

I’ve worked on several applications where an end user may need to change text on various sections of a web site. I’ve used this technique a few times and it’s worked out well so I thought I’d share.

We’re going to create a model called Content which will be backed by a database. When a request comes in, we can look at the requested controller and action name to look up all of the content sections for a page. Some pages may have more than one content section.

This solution is intended to be implemented and modified by developers. An end user would not be able to add new content regions to a system.

Create the model and table

ruby script/generate model Content

Next, modify the migration:

class CreateContents < ActiveRecord::Migration
  def self.up
    create_table :contents do |t|
      t.string :controller, :action, :name
      t.text :body
      t.timestamps
    end
  end			

  def self.down
    drop_table :contents
  end
end

The name field is what our end user will use to locate and edit a section. They don't need to know the controller and action name. Instead, they'll probably look for a content region like "Home Page main content". In order to make this work, the user will only be able to edit the body field. The other fields will be handled by the system.

Now, open up the content model. We're going to add a few methods here to easily grab the content out so we can use it in views. Out of the box, ActiveRecord allows us to find all the sections for a controller and action name by doing

@contents = Content.find_all_by_controller_and_action("public", "index")

At first glance, that looks pretty cool, but how do you identify the individual regions? You'd have to loop through that collection every time you want to output something. If you only have one content area per page, this could be good enough. However, I like things to be a little more spelled-out.

Add this method to the content class:

  def self.get_content_for(controller, action)
    c = Content.find_all_by_controller_and_action(controller, action)
    content = Hash.new
    c.each do |record|
      content[record.name] = record.body
    end
    content
  end'

Now, to fetch all of the sections for the page, we only need to call

@contents = Content.get_content_for "public", "index"

This class method fetches all of the content sections and then puts then into a hash which you can afccess via the name.

Trying it out

Open up the console and put two content regions in:

   ruby script/console
Content.create :controller=>"public", :action=>"index", :name=>"intro", :body => "Hello world"
Content.create :controller=>"public", :action=>"index", :name=>"main_content", :body => "Main content goes here"

Now quickly generate a new controller and action

ruby script/generate controller public index

Add this to the public controller

before_filter :get_content

Now open application.rb and add this method:

def get_content
  @content = Content.get_content_for(params[:controller], params[:action])
end

Finally, open up app/views/public/index.html.erb and change its contents.

Home page

<%=@contents["intro"] %>

About us

<%=@contents["main_content"] %>

Summary

I've used this approach in a few sites and it's served me well. I'd love to hear how you've done the same. Post ideas and suggestions in the comments.

Parsetreee gem available for Windows!

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

Luis Laverna compiled and released the parsetree gem for Windows. This means that libraries like ruby2ruby, heckle, flog, and even the merb framework are now available to Windows Rubyists.

You need to look at flog. It can show you how bad your code really is.

mongrel_service broken on Windows again.

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

If you’re working with the mongrel_service gem then you should know that right now there’s a few kinks in the system.

Here’s a quick rundown of the setup for Rails on Windows from scratch:

Download the One Click Ruby Installer and run the setup program.

Open a command prompt and type these commands:

gem update --system
gem install rails
gem install mongrel
gem install win32-service -v '0.5.2'
gem install mongrel_service

The key to this is that the win32-service gem is currently broken, so switching to a previous version (0.5.2) works great for us. Credit for this goes to Luis Laverna, the creator of the mongrel_service gem. See the discussion.

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.

ScaffoldForm Generator

Posted by Brian in News, Products, Rails (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, and 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 Products, Rails (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
    
         ServerName myapp.mydomain.com
         ProxyPass / http://internal.mydomain.com/
         #TransferLog /net/www/logs/sun.docs.access
         #ErrorLog    /net/www/logs/sun.docs.errror
    
    
  • 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 Howto, Rails, 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 script\generate 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 script\generate 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
    
« Previous PageNext Page »