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
to
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 svn.techno-weenie.net/projects/plugins/acts_as_authenticated
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
:adapter:
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 -% >
< %= text_field_tag 'login' % >
< %= password_field_tag 'password' % >
< %= submit_tag ' Log on ' % >
< % 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.