rod mclaughlin


This is how I ported this app from Merb to Rails

  • Rename all controllers in app/controllers to Rails-style names, eg. articles.rb -> articles_controller.rb - application.rb -> application_controller.rb - exceptions -> exceptions_controller.rb (I can never get the rule when to pluralize and when not to...)
  • Make controllers subclasses of ApplicationController
    eg. class ArticlesController < ApplicationController
  • Put this at the top of application_controller.rb:
    class ApplicationController < ActionController::Base
  • In the app/helpers folder, create application_helper.rb, containing:
    module ApplicationHelper end
  • Make all the helpers simple modules, like this, deleting references to Merb:
    module ArticlesHelper ... end
  • Delete file app/helpers/global_helpers.rb
  • In the app/models folder, change the definition of the models, like this:
    class Article include DataMapper::Resource
    class Article < ActiveRecord::Base
    except for those models which aren't linked to a database table - just leave

    class Foobar

    as it is.
  • Remove the 'property' declarations at the top of the model classes, eg.
    property :id, Serial
    (What were the Merb team thinking? HOW did they think they could challenge the almighty Ruby on Rails, the true way and the light unto the nations?).
  • If you are using acts_as_authenticated or restful_auth for user accounts, you need to install it in vendor and lib, change the User model and add account_controller.rb to your controllers. The top of user.rb should look something like this:
    require 'digest/sha1' class User < ActiveRecord::Base attr_accessor :password validates_presence_of :login def self.authenticate(login, password) u = find_by_login(login) u && u.authenticated?(password) and (u.approved) ? u : nil end ...
    Create folder lib/
    Get files authenticated_system.rb and authenticated_test_helper.rb from acts_as_authenticated and put them in lib/ (I got them from the lib/ folder in another Rails app).
    Create folder vendor/plugins/
    Copy 'acts_as_authenticated' into it, or install it in the normal way from
  • Delete folder merb/
  • Create folder db/migrate, and in it create file 20091021000000_create_users.rb or something like that, which looks like this
    class CreateUsers < ActiveRecord::Migration def self.up create_table "users", :force => true do |t| t.column :login, :string t.column :crypted_password, :string, :limit => 40 t.column :salt, :string, :limit => 40 t.column :created_at, :datetime t.column :updated_at, :datetime t.column :remember_token, :string t.column :remember_token_expires_at, :datetime end end def self.down drop_table "users" end end
    You can go into production database, nuke table 'users', and try to recreate it with the above migration.
    mysql> DROP TABLE IF EXISTS `users`; bash-$ rake db:migrate RAILS_ENV=production

    However, I did it the hard way:
    $ mysqldump -u root -p my_dbdevelopment > db.sql mysql> DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `id` int(11) NOT NULL auto_increment, `login` varchar(50) default NULL, `crypted_password` varchar(50) default NULL, `salt` varchar(50) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; LOCK TABLES `users` WRITE; INSERT INTO `users` VALUES (1,'administrator','cc4841732d87529efda30b400d58d0245af74c45', '9f98ab483f230ff2bfcd304318105c32c77814af'); UNLOCK TABLES;
  • Remove the contents of folder 'schema'
  • Remove folder 'autotest'
  • Remove folder spec
  • Create folders test/functional, test/fixtures and test/unit, and file test/test_helper.rb:
    ENV["RAILS_ENV"] = "test" require File.expand_path(File.dirname(__FILE__) + "/../config/environment") require 'test_help' class ActiveSupport::TestCase include AuthenticatedTestHelper fixtures :all end
  • Remove folder 'tasks'
  • Copy the whole of folder 'script' from a Rails app into your top level folder
  • Delete everything from folder 'config' except file database.yml
  • Copy everything except database.yml from the config folder of another Rails app into config
  • Make sure config/routes.rb is correct (how's that for precise instructions?)
    My routes.rb ended up looking like this:
    ActionController::Routing::Routes.draw do |map| map.root :controller => 'main' map.resources :articles map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end
    Your routes may vary.
  • In config/database.yml, remove the colons at the beginning of words like
    but leave all the other colons, so 'database.yml' ends up like this:
    development: adapter: mysql database: foobar_development username: root password: notverystrong host: localhost ...
  • Remove unused files in config/initializers - I had to remove some files from the Rails app I had copied the contents of 'config' from - you should end up with inflections.rb, mime_types.rb and new_rails_defaults.rb

    Then try starting the application:

    $ script/server &

    I then had a few errors deriving from legacy code in controllers, eg. referring to a class called Application instead of ApplicationControllers...

    Next, I had to remove some cude Merb code in controllers that looked like this:
    # Show static pages like spec.html.erb def main @pages = [] display @pages end
    and replace it with boring old Rails code:
    def main end
  • You may have some Merb lying around in your html.erb files like this:
    < % if session.user % >
    If so, replace it with a method in a helper, eg. application_helper:
    def admin (defined? current_user) and (not current_user.nil?) and current_user != :false and current_user.login == 'theman' end
    'current_user' is how acts_as_authenticated does it. You may have other ideas.
  • You will need to create folder app/views/account/ and create 'login.html.erb' in it. login.html.erb looks like this: < % form_tag do -% > <p><label for="login">Login</label><br/> < %= text_field_tag 'login' % ></p> <p><label for="password">Password</label><br/> < %= password_field_tag 'password' % ></p> <p>< %= submit_tag ' Log on ' % ></p> < % end -% >
  • If you have < %= form_for(@article, :action => resource(:articles) ) do % > change it to < % form_for(@article) do |f| % > and if you have < %= text_area :body, :cols => "70", :rows => "30" % > it should be < %= f.text_area :body, :cols => "70", :rows => "30" % > and of course < % end =% > should be < % end % > Are we having fun yet?
  • You may also find code like this:
    <%= link_to 'Edit', resource(@article, :edit), :class => 'edit' %>
    change it to
    <%= link_to 'Edit', articles_path %>
    If you have any files in the app/views/layout folder, they might contain something like this:
    < %#= message[:notice] % > < %= catch_content :for_layout % >
    That's the hip, trendy, Merb way of doing it. In Rails, it's
    < %= flash[:notice] % > < %= yield % >
    and by the way, it should be app/views/LAYOUTS, not app/views/LAYOUT. It took me two hours to figure that out. Thanks, Merb, for changing 'layouts' to 'layout'. That was a really good idea. Cool.

    Well, maybe I was being a bit sarcastic. Merb's CSS is pretty good. I'm sure Our Lord will find these guys something useful to do up in Rails Heaven.

    Having done all the above, your app will work perfectly. Guaranteed.

    I'm joking about Rails being boring. I think the Merb-heads are elitist hipsters from South of Market, and I'm glad they've been disappeared. And they have unpronounceable names like Yargonovochavoskyovitch too. However, they did give me a way of showing my mastery of Ruby, by enabling me to create an app in their fancy framework, Merb, and port it to the vastly superior and much better documented framework, Rails, the light of the nations, champion of the people, and killer app of the millenium.

Portland London