Ruby on Railsで延々作るTwitterもどき

Ruby on Railsで10分で作るTwitterもどきに触発されて、Ruby on RailsTwitterもどきを作ってみることにしました。
が、実はRailsは初。どう考えても10分じゃ無理なので、ゆっくり作っていくことにします。
作成過程はちょっとずつここで書いていく予定。


一応作ったものはオープンソースということで随時晒していくつもりです。
が、ろくに本も持っていないので、全てWebの情報だけが頼りですが、これで果たしてどこまでできるか…。


とりあえず形から入るべく、名前だけ決めておきます。
独り言をつらつら書くということで、「monologue」。
せっかくなので、ロゴもお絵描き。

とりあえず基本設定

作業環境はMac OS X 10.5を使います。rubyはもちろん、なんとrails標準インストール済み(ただしver1.2.6)。
というわけで、さっそく作成開始です。まずは、railsの開発環境を生成。

% rails monologue
      create  
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      create  config/environments
      create  components
      create  db
...

コマンド一つでいろいろ出来上がり。ディレクトリ構成は、

ディレクト 内容
app/controllers コントローラ
app/helpers ヘルパークラス
app/models モデル
app/views ビュー
config アプリケーションの設定
db DB用のファイルが入る
db/migrate migration用ファイル。DBを自動で作ってくれるetc.
doc ドキュメント(READMEとか。多分しばらく書かないが^^;)
lib ライブラリ?
log ログ
public Webサーバの公開フォルダ
public/images 画像ファイル
public/javascripts JavaScript (.jsファイル)
public/stylesheets スタイルシート (.cssファイル)
test ユニットテスト(これも最初は書かない… *1 )
script スクリプトなど。Webサーバもここに入っている
vendor/plugin プラグインなど

という感じらしい。


DBとしては最近は sqlite がデフォルトなので、何の設定もいりません。が、MySQLを使う場合は以下の設定を書き換えます。

config/database.yml の

   adapter: sqlite3
   database: db/production.sqlite3
   timeout: 5000

となっている部分(3カ所)を全て、

   adapter: mysql
   username: monologue
   password: ******
   database: monologue
   socket: /tmp/mysql.sock

と変更。MySQL側でもDBとユーザを作ります。日本語を使いたいので、utf8を文字コードとして指定しておきます。

mysql> create database monologue default character set utf8;

このときユーザ設定(権限の設定)もしておきます(詳細略)。

とりあえずサーバを起動してみます。

% cd monologue
% script/server
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
...

この状態で http://localhost:3000/ にアクセスしてみると、Railsのロゴと Welcome aboard / You’re riding the Rails! というメッセージが。これで、いよいよ中身を作っていきます。

*1:Test Drivenで書くのが良いのは分かってるのですが、そもそもRoRそのものの理解が先なので…。

DB設計

まずはDB設計から。といっても簡単に。Railsなら後から変更も楽に違いない(思い込み)。

┌──────────┐   ┌────────┐
│User        │n⇔n│Follow      │
│──────────│   │────────│
│名前、パスワード、 │   │user_id       │
│プロフィール、設定、│   │ followee_id  │
│などなど…     │   └────────┘
└──────────┘
  1
  ↓
  n
┌──────────┐
│Status       │
│──────────│
│user_id      │
│発言内容      │
└──────────┘

なんか崩れてるが心の目で見てください。

User:ユーザ情報を管理。ログイン等もこの情報をもとに行う。
Status: ユーザの発言を管理するテーブル。複数の発言が特定のユーザに属する(1:nの関係)
Follower: 特定のユーザがFollowしているユーザ(Follower)、あるいは逆にFollowされているユーザ(Followee)を関連づけるテーブル。


Railsでは普通全てのテーブルの各エントリにID (integer)をつけて管理するようなので、テーブル間の関連はそのIDで示します。


で、こんだけ書いておいて何ですが、まずはFollowerは抜きの、単なる独り言サイト(ユーザが独り言を書き込むだけのモノ)を作り、後からFollow機能を入れていくという方針にしようと思います。

ユーザ認証用のプラグインの導入とテーブルの生成

普通なら、ここでDBにテーブルを作ってしまうか、テーブル生成用のmigrationを書くのでしょうが、今回はユーザ認証のシステムを作る必要があるため、まずはプラグインを入れておきます。restful_authenticationというのがあるらしいのですが、今回Rails自体のバージョンが古いため、代わりに古い acts_as_authenticated を導入します。

プラグインの導入

といってもコマンドはまた一行だけ。

% script/plugin install acts_as_authenticated

すると、自動的に必要なものをダウンロードして vendor/plugins 以下にプラグインを導入してくれます。
README的なメッセージも現れます。

Userモデルの自動生成

表示された説明に従って、このままユーザを管理するためのモデルやコントローラ、ビューも生成してしまいます。

% script/generate authenticated user account

このscript/generateは、いろんなファイルを自動生成してくれるスクリプトで、RoRが高速開発ができるための肝です。script/generate 単体で実行すると、生成できるものの種類が分かります。なお今回プラグインを入れたため、authenticatedが追加されています。

今回は上記のコマンドで、userという名前のモデル(≒DBにアクセスするクラス)とaccountというコントローラ(≒ロジック部分)が自動的に作られます。

アプリケーション全体への認証システムの適用

ここで、app/controllers/application.rb 内に

class ApplicationController < ActionController::Base
  include AuthenticatedSystem        # 追記
  before_filter :login_from_cookie   # 追記

の二行を書き加えておくと、導入した認証システムをアプリケーション内のどこでも使えるようになります。

Usersテーブルの作成

しかしまだ肝心のDB上のテーブルが出来ていませんから、作る必要があります。

migrationファイルの確認

RoRではmigrationという仕組みを使ってテーブルを作成することができます。これを使うようにしておくと、後々テーブル構造の変更時にも便利とのこと。具体的には、db/migrate/00n_xxx.rb (00nは連番)というファイルに、DBを作るためのスクリプトを書き、rakeコマンドを実行すればOKです。


実は先ほどUserモデルを作ったときにUser用のmigrationファイルも自動生成されています。db/migrate/001_create_users.rb です。内容は下のような感じ。

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table "users", :force => true do |t|
      t.column :login,                     :string
      t.column :email,                     :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

upメソッドがテーブルを作るメソッド、downが消すメソッドですね。
テーブルの名前は、モデルクラスの名前(User)を複数形にした users とするのがRails流らしいです。この対応付けはRails内部が自動で行うため、この規約に従う限り、ユーザが明示的に名前を設定する必要がなくなっています。

カラム(フィールド)の追加

さて、せっかくなので、usersテーブルに自己紹介を記述するカラムを追加してみます。upメソッド内のテーブル作成メソッド create_table 内の適当なところに、真似して

      t.column :profile,                     :text

と書き加えます。ちなみに string はMySQLのVARCHAR(255)に対応する型なので、255byteまでしか入りません(UTF8なので日本語だと80文字ちょっと)。:string :limit => 40ならVARCHAR(40)。一方、:textや:binaryなら任意長です。ちなみに数字は :integer、日付&時刻は :datetime、など。

テーブルの自動生成

こうしておいて、

% rake db:migrate

を実行すると、勝手にテーブルを生成してくれます。rakeコマンドは、ruby版のmakeコマンドです。

Userモデルやコントローラはは全く触ってませんが、RailsがDBのテーブルに合わせて動的にメソッドを作ってくれるので、いまのところ変更の必要はありません。

サーバの起動とユーザ認証のテスト

ここまでで、

% script/server

を実行してサーバを立ち上げ、http://127.0.0.1:3000/account/signup で新規ユーザ作成ができます。 http://127.0.0.1:3000/account/login にアクセスすると、ログイン画面が出ます。
現在、何も作っていないので、ログインすると謎のポエムが出現します。ログアウトしても出ます…。まあ、この辺の見た目(ビュー)は後々変更していきます。

URLの意味

http://127.0.0.1:3000/account/login にアクセスするときには、app/controllers/account_controller.rb 内のロジックが実行されます。メソッド名はlogin。そして、app/views/account/login.rhtml のビューの内容をもとにページをレンダリングしています。
account_controller のなかでは、Userというクラスを使ってユーザ情報にアクセスしていますが、このクラスの定義はapp/models/user.rb にあります。テーブル名やフィールド名については全く定義されていない(ただしvalidation(フィールド内容チェック)などは自動生成されている)のですが、名前を複数形にしたusersテーブルにアクセスし、動的にフィールド名は取得してくれています。
こうやって、URLや名前を対応付けることで設定を省いている、と*1

*1:URLとの関連付けは、config/routes.rbで設定されています。

発言管理用のテーブル&モデルを作成

ユーザ管理テーブルではいきなり変則的なモデルの作り方をしてしまいましたが、次は「普通」に発言を管理するStatusテーブルを作ってみます。

まず、次のコマンドを打ち込んでmodelとmigrationのファイルを自動生成します。

% script/generate model status
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/status.rb
      create  test/unit/status_test.rb
      create  test/fixtures/statuses.yml
      exists  db/migrate
      create  db/migrate/002_create_statuses.rb

そして、生成された db/migrate/002_create_statuses.rb を編集し、Statusesテーブルに必要なカラムを書き加えます。

class CreateStatuses < ActiveRecord::Migration
  def self.up
    create_table :statuses do |t|
      t.column :user_id,  :integer                           #ここから追記
      t.column :status,    :text
      t.column :created_at,                :datetime
      t.column :updated_at,                :datetime         #ここまで
    end
  end

  def self.down
    drop_table :statuses
  end
end

user_idはユーザ管理テーブルとの関連用、statusが発言内容を格納するカラムです。user_id という名称には「Userクラスのidをキーとして関連する」という意味があります。また、created_at、updated_at というのはRailsでは特殊な意味があり、エントリの作成日時/更新日時を自動的に保存してくれるというものです。

以上を追記した後、

% rake db.migrate

を実行すると、statusesテーブルが生成されます。


次に、User - 1:n -> Status という関連を示すために、モデル部分に追記を行います。

app/models/status.rb に次のように belongs_to メソッドを追記し、userと関連することを示します。

class Status < ActiveRecord::Base
  belongs_to :user    # 追記
end

逆に、app/models/user.rb には次のように has_many メソッドを追記します。

class User < ActiveRecord::Base
  has_many :statuses, :dependent => :destroy     #追記
...

認証用に自動生成したので既にいろいろ入っていますが、適当な場所に書きます。

なお、belongs_to のあとは単数系、has_many のあとは複数形で書きます。英語的に読むと自然ですが、ちょっとややこしい…。また、 :dependent => :destroy と書いておくと、Userを削除した際に、関連するStatus(es)も削除してくれます(デフォルトでは残ってしまう)。


とりあえず、ここまでで各ユーザが発言した内容(複数)を管理するためのモデルが出来上がりました。


理解すべきことは非常にたくさんありますが、多分まだ10行ちょっとしか書いてません。
でも、まだ発言の追加・削除はもちろん、表示も出来ません*1。というわけで、次はコントローラ、ビューを作っていきます。

ここまでのソース

monologue_000.tar.bz2

*1:ActiveScaffold(もっといろいろ自動生成)を使っていれば、この辺りで一連の機能はできてしまっているのかも…。

Userコントローラの作成

まずは、ログイン時の謎のポエムをなんとかしましょう。

Userコントローラの自動生成

ユーザの情報を表示するためのコントローラとして、userコントローラというのを作ることにします(userモデルと名前を一致させておきます)。例によってscript/generateで自動生成します。

% script/generate controller user

生成されたもののうち、app/controllers/user_controller.rb がコントローラの定義です。まだ中身は空っぽ。

class UserController < ApplicationController
end

ここに、ユーザの情報(名前とか発言内容とか)を表示を行うためのメソッドを書いていきます。


コントローラのリファレンスはここ(日本語、UTF-8)とかここ(英語)にありますので、必要に応じて参照しながら書いていきます。

indexメソッドの記述

まず、ユーザの情報を表示する index メソッドを作ります。
http://localhost:3000/user/?id=NeoCat
もしくは
http://localhost:3000/user/index/NeoCat
のようにユーザのログイン名が指定された場合にはそのユーザの情報を表示し、
http://localhost:3000/user/
指定なしだとログイン中のユーザを表示する、という感じにしてみます。

URLのコントローラ名の後に何も指定されなかった場合、indexメソッドが呼ばれます。そこで、下記のメソッドをUserControllerに加えます。

class UserController < ApplicationController
  def index
    redirect_to(:controller => :account, :action => :login) and return if !logged_in?

    if params[:id]
      @user = User.find_by_login(params[:id])
      render :text => "not found" and return unless @user
    else
      @user = current_user
    end
  end
end

コントローラでやることはこれだけです。実際の表示するものの指定はビューの中でやりますので、ここではロジック部分のみを書きます。

中身の説明

まず、ユーザがログイン中であるかを確認し、ログインしていなかった場合は account/login にリダイレクトさせます。and returnはここでメソッドの処理を終わらせるためです。


次に、ビューに表示すべきユーザを渡すための処理を行います。@つきの変数は、ビューの内部でもアクセスできるようになります。ここでは@userを使って、ユーザ情報を渡します。


if文に出てくる params は渡された情報を示すハッシュです。params[;id]には http://localhost:3000/user/index/NeoCat のようにアクセスされた場合、NeoCatが入ります。URLの末尾に ?id=NeoCat と指定された場合も同じです。

この指定があれば、それをログイン名に持つユーザを検索します(idっていう名前はちょっと変だが)。User.find_by_loginというメソッドはフィールド名からRailsが自動生成したもので、文字通り引数に指定されたlogin名を持つユーザをusersテーブルから一人検索してくれます。この仕掛けはActiveRecordというもので、O/Rマッピングを提供してくれます。find*についてはid:elm200:20070316:1174044163あたりにいろいろな書き方が載ってます。

見つからなかった場合はnilになりますので、render_to メソッドを使って "not found"という文字をレンダリングし、処理を中止します。この場合ビューは呼び出されません。


idが指定されていなかった場合は、current_userを代入しておきます。current_userにはログイン中のユーザがいればUserクラスのインスタンスが代入されています。


renderもredirect_toも指定せずにメソッドを抜けると、自動的に app/views/user/index.rhtml の内容がレンダリング対象になります(userはコントローラ名、indexはメソッド名)。とりあえずこのファイルに

<%= @user.login %> 

とだけ書いて、ログイン名だけを表示するようにしておきます。

accountコントローラの変更

なお、ログイン後にポエムがでるのは、app/controllers/account_controller.rbの中で account/index にリダイレクトしているためです。これを、今作った user/index に飛ばすようにしましょう。
同ファイルの以下の部分を変更します。3カ所くらいあります。

      redirect_back_or_default(:controller => '/account', :action => 'index')
                                              ↓
      redirect_back_or_default(:controller => '/user', :action => 'index')

また念のため、ポエムをレンダリングしている本体であるaccount_controller.rbのindexメソッドを書き換えて

  def index
    if logged_in?
      redirect_to(:controller => '/user', :action => 'index')
    else
      if User.count > 0
        redirect_to(:action => 'login')
      else
        redirect_to(:action => 'signup')
      end
    end
  end

のように、適当な場所にリダイレクトするようにしておきます。
これでもうポエムの入っている views/account/index.rhtml は不要なので、消してしまいましょう。:-P

動作テストしてみる

これで、ログインしてみたり http://localhost:3000/user/http://localhost:3000/user/index/ユーザ名 にアクセスしてみると、上記の動作を試すことが出来ます。


次に、もうちょっとちゃんとビューの中身を作っていきます。

全体レイアウトを作る

先ほど生成されたビューを見てみると、本当にユーザ名しか書かれておらず、〜などの基本的な構造すら入っていないのが分かります。しかし、これからビューを増やしていくことを考えると、いちいち全てのビューに同じことを書いていくのは大変です。

そこで、Railsではlayoutという仕組みを用意しています。詳しくはこことかここ 辺りに。


今回は、アプリケーション全体に適用するレイアウトを書いてみます。場所は app/views/layouts/application.rhtml 。
スタイルシートとか、共通で使うJavaScriptもここに書くと良いでしょう。例えば

<html>
<head>
  <title><%= @title %></title>
  <%= stylesheet_link_tag('monologue') %>
</head>
<body>
<div id="subpage">
<%= link_to image_tag("monologue.png", :align => 'left', :id => 'logo'), "/" %>
<br style="clear:both">

<%= @content_for_layout %>

</div>
</body>
</html>  

とか。


ちなみに <%= 〜 %> や <% 〜 %> はerbの表記です。〜にはrubyの命令を埋め込めます。前者は結果をHTML内に出力し、後者は出力しません。後者はループやif文などの制御構造を書くためにも使えます。


image_tag はimgタグの生成。public/stylesheets/images/ 内においたファイルへのimgタグを生成します。
stylesheet_link_tag は、public/stylesheets/ においたcssファイルへのlinkタグを生成するメソッドです。
JavaScriptの場合も、javascript_include_tag メソッドで、 public/javascripts/ 内のファイルを呼び出すscriptタグが生成できます。


今回はロゴの画像を配置するとともに、monologue.cssという全体に適用するスタイルシートへのリンクを張っています。

ユーザ情報のビューを作成

app/views/index.rhtml を編集し、次のようにします。ログインした状態で http://localhost:3000/user/ を見ながら、どんどん書いていきます。発言内容のフォームもまだ機能しませんが、書きます。

<div id="left">

<!--表示対象のユーザがログイン中のユーザの場合のみ、発言用のフィールドを表示-->
<% if current_user == @user %>
  <div id="update_status">
  <p><% form_for :status, :url => { :controller => :status, :action => :new } do |f| %>
    <p><label for="status">めっせーじ?<small>(140文字以内)</small></label><br>
    <%= f.text_area :status, :cols => 70, :rows => 4 %><br>
    <%= submit_tag "送信" %></p>
  <% end %></p>
  </div>
<% end %>
<!--ここまで-->

<b><hr></b>


<!--対象ユーザの過去の発言内容を表示-->
<% @user.statuses.reverse.each do |s| %>
<%= image_tag('person.png', :size => "32x32", :id => "user_icon", :align => "left") %>
<strong><%= @user.login %></strong> <%= s.status%> <small>(<%= s.updated_at,to_s %>)</small>

<hr style="clear:left">
<% end %>

</div>
<!--ここまで-->

<div id="right">

<!--ユーザ情報の表示-->
<%= image_tag('person.png', :size => "64x64", :id => "user_icon") %>
<strong><%= h @user.login %></strong><br>
<%= link_to(image_tag("mail.png"), "mailto:" + h(@user.email)) %><br>
<b>プロフィール:</b> <%= h @user.profile %>
<hr>
<!--ここまで-->


</div>

全体構成

二つのdivから成り立っています。
id="left"の方は左側に表示する大きめの枠で、発言用のボックスや、過去の発言が入る枠。
id="right"は右側の小さな枠で、ユーザのプロフィールなどの情報などを表示する枠。

発言用のフィールド

発言用のフィールドは、自動生成されたログイン用のフォームを物まねして、とりあえず書いておきます。コントローラを書いていないので、今のところ送信してもエラーになるだけです。
form_forの使い方はこの辺を参考に。モデルの新しいインスタンスを作るときに使うと良いようです。

過去の発言

ここでは、対象ユーザの過去の発言を @user.statuses で取得し、その内容を逆順に表示しています。user.statuses なんて定義したっけ?と思われるかもしれませんが、モデル作成時にUserモデルにhas_many: :statuses を書いておいたことで自動生成されています。自動的にStatusのuser_idが @user.id と一致するものを検索してくれます。発言時刻はRailsがupdated_atとかcreated_atに記録してくれているので、それを参照すればOK。よくできてるなあ。

ユーザ情報

@userのプロフィールなどを表示しています。ここが一番シンプル。

見た目はCSS

あわせて、ユーザアイコンの画像を配置したり、CSSを適宜書いておきます。以上で、見た目的には下のような感じになりました。


ここまでのソース

monologue_001.tar.bz2

flashを表示できるようにする

AdobeFlashではなくて、ページをリダイレクトしたときにメッセージを伝達する仕組みがflash
この辺が詳しい。


実は既に flash[:notice] = "You're logged in" とかいった設定がaccountコントローラ内で自動生成されています。
これを表示するようにしてみます。


どうせなら、全ページにLayoutを使って埋め込んでしまいましょう。ついでに、しばらく放っておくと消えるようにしておけば、全ページに埋め込んでもデザイン上邪魔にならないでしょう。


app/views/layouts/applications.rhtml に、以下を書き加えます。

<% if flash[:notice] %>
<div id="notice"><%= flash[:notice] %><% flash[:notice] = nil %></div>
<script>
var d_notice = document.getElementById('notice');
function setNoticeAlpha(a){
	if (a>0) {
		d_notice.style.opacity=a;
		setTimeout(function(){setNoticeAlpha(a-0.1)},100);
	} else
	 d_notice.style.display = "none";
}
setTimeout(function(){setNoticeAlpha(1.0)}, 2000)</script>
<% end %>

スタイルシートに以下を加え、適当な右上辺りの場所に固定しておきます。

#notice {
	position: absolute;
	right: 20px;
	top: 18px;
	width: 340px;
	margin: 0 auto;
	border: solid 2px #222;
	background-color: #fce;
	text-align: center;
	font-size: 14pt;
	line-height: 20pt;
	z-index: 999;
}

ログインしたときの画面。flash表示は2秒後に、徐々に消えていきます。

Statusコントローラを書く

Userのindexビューに発言用のフォームを作ったので、これを受理して発言をユーザに追加登録するコントローラを書きましょう。

まず、コントローラのひな形をgenerateします。

% script/generate controller status

そして、app/controllers/status_controller.rb を以下のように編集します。

class StatusController < ApplicationController
  def new
    if logged_in? && request.post?
      @status = Status.new(params[:status])
      if @status
        if @status.status == ''
          redirect_to(:controller => :user, :action => 'index')
          return
        end
        begin
          current_user.statuses << @status
          flash[:notice] = "更新しました!"
        rescue
          flash[:notice] = @status ? @status.errors.full_messages : "エラー:更新に失敗しました。"
        end
      end
    end
    redirect_to(:controller => :user, :action => 'index')
  end
  
  def delete
    @status = params[:id] && Status.find(params[:id])
    if @status && @status.user == current_user
      @status.destroy
      flash[:notice] = "削除しました!"
    end
    redirect_to(:controller => :user, :action => 'index')
  rescue
    flash[:notice] = "削除できませんでした。"
    redirect_to(:controller => :user, :action => 'index')
  end
end

ついでに削除も書いておきました。「追加した」「削除した」、あるいは「できなかった」というメッセージは、先ほど追加したflashを使ってユーザにフィードバックします。

追加処理

    if logged_in? && request.post?

POSTで投稿されたときのみ受け付ける。

      @status = Status.new(params[:status])

フォームから発言内容を受け取って新規にStatusオブジェクトを作る。form_forを使った場合は、このようにいきなりオブジェクトとして取得できます。

          current_user.statuses << @status
          flash[:notice] = "更新しました!"

ちゃんと中身がある場合は、現在のユーザのステータス配列に新しい発言を追加。また、flash[:notice]でユーザに追加した旨のメッセージを返します(後述)。

削除処理

    @status = params[:id] && Status.find(params[:id])

idで渡された削除対象を取得。

    if @status && @status.user == current_user
      @status.destroy
      flash[:notice] = "削除しました!"

発言がちゃんと存在し、発言した人がログイン中のユーザの場合のみ、該当する発言を削除。追加時と同様にflash[:notice]でユーザに追加した旨のメッセージを返します(後述)。

テスト

何かをフォームに書いて送信してみると、一覧表示に追加されるハズ。
statusesをreverseしてから表示いるので、新しいものほど上にきます。

削除は、app/views/user/index.rhtml に

<% if current_user == @user %>
  <%= link_to "[x]", {:controller => :status, :action => :delete, :id => s.id}, :confirm => '本当に削除しますか?' %>
<% end %>

を書き加えておいて、[x] をクリックすればOKかな。link_to についてはリファレンスとかこの辺とかを見ながら。

デフォルトコントローラの設定

URLにいちいち user を書くのが面倒だなあという気がしてきたし、http://localhost:3000/ でアクセスできるようにしたいところです。
この設定は、config/routes.rb で行います。
もとからある「map.connect '' 〜」のコメントを外し、以下のようにデフォルトのコントローラをuserに設定します。

  map.connect '', :controller => "user"

また、public/ の中に index.html がおいてあると、こちらが優先されてしまうようなので、削除してしまいます。

これでサーバを再起動し、http://localhost:3000/ にアクセスするとユーザ情報にいきなりアクセスできます。
ログインしていない場合は、ログインページにリダイレクトされます。

ここまでのソース

monologue_002.tar.bz2