Upgrading to Rails 2.0.2 problems/solutions

Problem
Upgrading from Rails version 1.2.3 to version 2.0.2.
Following the suggestion in DH’s weblog here when using sudo gem install rails -y, it gets the trunk version of rails which at the time was 2.0.2.9216.
This causes a few problems and breaks a few more things.

Solution
In order to get back to the latest stable version, you have to uninstall a few of the gems installed from the trunk version.
If you have installed the latest version of top of an existing one using gems, then doing:

gem list --local

will give you all the installed versions of the gems. Something like:

actionmailer (2.0.2.9216, 2.0.2, 1.3.3)
actionpack(2.0.2.9216, 2.0.2, 1.3.3)
rails(2.0.2.9216, 2.0.2, 1.2.3)
...

Make sure you uninstall all the gems with version number 2.0.2.9216:

sudo gem uninstall rails
sudo gem uninstall actionmailer
sudo gem uninstall actionpack
sudo gem uninstall activerecord
sudo gem uninstall activeresource
sudo gem uninstall activesupport
sudo gem uninstall rails

In each of the above commands the gem package manager should ask you to select the one you want to uninstall.
Pick the one with the 2.0.2.9216 (or other version later than 2.0.2).

At the end if you list the gems again you should only have gems going up to version 2.0.2

An extra step I had to take for making the migrations work was to install rake again:

sudo gem install rake

After all these my installation seems to be working fine again.

Regular expression checking of landline/mobile UK numbers in Ruby on Rails

Problem
You want to have validations for phone numbers in Ruby on Rails code.

Solution
The mobile numbers in UK should start with a 0, followed by 7, then a number between 5 and 9, and finally another 8 numbers.
For the landline numbers in UK the number should start with 0, followed by either 1 and 8 or 9 digits, or by 2 or 3 and then 9 digits.
So in order to use a regular expression in your validations, you could use something like the following in your model:

case phone_no_type

  when 'mobile'

    if phone_no !~ /\A(([0][7][5-9])(\d{8}))\Z/

      errors.add('Mobile number")

    end

  when 'landline'

    if phone_no !~ /\A([0])((([1])(\d{8,9}))|(([2-3])(\d{9})))\Z/

      errors.add('Landline number')

    end

  end

Red Box progress indicator with active_scaffold_upload branch

Problem
You need to display a splash screen when uploading files to a Ruby on Rails application.

Solution
My model:

class Number < ActiveRecord::Base
  file_column :intro
  file_column :vmail
end

The steps I have followed.

  1. Install redbox plugin from project path run:
    ./script/plugin install svn://rubyforge.org/var/svn/ambroseplugins/redbox
  2. If files redbox.js, redbox.css and redbox_spinner.gif haven’t been copied over to the public folders copy them over manually or go to vendor/plugins/redbox and run:
    rake update_scripts
  3. Find an animated gif for the progress indicator to be used (ie pleasewait.gif) and copy it over to public/images.
  4. In order to be able to use the progress indicator in different parts of the application, add the following to the app/views/layouts/ :
    application.rhtml
                 <%= stylesheet_link_tag 'redbox' %>
                <%= javascript_include_tag 'redbox' %>

    near the place where <= javascript_include_tag :default > is located.
    Also at the bottom of the page create the content of the redbox:

    <p id="redbox" style="display: none"> </p>
    
    <p style="color: blue"> Please wait ....
    
    Uploading files
    
    <img src="/images/pleasewait.gif" width="200" />
    
  5. Copy _update_form.rhtml, update_form.rhtml and update.rjs from vendor/plugins/active_scaffold_upload/frontends/default/views/ to the app/views/numbers (model you want to use).
  6. To display the redbox in the numbers/_update_form.rhtml add the following in the submit_tag:
     , :onClick => "return RedBox.showInline('redbox') " %>
  7. To close the redbox after the uploading was successful, add the following in numbers/update.rjs as the first line inside controller.send :successful? clause:
    page.RedBox.close()

Ruby On Rails on CentOS 4.6

Problem
Installing Ruby on Rails on CentOS 4.6.
The yum install ruby installs an old version of Ruby 1.8.1, but you want 1.8.6
Solution
Based on a script from uberdose

The original post is here:
http://wp.uberdose.com/2007/07/15/ruby-on-rails-on-centos-45/

  wget ftp://ftp.gnu.org/gnu/readline/readline-5.1.tar.gz
  tar xvfz readline-5.1.tar.gz
  cd readline-5.1
  ./configure --prefix=/usr/local
  make
  sudo make install

  cd ..
  wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6.tar.gz
  tar xvfz ruby-1.8.6.tar.gz
  cd ruby-1.8.6
  ./configure --prefix=/usr/local --enable-pthread --with-readline-dir=/usr/local --enable-shared
  make
  sudo make install

  cd ..
  wget http://rubyforge.org/frs/download.php/20980/rubygems-0.9.4.tgz
  tar xvfz rubygems-0.9.4
  cd rubygems-0.9.4
  sudo /usr/local/bin/ruby setup.rb
  cd ..
  sudo gem install rails --include-dependencies
  sudo gem install termios --include-dependencies
  sudo gem install mongrel --include-dependencies
  sudo gem install mongrel-cluster --include-dependencies
  sudo gem install capistrano --include-dependencies
  sudo gem install mysql -- --with-mysql-dir=/usr/

Using older Capistrano version 1.x after upgrading to Capistrano 2.x

Problem
You have just upgraded your Capistrano installation to version 2.x, but you didn’t have time to convert your recipes to the newer version.

Solution
In order to be able to use your old recipes of Capistrano version 1.x after upgrading, you can use the following (assuming your version 1.x is 1.4.1):

cap _1.4.1_ deploy

or, if you have migrations you want to use:

cap _1.4.1_ deploy_with_migrations

using authentication with acts_as_authenticated

Problem
You want to use the easiest authentication method, in order to add users/permissions to your application.

Solution

  1. Install the act_as_authenticated plugin:
    script/plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_authenticated
  2. Generate controllers, models and migration:
    script/generate authenticated user account
  3. Add necessary user foreign keys in appropriate tables (ie customer in xxx_create_users.rb), plus other fields you may want to use in your user table (ie role):
    create table "users", :force => true do |t|
      t.column :login, :string
      ...
      t.column :role, :string, :default => 'C'
      ...
      end
      add_column :customers, :user_id, :integer
      ...
      def self.down
        ...
        remove_column :customers, :user_id
      end
  4. Run the migration:
    rake db:migrate VERSION=xxx
  5. Comment out from app/controllers/account_controller.rb the following:
    include AuthenticatedSystem
  6. Add it in the app/controllers/application.rb just under the class declaration.
  7. Add in application.rb (same as above) the following just after the session section:
    before_filter :login_required, :except => [:login, :signup, :logout]
  8. Comment out the default redirection after login and put your own (ie customers): in the account_controller.rb, just before
    the flash[:notice] = “Logged in successfully”.
    Also add the else for the the invalid login:

      redirect_back_or_default(:controller => 'customers', :action => 'list')
      flash[:notice] = "Logged in successfully"
    else
      flash[:notice] = "Invalid Login/Password!"
  9. Change the action in the signup and logout functions in the account_controller.rb file from index to login
  10. Add (optionally) more fields (role) in the signup page (app/views/account/signup.rhtml):
    
    
    
    <%= f.select :role, ['A','R','C'] %>
  11. Add restrictions for displaying records depending on user logged in, by using the conditions_for_collection of the activescaffold plugin in app/controllers/customers_controller.rb:
    def conditions_for_collection
      ['customers.user_id = (?)', current_user.id]
    end
  12. Add a menu page layout in app/views/layouts/_menu.rhtml:
  13. Add the call to the menu partial in the app/views/layouts/application.rhtml, just before the div with id=main :
    <%= render :partial => "layouts/menu"%>

Keeping uploaded files between deployments

Problem
You are using file_column plugin (or maybe another plugin?), to upload files in your ruby on rails application. Because the files are big you don’t want to have a different copy stored in your subversion repository for each different deployment version. You want to keep a common folder with all your uploaded files, and use it with every different deployment version.

Solution
For the example, we will have a numbers table that has two file_column uploadable columns (intro,voice_mail), with the following migration:

class CreateNumbers < ActiveRecord::Migration
  def self.up
    create_table :numbers do |t|
      t.column :customer_id, :int, :null => false
      t.column :phone_no, :string, :null => false
      t.column :intro, :string
      t.column :vmail, :string
      t.column :created_at, :datetime
      t.column :updated_at, :datetime
    end

  def self.down
    drop_table :numbers
  end
end
  1. If you already have used cap deploy or cap setup you should have a shared folder in your deployment server.
    You should copy the intro and vmail folders that should be located on your public/number folder on your local development client, on a folder called number in your development server in your shared folder.
  2. Create a file in your local pc in lib/cap_recipes.rb:
    Capistrano.configuration(:must_exist).load do
    
      desc "Keep generated uploaded files between deployments"
        task :after_symlink do
           run "rm -drf #{deploy_to}/#{current_dir}/public/number"
           sudo "ln -nfs #{shared_path}/number #{deploy_to}/#{current_dir}/public"
        end
      end

    Be careful with the naming of the task as (at least for capistrano 1.4 that I’m using), it must have a special name as after_symlink.
    Also be careful that if you try to use before_symlink, it won’t work as the current symlink won’t be setup.

  3. In your config/deploy.rb file add at the top the following:
    require 'lib/cap_recipes'
  4. Now you should be ready to deploy your new version so:
    svn -m "added customised capistrano recipes" commit

    make sure that you check in your version in subversion, and then:

    cap deploy

    you should be able to see a link in your current/public folder called number that points to the shared/number folder that hold all the uploaded files.

Adding icons to ActiveScaffold’s actions

Problem
You want to replace the standard text descriptions in ActiveScaffold’s actions with your icons.

Solution

  1. Create a file called active_scaffold_overrides.css in ror_project/public/stylesheets
  2. Copy the css code from ror_project/vendor/plugins/active_scaffold/frontends/default/stylesheets/stylesheet.css and paste it in to the file created in the previous step.
  3. Create a directory my_images in ror_project/public/images/activescaffold to hold your images.
  4. Copy to the new directory the images you want to use in the application.
  5. In the active_scaffold_overrides.css file find the section named:
    /* Table :: Actions (Edit,Delete) .... */

    and for each action that you want to use an icon add (ie edit)

    .active_scaffold tr.record td.actions a.edit {
        display:     block;
        width:        16px;
        height:       16px;
        background: transparent url(../../../images/active_scaffold/my_images/image.png) no-repeat right 50%;
    }
  6. In the application.rb, if you want the links to be the same for the whole application add:
    ActiveScaffold.set_defaults do |config|
        config.update.link.label =""
    end
  7. in your layout/application.rhtml (create one if you don’t already have one), include
    <%= stylesheet_link_tag "active_scaffold_overrides" %>
  8. Restart webrick/mongrel