インストールするだけですぐに使える本格的な無料Railsプラグイン
よく使うRailsプラグインをリスト。毎回検索してインストールするのが面倒だったので。
ちなみにタイトルはホッテントリメーカーです。無料じゃないプラグインなんて見た事ないけどw160ブクマはいく予感!
rails app_nameしたら即行入れるプラグインたち
Annotate Models
Modelに対応するテーブルのカラム情報をコメントとして付加してくれる。
script/plugin install http://repo.pragprog.com/svn/Public/plugins/annotate_models
Safe ERB
HTMLエスケープを忘れていると警告してくれる。
いつのまにかAgile Web Developmentに乗ってる!と思ったら、さらにGitHubで亜種が出ててびっくり。リンクを張ったものはsqlite3にも対応している模様。
script/plugin install git://github.com/emk/safe_erb.git
Safe Record
script/plugin install git://github.com/authorNari/safe_record.git
Special Warnings
"1" == 1のように文字列と数値を比較しているとログに警告を出してくれる。
script/plugin install git://github.com/authorNari/special_warning.git
なんだかんだで結局どのアプリでも入れてるプラグインたち
jRails
jQuery派なので。Rails標準のprototype.jsをラップしたjavascript helperをjQueryをラップしたものに置き換えてくれる。
script/plugin install http://ennerchi.googlecode.com/svn/trunk/plugins/jrails
Restful Authentication
認証機能一式をごっそり生成してくれる。
script/plugin install git://github.com/technoweenie/restful-authentication.git
Forgot Password
パスワード再設定機能一式をごっそり生成してくれる。
script/plugin install git://github.com/greenisus/forgot_password.git
Active Form
DBに対応したテーブルがなくてもModelを作れる。
script/plugin install git://github.com/zaczheng/activeform.git
Jp Mailer
iso-2022-jpで日本語メールを送りたいときに。
script/plugin install http:/taslam-plugins.googlecode.com/svn/trunk/jp_mailer/
RailsのMigrationをTimestampから連番に戻す
Rails 2系からMigrationファイルのバージョンがTimestampで管理されるようになりましたが、あれエディタで開くとき不便なんですよね。2.2からはconfigで連番に戻せるようになったので、戻しました。
config/environment.rb
config.active_record.timestamped_migrations = false
で、今までTimestampを頭につけて管理されていたものを連番にリネーム。
ruby -rfileutils -e 'Dir["db/migrate/*.rb"].sort.each_with_index {|f, i| FileUtils.mv f, f.gsub(/\d+/, sprintf("%03d", i))}'
RailRoadでRailsのモデルを視覚化(ERDを出す)
RailRoadというライブラリを使うと、Railsのモデルを視覚化することができます。最近のプロジェクトでは先にDBを作ってから実装を始めるというRailsっぽくない開発が多かったので久しくお世話になってなかったのですが、今開発中のアプリはとりあえずモデルの関係だけ定義しておいて、必要になったらフィールドを増やすというラフな開発をしているので、コマンド一発でモデルの関係とフィールドが視覚化できるRailRoadはありがたい存在です。
と、前置きはこのへんにしてUbuntuでRailRoadを使うメモを残しておきます。
Graphvizというクロスプラットフォームの視覚化ツールと、RailRoadのライブラリをインストールします。RailRoadのサイトにはRails1.2.3で動く的なことしか書いてないですが、2.2.2でも動いてます。
sudo aptitude install graphviz sudo gem install railroad
あとはRailsプロジェクトで、
railroad -M | neato -Tpng > doc/erd.png
すればdoc/erd.pngにERDが出てきます。こんな感じ。
うまくいった!…と思ったら、ERDの表記法がIE表記っぽいんだけど、鳥足の向きが逆…こんな表記法ありましたっけ?IE表記に慣れているのでこれでは見づらい!ということで、向きを逆にしてみる。
railroad -M | sed -e 's/arrowtail=\(.*\)\?, arrowhead=\(.*\)\?,/arrowtail=\2, arrowhead=\1,/g' | neato -Tpng > doc/erd.png
逆になった!
Railsでネストしたリソースのscaffoldを生成する
これは結構便利!blogにひもづくentriesのようなネストしたリソースを管理するアプリを作りたいときに、今まで手動でmodelの関係・routes・controllerのfilter・viewのurlヘルパーをを編集していたが、そこらへんを解決済みのscaffoldを生成してくれるプラグインがあった。
http://deaddeadgood.com/2008/10/8/scaffolding-nested-resources-in-rails
これを使えば、この間作ったRailsで作るログイン可能なブログシステムもたったのこれだけ!
rails blog cd blog script/plugin install git://github.com/technoweenie/restful-authentication.git script/plugin install git://github.com/phorsfall/rspec_on_rails_nested_scaffold.git script/generate authenticated user script/generate rspec_nested_scaffold blog title:string user:belongs_to --owner user script/generate rspec_nested_scaffold entry title:string body:text blog:belongs_to --owner blog rake db:migrate
で出来ると思ったんだけど、routesとmodelは自分で変更する必要あり。
# config/routes.rb ... map.resources :users, :shallow => true do |user| user.resources :blogs do |blog| blog.resources :entries end end ... # app/models/user.rb class User < ActiveRecord::Base ... has_many :blogs ... end # app/models/blog.rb class Blog < ActiveRecord::Base belongs_to :user has_many :entries end
あとviewからuser:belongs_toとblog:belongs_toの部分を抜いて、ブログとエントリーへのアクセスにログイン必須のフィルターをかけてあげる必要があるけど、こりゃ大分楽になるわ。
追記
routesに:shallow => trueオプションを付けてしまうと、show, editのアクションへのurlを解決できなかった。:shallowオプションなしの一段のネストなら大丈夫。
質問した。
家計簿について。
http://sooda.jp/qa/100720
http://oshiete1.goo.ne.jp/qa4703605.html
始めて人力検索っぽいサービス使ったけど、回答貰えると嬉しい。
Sooda!の回答の早さにびっくりした。回答くださった方ありがとうございます。
引き続きよろしくお願いします。
Cucumberでブログシステムの統合テストをする
バイト先の社内勉強会でCucumberのデモをやったときのログです。
はじめに
このエントリーではCucumberのセットアップから新しいシナリオの追加までの手順を紹介します。エントリーを管理するシンプルなRailsアプリケーションに対するCucumberによるテストを生成し、Feature、Stepの読解とエントリーの変更シナリオの追加を行います。
セットアップ
こちらを参考に。
インストール
$ sudo apt-get install libxml2-dev libxslt1-dev
必要なRubyのライブラリをインストールします。
$ sudo gem install nokogiri rspec rspec-rails webrat cucumber
ブログシステムを作成
この間作ったマスターは使いません。
タイトルと本分を持つエントリーを管理するシンプルなscaffoldを作成します。
$ rails blog $ cd blog/ $ script/generate scaffold entry title:string body:text $ rake db:migrate $ rake db:migrate RAILS_ENV=test
Cucumberの準備
railsアプリでCucumberを使う準備をします。
$ script/generate cucumber create features/step_definitions create features/step_definitions/webrat_steps.rb create features/support create features/support/env.rb create features/support/paths.rb exists lib/tasks create lib/tasks/cucumber.rake create script/cucumber
シナリオを作成する際に使用する語彙やrakeタスクが生成されます。
エントリー管理のシナリオテストを生成
$ script/generate feature entry title:string body:text exists features/step_definitions create features/manage_entries.feature create features/step_definitions/entry_steps.rb
エントリー管理をテストするための、manage_entries.featureとentry_steps.rbが生成されます。
CucumberではFeatureという自然言語のシナリオと、それをRubyで解釈するためのStepの二つが登場します。詳しくは、Cucumberがアツい - moroの日記
Featureを実行してみる
ジェネレータで生成されたFeatureを実行してみます。
$ rake features ... 2 scenarios 9 steps passed
2つのシナリオと9つのステップが実行されたらしい。では、シナリオがどのようになっているのか見てみましょう。
features/manage_entries.feature
Feature: Manage entries In order to [goal] [stakeholder] wants [behaviour] Scenario: Register new entry Given I am on the new entry page When I fill in "Title" with "title 1" And I fill in "Body" with "body 1" And I press "Create" Then I should see "title 1" And I should see "body 1" Scenario: Delete entry Given the following entries: |title|body| |title 1|body 1| |title 2|body 2| |title 3|body 3| |title 4|body 4| When I delete the 3rd entry Then I should see the following entries: |title|body| |title 1|body 1| |title 2|body 2| |title 4|body 4|
Scenario:で始まるエントリー登録のシナリオとエントリー削除の2つのシナリオが生成されてますね!どう見てもただの英文テキスト。
Given, When, Then, Andで始まるのがStepでちょうど9つあります。
シナリオとステップの関係
シナリオはステップから構成されていて、シナリオごとに
- Given: 前提として○○、
- When: そのとき□□すると、
- Then: △△になるはず。
という検証を行っています。では、このシナリオはどのように解釈されているんでしょうか。
ここで、ステップ定義の登場です。
features/step_definitions/entry_steps.rb
Given /I am on the new entry page/ do visit "/entries/new" end Given /^the following entries:$/ do |entries| Entry.create!(entries.hashes) end When /^I delete the (\d+)(?:st|nd|rd|th) entry$/ do |pos| visit entries_url within("table > tr:nth-child(#{pos.to_i+1})") do click_link "Destroy" end end Then /^I should see the following entries:$/ do |entries| entries.raw[1..-1].each_with_index do |row, i| row.each_with_index do |cell, j| response.should have_selector("table > tr:nth-child(#{i+2}) > td:nth-child(#{j+1})") { |td| td.inner_text.should == cell } end end end
ステップに対するRubyの命令が書かれています。GivenやThenには/I am on the new entry page/のように正規表現が与えられていて、ステップがこの正規表現にマッチするとブロック内のRubyの命令が実行される仕組みです。
バグがあったときどうなるのか
バグがあるとどうなるのでしょう。
app/views/entries/show.html.erbで本文を出力しているところをコメントアウトしてみます。
app/views/entries/show.html.erb
@@ -5,7 +5,7 @@ <p> <b>Body:</b> - <%=h @entry.body %> + <%#=h @entry.body %> </p>
Featureを実行すると、
$ rake features Scenario: Register new entry # features/manage_entries.feature:6 ... And I should see "body 1" # features/step_definitions/webrat_steps.rb:89 expected: /body 1/m, got: "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n ... 2 scenarios 8 steps passed 1 step failed rake aborted!
I should see "body 1"というステップが落ちています。
なるほど、こんな感じで検証できるんですね。app/views/entries/show.html.erbを元に戻して次いってみましょう。
エントリー変更を検証するシナリオを追加する
エントリー登録のシナリオを参考にエントリー変更のシナリオを作成してみます。
シナリオはこんな感じになるはず。
- 前提として、id○番のエントリー変更ページを表示していて
- かつ、"title 1"と"body 1"が表示されている
- そのときTitleに"title updated"と入力して
- かつ、Updateボタンを押すと
- "title updated"と表示されるはず。
最初から日本語でFeatureを書いておけばよかったと思いつつ、今回は最後まで英語でいきます。
シナリオを追加します。
features/manage_entries.feature
... Scenario: Register new entry ... Scenario: Edit existing entry Given I am on the edit entry page of 1 And I should see "title 1" And I should see "body 1" When I fill in "Title" with "title updated" And I press "Update" Then I should see "title updated" ... Scenario: Delete entry
Featureを実行してみます。
$ rake features ... 3 scenarios 9 steps passed 5 steps skipped 1 step pending (1 with no step definition)
1 step pendingということで、新しく追加したGiven I am on the edit entry page of 1 というシナリオがペンディングになっているはずです。解釈できないステップがあるとペンディングになるんですね。
ステップ定義を追加しましょう。idの部分は可変なので変数にします。正規表現の後方参照を使うとブロック引数として受け取ることができます。
features/step_definitions/entry_steps.rb
Given /I am on the edit entry page of (\d+)/ do |id| visit "/entries/#{id}/edit" end
Featureを実行します。
rake features ... Scenario: Edit existing entry # features/manage_entries.feature:14 Given I am on the edit entry page of 1 # features/step_definitions/entry_steps.rb:5 Couldn't find Entry with ID=1 (ActiveRecord::RecordNotFound) ... 3 scenarios 9 steps passed 1 step failed 5 steps skipped rake aborted!
あれ…落ちましたね。原因はActiveRecord::RecordNotFound。初期データが足りてないんですね。削除のシナリオと同じように初期データを用意しましょう。
最終的なFeatureはこうなります。
features/manage_entries.feature
... Scenario: Register new entry ... Scenario: Edit existing entry Given the following entries: |id|title|body| |1|title 1|body 1| Given I am on the edit entry page of 1 And I should see "title 1" And I should see "body 1" When I fill in "Title" with "title updated" And I press "Update" Then I should see "title updated" ... Scenario: Delete entry
今度こそ、Featureを実行すると、
$ rake features ... 3 scenarios 16 steps passed
通った!
試しに、間違ってEntryモデルのタイトルメソッドをオーバーライドすると…
app/models/entry.rb
class Entry < ActiveRecord::Base def title "title 1" end end
rake features ... Scenario: Edit existing entry # features/manage_entries.feature:14 Given the following entries: # features/step_definitions/entry_steps.rb:9 Given I am on the edit entry page of 1 # features/step_definitions/entry_steps.rb:5 And I should see "title 1" # features/step_definitions/webrat_steps.rb:89 And I should see "body 1" # features/step_definitions/webrat_steps.rb:89 When I fill in "Title" with "title updated" # features/step_definitions/webrat_steps.rb:18 And I press "Update" # features/step_definitions/webrat_steps.rb:10 Then I should see "title updated" # features/step_definitions/webrat_steps.rb:89 expected: /title updated/m, ... 3 scenarios 14 steps passed 2 steps failed
バッチリおちました!
まとめ
今回はscaffoldに対するシナリオテストを生成し、Cucumberの基本的な使い方を見ていきました。ジェネレータで生成された英語のシナリオをそのまま使いましたが、日本語でシナリオを書くことも可能です。自然言語で書いたシナリオがそのまま動くなんて動く仕様書も夢じゃない!
月々たったの168円でRailsアプリを公開する方法
なんかAdsenseにありそうなタイトルになってしまいましたが(笑)言わずと知れた超高機能で低価格な夢のようなサーバーDream Hostの話です。
Railsでアプリを作ると、作るまではレールに乗っかってすいすい行けるんですが、そこから先の公開となるとPHPのように簡単にはいかないんですよね。
DreamHostを使えば、それが5分で出来てしまいます。(Dream HostというよりPassengerのおかげですけど)しかも、今なら月々たったの168円!金利手数料なし!
円高の今がチャンスということでさっそくサインアップしちゃいました。攻殻のDVDBoxが2000円で買えちゃったりしてるみたいですけど、ほんと円高様様ですね。
スペック
ディスクスペース | 50GB+α |
転送量 | 無制限*1 |
メールアドレス | 無制限 |
ユーザー数 | 無制限 |
ドメイン | 1個無料 |
サブドメイン | 無制限 |
開発環境 | PHP5, Perl, Python, Ruby(Railsは2.2.2が入ってた!), CSV, SVN |
という頭おかしいんじゃないかと思うスペックです。詳しくは、こちら
お値段
月払い$10.95/month, 1年払い$9.95/month 〜 10年払い$5.95/month等のプランがあります。
このままだと1年払いで月1000円くらいですが、promoコードという$97を招待した人とされた人で山分けする仕組みがあり、全額招待された人に配分されているコードがあるので、それを使うと…
$119.4(1年分一括) - $97 = $22.4
2009/2/2現在$1が90円を切ってるので
$22.4 * 90 = ¥2016
つまり月あたり…
¥2016 / 12 = ¥168
ということになるわけです。私もさっそくMax配分のPromoコードを作ったのでぜひ使ってください。
サインアップするときに、
promotion codeに"KOUMIYA"と入力すればおkです。メールアドレスは、配分には関係ないみたいですが、ランキング(?)が出るようなのでめんどくさくなかったら入れてください(笑)
次の画面で割引されているのを確認してくださいね。
使ってみて
安いのには訳がある、その分重いって話も聞きますが今のところ大丈夫です。感覚的なものもあるし、まだ一人でしか使ってないってのでなんとも言えないですが。
さっそくサブドメインを切ってredMineをインストールして使っていますが、かなり快適に使えてます。しかも、チェックボックス1個チェックするだけで、Railsが動く環境が整うのが素晴らしすぎる!とりあえず1年間試してみる価値は十分あると思いますよ。
*1:普通に使っている分には上限なしというニュアンスで、ありえない転送量だったら交渉してねという感じ