Rails, Cucumberでfeatureで前提にログイン済み状態

背景の前提で、ログインしている状態にしておくメモ。

steps.rb

Given /^"(.*)"でログインしていること$/ do |login|
  @current_user = Admin.create!(
    :login => login,
    :password => "testtest",
    :password_confirmation => "testtest",
    :email => "foobar@example.com")
  visit "/session/new"
  fill_in("ログインID", :with => login)
  fill_in("パスワード", :with => "testtest")
  click_button("ログイン")
  response.body.should =~ /ログインしました。/m
end

feature

背景:
  前提 "foobar"でログインしていること

シナリオ:
 ....

CentOS, MySQL Clusterを楽々設定したい

苦労して色々試してみた結果、さっくりyumでインストールできる方法を見つけたのでやってみる。

yumかわいいよ。

RPMでやっても同じなんだけどね。

epelとremiのrepoを設定。

wget http://ftp.iij.ad.jp/pub/linux/fedora/epel/5/x86_64/epel-release-5-3.noarch.rpm
rpm -Uvh epel-release-5-3.noarch.rpm
wget http://rpms.famillecollet.com/el5.x86_64/remi-release-5-7.el5.remi.noarch.rpm
rpm -Uvh remi-release-5-7.el5.remi.noarch.rpm

インストール。

yum install mysql-server mysql-cluster

=================================================================================================================================================================================================================
 Package                                               Arch                                         Version                                                 Repository                                      Size
=================================================================================================================================================================================================================
Installing:
 mysql-cluster                                         x86_64                                       5.1.34-1.el5.remi                                       remi                                            14 M
 mysql-server                                          x86_64                                       5.1.34-1.el5.remi                                       remi                                            10 M
Installing for dependencies:
 mysql                                                 x86_64                                       5.1.34-1.el5.remi                                       remi                                           3.7 M
 mysql-libs                                            x86_64                                       5.1.34-1.el5.remi                                       remi                                           2.1 M
 mysqlclient15                                         x86_64                                       5.0.67-1.el5.remi                                       remi                                           1.3 M
 perl-DBD-mysql                                        x86_64                                       4.010-1.el5.rf                                          rpmforge                                       225 k
 perl-DBI                                              x86_64                                       1.607-1.el5.rf                                          rpmforge                                       871 k
 perl-Net-Daemon                                       noarch                                       0.43-1.el5.rf                                           rpmforge                                        44 k
 perl-PlRPC                                            noarch                                       0.2020-1.el5.rf                                         rpmforge                                        33 k

Transaction Summary
=================================================================================================================================================================================================================
Install      9 Package(s)         
Update       0 Package(s)         
Remove       0 Package(s)         

remiだけだったぽい。

ここにある、mysqlとmysql-serverは普通にmysqlをインストールする時のパッケージ。mysqldとmysqlクライアント。
MySQL Clusterには、管理ノード、データノード、SQLノードとあるのですが、そのうちSQLノードがmysqldとかです。

管理ノードは所謂管理ツール。クラスタ状態だとかmysqldだとかを管理してる。

データノードがデータを保存する場所。メモリ上に保存している模様。ファイル保存しないのかな?

SQLノードがmysqld。データノードからデータを取得したりSQLを解析したり、それをプログラムに渡してあげたり。
いつもだとテーブルのエンジンはMyISAMやInnoDBですが、これをNDBCLUSTERにするだけでいいのです。

さくっとインストールを終えて簡単に設定。

vi /etc/my.cnf

[mysqld]
ndbcluster
ndb-connectstring="127.0.0.1"

default-character-set=utf8

[ndbd]
ndb-connectstring=127.0.0.1

[mysql_cluster]
ndb-connectstring=127.0.0.1

[mysql]
default-character-set=utf8

vi /var/lib/mysql-cluster/config.ini

[NDBD DEFAULT]
NoOfReplicas: 1
IndexMemory=30M

[MGM DEFAULT]
PortNumber: 1186

[NDB_MGMD]
Id: 1
HostName: 127.0.0.1
ArbitrationRank: 1
DataDir: /var/lib/mysql-cluster

[NDBD]
Id: 21
HostName: 127.0.0.1
DataDir: /var/lib/ndb/data

[NDBD]
#Id: 22
#HostName: 192.168.0.12
#DataDir: /var/lib/ndb/data

[MYSQLD]
Id: 31
HostName: 127.0.0.1

[MYSQLD]
[MYSQLD]
[MYSQLD]

必要なディレクトリを作っておく。

mkdir -p /var/lib/ndb/data
chown -R mysql:mysql /var/lib/ndb

これじゃあまりMySQL Clusterの実感ないけどとりあえず起動。

service ndb_mgmd start
service ndbd start
service mysqld start

状態を見てみる。

ndb_mgm
> show
Connected to Management Server at: 127.0.0.1:1186
Cluster Configuration
---------------------
[ndbd(NDB)]	1 node(s)
id=21	@127.0.0.1  (Version: 5.1.34, Nodegroup: 0, Master)

[ndb_mgmd(MGM)]	1 node(s)
id=1	@127.0.0.1  (Version: 5.1.34)

[mysqld(API)]	4 node(s)
id=31	@127.0.0.1  (Version: 5.1.34)
id=32 (not connected, accepting connect from any host)
id=33 (not connected, accepting connect from any host)
id=34 (not connected, accepting connect from any host)

おー

次回は複数のサーバーで複数のノードを設定してみよう。

まだまだ調べることいっぱいあるね。

Nginx, Passenger, Rack, Sinatraで起動してみる

Passengerがnginxで使えるみたい。

nginxモジュールをインストールする際にnginxをダウンロードするかどうか聞かれました。
ソースからnginxをインストールしているなら、そのディレクトリを指定すればよいらしいけど、ちょっと前にnginxをyumからに変えていたので一旦削除。

sudo gem install passenger
passenger-install-nginx-module

(略

Automatically download and install Nginx?

Nginx doesn't support loadable modules such as some other web servers do,
so in order to install Nginx with Passenger support, it must be recompiled.

Do you want this installer to download, compile and install Nginx for you?

 1. Yes: download, compile and install Nginx for me. (recommended)
    The easiest way to get started. A stock Nginx 0.6.37 with Passenger
    support, but with no other additional third party modules, will be
    installed for you to a directory of your choice.

 2. No: I want to customize my Nginx installation. (for advanced users)
    Choose this if you want to compile Nginx with more third party modules
    besides Passenger, or if you need to pass additional options to Nginx's
    'configure' script. This installer will  1) ask you for the location of
    the Nginx source code,  2) run the 'configure' script according to your
    instructions, and  3) run 'make install'.

Whichever you choose, if you already have an existing Nginx configuration file,
then it will be preserved.

Enter your choice (1 or 2) or press Ctrl-C to abort: 1

(略

ほとんどreturnキー押して終了。

/opt/nginx以下にファイルができます。

conf/nginx.confに以下が記述されてます。

http {
    ...
    passenger_root /usr/local/ruby/lib/ruby/gems/1.8/gems/passenger-2.2.4;
    passenger_ruby /usr/local/ruby/bin/ruby;
    ...
}

あとはvirtual.confとか作って、

server {
   listen 80;
   server_name www.yourhost.com;
   root /somewhere/public;   # <--- be sure to point to 'public'!
   passenger_enabled on;
}
&#91;/sourcecode&#93;

こんな風に書けばいいようで。

passengerのモジュールインストール中に説明してくれるので親切。

で、今回はSinatraを使っているのでSinatraアプリ以下にconfig.ruをつくり、publicとtmpディレクトリを用意。

起動ファイルはyumでインストールした時のものを流用します。

&#91;sourcecode language='bash'&#93;
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin
#
# chkconfig:   - 85 15
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /etc/nginx/nginx.conf
# config:      /etc/sysconfig/nginx
# pidfile:     /var/run/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
&#91; "$NETWORKING" = "no" &#93; && exit 0

nginx="/opt/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/opt/nginx/conf/nginx.conf"

# &#91; -f /etc/sysconfig/nginx &#93; && . /etc/sysconfig/nginx

lockfile=/var/lock/subsys/nginx

start() {
    &#91; -x $nginx &#93; || exit 5
    &#91; -f $NGINX_CONF_FILE &#93; || exit 6
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    &#91; $retval -eq 0 &#93; && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    &#91; $retval -eq 0 &#93; && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}
case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

起動したり終了したりが楽。

/etc/init.d/nginx start
/etc/init.d/nginx stop
/etc/init.d/nginx restart

わぁー

やっぱメモリは喰うのね。。

Processing, なんとなくやってみる

ぼくもまだよくわかりませんが、ProcessingとはiTunesとかMediaPlayerとかスクリーンセーバーみたいな視覚的なものをプログラミングで簡単にデザインできる環境みたいです。

とにかくやってみた方が早い気がする。

http://processing.org/

DownloadからMac OSXをダウンロードします。

インストールしたら早速起動。

こんな画面が立ち上がる。

mainwindow

予備知識もないのでサイトのドキュメントからちょこっと試す。
そのままエディタ上にコードを書くだけ。

まるを描いてみる。

size(400, 400);
ellipse(100, 100, 200, 200);

draw1

線を引いてみる。

size(400, 400);
background(192, 64, 0);
stroke(255);
line(150, 25, 270, 350);

draw2

マウスを動かすと放射線みたいな線が引かれる。

void setup(){
  size(400, 400);
  background(192, 64, 0);
  stroke(255);
}

void draw(){
  line(150, 25, mouseX, mouseY);
}

draw5

マウス動かす毎に背景かえてみる。

void setup(){
  size(400, 400);
  stroke(255);
}

void draw(){
  background(192, 64, 0);
  line(150, 25, mouseX, mouseY);
}

マウスをクリックとか。

void setup(){
  size(400, 400);
  stroke(255);
}

void draw(){
  line(150, 25, mouseX, mouseY);
}

void mousePressed(){
  background(192, 64, 0);
}

いっぱいまるができる。

size(400, 400);

for(int i=0; i&lt;400; i++){
  fill(128, random(256), 255);
  float size = random(10, 20);
  ellipse(random(width), random(height), size, size);
}

draw3

なんか永久ループはいったぽいまるを描いてみる。

void setup(){
  size(400, 400);
  background(192, 64, 0);
}

void draw(){
  for(int i=0; i&lt;400; i++){
    fill(128, random(256), 255);
    float size = random(10, 20);
    ellipse(random(width), random(height), size, size);
  }
}

draw4

とまあ試してみましたが、やっている間はちょっと面白くて色々と調べてたりしました。

3Dとかもコードでかけるようです。(まだ試してませんが。。

最近ではARToolKitとかで表現できるみたい。
ライブコードをマーカーの上に3Dで表示するとかってことなのかな??

as3とかrubyでもかけるようなのでもう少し調べてみよう。
rubyでっていうのは気になるところ。

Rails, 国際化の件

いつも忘れてしまうので、とりあえずの国際化メモ。

sudo gem install amatsuda-i18n_generators
./script/generate i18n ja
./script/generate i18n en

生成されたファイル。

config/locales/translation_ja.yml #モデルまわり
config/locales/translation_en.yml

config/locales/action_view_en.yml
config/locales/active_record_en.yml
config/locales/active_support_en.yml

config/locales/ja.yml #上記の3ファイルがまとめて生成されてる?

バリデーション関係は特に弄らずそのまま。

コントローラーとかでflash[:notice]やる場合に、

flash[:notice] = t(:created_success, :model => Post.human_name)

こんな感じ。

たぶんこんなのが出る。

translation missing: ja, created_success

出たら、


vi config/locales/ja.yml
ja:
created_success: “{{model}}を作成しました。”

みたいに追加しておく。

すると、「記事を作成しました。」と表示される。

Rails, RSpecとCucumberのautospecをgrowlに通知する

やっぱりgrowlにも通知しておきたい。

以前rspecに設定した.autotestを編集します。

# -*- ruby -*-
 require 'autotest/redgreen'
module Autotest::Growl
  def self.growl title, msg, img="~/.rails_ok.png", pri=0, sticky=""
    msg += " at #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
    system "growlnotify -n autotest --image #{img} -p #{pri} -m #{msg.inspect} #{title} #{sticky}"
  end

  Autotest.add_hook :ran_command do |at|
    results = [at.results].flatten.join
    ex = results[/(\d+)\s+example?/].to_i
    fa = results[/(\d+)\s+failure?/].to_i
    er = results[/(\d+)\s+error?/].to_i
    num = fa + er
    if ex &gt;= 0
      if num.to_i &gt; 0
        output = "#{fa} failures, #{er} errors"
        growl "RSpec Failed", "#{output}", "~/.rails_fail.png", 2, "-s"
      else
        growl "RSpec Passed", "#{ex} examples passed", "~/.rails_ok.png", -2
      end
    else
      growl "RSpec Errored", "errors", "~/.rails_fail.png", 2, "-s"
    end
  end
  
  Autotest.add_hook :ran_features do |at|
    results = [at.results].flatten.join
    sc = results[/(\d+)\s+scenario?/].to_i
    sk = results[/(\d+)\s+skipped?/].to_i
    pe = results[/(\d+)\s+pending?/].to_i
    un = results[/(\d+)\s+undefined?/].to_i
    fa = results[/(\d+)\s+failed?/].to_i
    pa = results[/(\d+)\s+passwd?/].to_i
    st = results[/(\d+)\s+step?/].to_i
    num = sk + pe + fa + un
    if sc &gt;= 0
      if num.to_i &gt; 0
        output = "#{sk} skipped, #{un} undefined, #{pe} pending, #{fa} failed"
        growl "Cucumber Failed", "#{output}", "~/.rails_fail.png", 2, "-s"
      else
        growl "Cucumber Passed", "#{sc} scenarios, #{st} steps passed", "~/.rails_ok.png", -2
      end
    else
      growl "Cucumber Errored", "errors", "~/.rails_fail.png", 2, "-s"
    end
  end
end

いい感じ。

Rails, cucumberで日本語feature書いたけど。。。

というわけで、前回の続きです。

Rails, cucumberでしあわせになりたい

やっていた時点での最新

  • rspec 1.2.6
  • rspec-rails 1.2.6
  • webrat 0.4.4
  • cucumber 0.3.9

すでにこの時点で、

Featureがフィーチャ、Senarioがシナリオ、Givenが前提、、などと書く事ができました。

さらに、features/step_definitions/webrat_steps.rbを日本語対応してfeatures/manage_posts.feature自体も日本語で書きたいので、下記をインストールして実行しました。

% sudo gem install moro-miso
% ./script/generate miso
 create  features/step_definitions/webrat_ja_steps.rb
 create  features/step_definitions/web_extra_ja_steps.rb

ちょっと中身をみてます。

% grep When webrat_ja_steps.rb
When(/^"([^\"]*)"ページを表示する$/, &visit)
When /^"([^\"]*)"ボタンをクリックする$/ do |button|
  When %Q(I press "#{button}")
When /^"([^\"]*)"リンクをクリックする$/ do |link|
  When %Q(I follow "#{link}")
When /^"([^\"]*)"に"([^\"]*)"と入力する$/ do |field, value|
  When %Q(I fill in "#{field}" with "#{value}")
When /^"([^\"]*)"から"([^\"]*)"を選択する$/ do |field, value|
  When %Q(I select "#{value}" from "#{field}")
# When I select "December 25, 2008 10:00" as the date and time 
When /^日時として"([^\"]*)"を選択する$/ do |time|
  When %Q(I select "#{time}" as the date and time)
# When I select "November 23, 2004 11:20" as the "Preferred" date and time
When /^"([^\"]*)"の日時として"([^\"]*)"を選択する$/ do |datetime_label, datetime|
  When %Q(I select "#{datetime_label}" as the "#{datetime}" date and time)
# When I select "2:20PM" as the time
When /^日付として"([^\"]*)"を選択する$/ do |time|
  When %Q(I select "#{time}" as the time)
# When I select "7:30AM" as the "Gym" time
When /^"([^\"]*)"の日付として"([^\"]*)"を選択する$/ do |time_label, time|
  When %Q(I select "#{time_label}" as the "#{time}" time)
# When I select "February 20, 1981" as the date
When /^時間として"([^\"]*)"を選択する$/ do |date|
  When %Q(I select "#{date}" as the date)
# When I select "April 26, 1982" as the "Date of Birth" date
When /^"([^\"]*)"の時間として"([^\"]*)"を選択する$/ do |date_label, date|
  When %Q(I select "#{datetime_label}" as the "#{date}" date)
When /^"([^\"]*)"をチェックする$/ do |field|
  When %Q(I check "#{field}")
When /^"([^\"]*)"のチェックを外す$/ do |field|
  When %Q(I uncheck "#{field}")
When /^"([^\"]*)"を選択する$/ do |field|
  When %Q(I choose "#{field}")
When /^"([^\"]*)"としてファイル"([^\"]*)"を選択する$/ do |field, path|
  When %Q(I attach the file at "#{path}" to "#{field}")

これは便利。感謝です。

でfeatureの中身は、

フィーチャ: 記事
  In order to [goal]
  [stakeholder]
  wants [behaviour]

  背景:
    前提 ユニークIDを持っていること

  シナリオ: 新しい記事の登録をする。
    前提 "docomo"でアクセスしている
    もし 記事登録ページへ"email"が"test@example.com"でアクセスする
    かつ "お名前"に"わたくしです"と入力する
    かつ "メールアドレス"に"hoge@example.com"と入力する
    かつ "送信する"ボタンをクリックする

    ならば "わたくしです"と表示されていること
    かつ "hoge@example.com"と表示されていること

これで、rake featuresと実行すればテストできる!!

ただ上記の例で書いている通り、前提に携帯電話のエージェントを指定させているのですが、これはjpmobileでテストしたかった名残です。

結構頑張って色々コード書いたのですが、文字コードの問題なのかうまい事テストできなかったです。これもあとで出来るようにしておきたいな。

PCだけならすごく便利!

Linux, yumのrepoを追加

どこかに書いた記憶があるけど・・

# wget http://ftp.iij.ad.jp/pub/linux/fedora/epel/5/x86_64/epel-release-5-3.noarch.rpm
# rpm -Uvh epel-release-5-3.noarch.rpm
# wget http://rpms.famillecollet.com/el5.x86_64/remi-release-5-7.el5.remi.noarch.rpm
# rpm -Uvh remi-release-5-7.el5.remi.noarch.rpm

remiはenabled=0なので1にしておきました。