2007年10月3日水曜日

ruby misc tips

Gem での proxy 超えは http_proxy 環境変数に http://_proxy_host_:_port_ を
設定するのが良いらしい。

rake を初めてビルドツールとして使ってみる。利点は make/ant に比べて
rakefile の記述力が高いということだろうか。慣れると面白そう。
http://www2s.biglobe.ne.jp/~idesaku/sss/tech/rake/

Capistrano も気になって少し調べてみる。こちらはデプロイツールとなっている。
複数のホストにまたがる更新処理などを書きやすいということのようだ。
古い版は Rails に依存していたのでレシピファイルは config/deploy.rb だが
現行の v2.0.0 では Capfile または capfile も受け付ける。

$ gem install capistrano --include-dependencies

ssh が使えて posix shell 相当のものがデフォルト(?)の場所にあるシステム
に対していろいろと実行を指示出来るようである。

ssh が使えてというのは capistrano を実行するシステムの ssh public key が
リモートのシステムの authorized_keys に登録された状態をいう。
手順としては ssh-keygen -t dsa で private/public キーを作り、public キー
をログイン先の .ssh の authorized_keys に追加する。クライアントからは
ssh リモートホスト だけでログインできるようにしておく。一回目は known_hosts
更新があるので登録するかどうか聞かれるので、登録しておく。private キーを
暗号化した場合には ssh でリモートアクセスする際に、クライアントサイドで
private キーを使用するために暗号化に使用したパスワード(パスフレーズ?)を
聞かれる。このケースはよく試していないが capistrano からでもターミナルで
インターラクティブに実行している分には問題なさそう。

Cygwin に OpenSSH を入れれば SSH サーバとして構成できるようで (ssh-host-config
を一度実行する必要がある、また Cygwin 自体 all user 対象でインストールし、かつ
アドミン権限が必要)サービスを起動しておけば ssh で Windows マシンにログイン
できる。結局のところ Cygwin 環境にリモートで入るわけで Linux より少し
不便な環境ぐらいに思ったほうが良いだろう。

Capistrano 自体はまだまだ学習しないといけないが、task にどのホストで実行
させるかという属性がつけられる。また、単一、複数のほすとを role として
定義し、role に対して特定のタスクを実行などということもできる。
http://www.capify.org/

2007年10月2日火曜日

rails again

Linux で Ruby on Rails 環境を確保。

サービスの設定に mysqld があるので、起動してみると動いたみたい。

さて、パスワードはなんだ??? 管理ユーザは root なのか???

mysqld は --skip-grant-tables オプションつきで起動すると
権限不要モードで立ち上がる。その状態で mysql mysql で接続して
次のように root のパスワードをクリアできる。

mysql> update user set Password=null where Host='localhost' and User='root';

どうやら RedHat についてくる mysql はこの状態になっている。
(したがって上記は不要)

使える状態にするため root にパスワードを設定する。

# mysqladmin --user=root password <newpass>

なければデータベースを作る

mysql > create table test;

アプリケーション用のユーザーを作る
mysql > grant all privileges on test.* to test@localhost identified by '...';

一応、作成したユーザーでローカルアクセスできるかを確認。
$ mysql -u test -p test
Password:
mysql> show tables;

Rails のインスタンスを作成
$ rails test1

当面は development 部分だけでよいが database 設定を行う(user, password, etc)
$ vi config/database.yml

ちなみに local 接続のソケットはデフォルトが /tmp/mysql.sock になっているようなので
sock: /var/lib/mysql/mysql.sock の一行を入れて適切に変更。このパスは ps -ef | grep mysql
で見つけた。

まずはモデルの作成。

$ ruby script/generate model Book
...
create db/migrate/001_create_books.rb

db/migrate/001_create_books.rb を編集してフィールドを定義
create_table の do block 内にカラムを名前、型で定義。
これで sql を打たなくてもテーブルが作れる。

class CreateBooks < ActiveRecord::Migration
def self.up
create_table :books do |t|
t.column :isbn, :string
t.column :name, :string
t.column :author, :string
t.column :manufacturer, :string
t.column :release_on, :date
end
end

def self.down
drop_table :books
end
end



$ rake migrate
// 実はここで socket がおかしいことに気づいた。

$ rake migrate
== CreateBooks: migrating ====...
-- create_table(:books)
-> 0....
== CreateBooks: migrate (0....s) ===

The rake task migrate has been deprecated, please use the replacement
version db:migrate

メッセージは db:migrate を今後は使いなさいとのこと。

ここで rake と打つとテストをしてくれるらしいが socket のエラーで失敗する。
test 以下のファイルを眺めていると、結局 config の下のファイルに行き着く。
database.yml には test セクションがあり、そこはデフォルトのままだったので
db name, user, pass, socket をなおす。このあとは rake は動作するようになった。

あとは scaffold を Book に対して行えばとりあえず CRUD はできるようになる。

$ ruby script/generate scaffold Book

$ ruby script/server

validation の例:

$ vi app/models/book.rb

class Book < ActiveRecord::Base
protected
def validate
errors.add('isbn', 'format error') unless isbn =~ /\A[0-9X]+\z/
end
end


DB 抜きで簡単なアプリを作りたければ

$ ruby script/generate controller foo
とすると次のファイルができる。
app/views/foo
app/controllers/foo_controller.rb
test/functional/foo_controller_test.rb
app/helpers/foo_helper.rb

このまま foo にアクセスしても Unknown action と出るだけ。
FooController もからだし、view も空っぽだ。

$ vi app/views/foo/index.rhtml

<html>
<head>
<title>Foo</title>
</head>
<body>
<h2>Foo page</h2>
This is the index page for Foo
</body>
</html>


これでも悪くはないがスタイルの適用を考えれば

app/views/layouts 以下に view の名前で rhtml を作り、app/views/<controller>/*.rhtml
は body の中身だけにすると良い。

$ vi app/views/layouts/foo.rhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Foo: <%= controller.action_name %></title>
<%= stylesheet_link_tag 'scaffold' %>
</head>
<body>

<p style="color: green"><%= flash[:notice] %></p>

<%= yield %>

</body>
</html>



$ vi app/views/foo/index.rhtml

<h2>Foo page</h2>
This is the index page for Foo