Ruby on Rails 3.X を教えるのに困るところ

EY-OfficeではRuby on Railsの教育を行っています。Ruby on Rails はアグレッシブにバージョンアップしていきますが、教育を行う際には毎回、最新のバージョンで教育させて頂いています。


http://rubyonrails.org/images/rails.png
http://rubyonrails.org/images/pages/overview/download32.png


Rails3.0では大幅な内部構造の変更、3.1ではアセットパイプラインなどの追加、3.2では遅くなった開発コマンドの高速化・・・ と改良されて行くのはRailsを使うプログラマーとしては嬉しいのですが、教育で新たにRuby on Railsを学ぶ人に教えるには困った事があります。

それは、リファレンスマニュアル(API document) が使いにくくなったことです。

リファレンスマニュアルには、2つの使い方があると思います

  1. メソッド(API)の詳細な動作、オプション等を知る
  2. Railsの各クラス、モジュールにどのようなメソッド(API,機能)が在るのかを知る

1. の方は、最近のドキュメントはJavascriptで検索が出来るので、便利に使えます。


しかし、2. は問題です。

皆さん、Rails2.3のドキュメント覚えてますか? 例えば ActiveRecord::Baseクラス。ここには ActiveRecord(データベース操作のAPI)のほぼ全てのメソッドが書かれています。したがってRailsを勉強する人はこのページを一読すればRailsのデータベース操作がほぼ分かります(もちろん、バリデーションや関連なのど他のページの情報も必要ですが)。

比べ Rails3.2のActiveRecord::Baseクラス、ここを見てもRailsのデータベース操作メソッドは全く分かりません。 検索関係は ActiveRecord::FinderMethods 、格納・変更は ActiveRecord::Persistence 、集計系は ActiveRecord::Calculations ・・・・ とわかれています。
これは、Rails3.0 で内部構造の大きなリファクタリングを行った結果であり、この変更自体はRailsの成長の為には良いものだったと思います。でも、教育では困ったものです・・・・


Rails3.0 以降の教育では困ったものだなぁ〜 と思いつつ進めています。Rails2.X(Rails1.X)から使っている人にはRailsのクラス構造や機能は判っているので3.Xでも問題なく使えると思いますが、3.0以降から始めた人には、Railsにはどんなメソッドがあるのかを探すのは難しくなってるなぁ〜 と思う今日この頃です。


何か良いドキュメントを作らなくては行けないのかなぁ〜 。 どこかにないのかなぁ〜 。

Rails勉強会@東京第69回で 「今さら聞けないAWS on Rails」という話をしてきた

最近 Amazon Web Services (AWS) を使ってサービスを構築ていいますが、その際に調べたAWSの概要とRuby on Railsを動か際の注意点(ほとんど無いですが)やpaperclip + s3 でハマった事などを、先日行われた Rails勉強会@東京第69回 で話しました。

iPhoneで撮った画像をアップロード Paperclipで正しい向きのサムネール画像を作る方法

http://thoughtbot.com/images/oss/paperclip.png

Ruby on Rails で画像のアップロードを行うのに便利なライブラリー Paperclip
サムネール画像も自動的に作ってくれる優れものです。




ところが、iPhoneを縦向きにして撮影した画像のサムネールが横向きになってしまします!

実は iPhoneで取った画像は全て横長の画像で、縦向きで撮影した画像は、EXIF情報のOrientationに縦向きの情報がセットされています。iPhoneMac等ではこの情報を見て画像を縦に表示してくれます。しかしブラウザーに表示されるサムネールは縦にはなりません。

Paperclipはサムネール作成に ImageMagick を使いますが、ImageMagick には Orientation を見て画像を回転してくれる -auto-orient オプションがあります、素晴らしい!
このオプションをPaperclip の設定に書けば 上手く行くはずですが、その指定方法がなかなかわかりませんでした・・・・・
検索するといくつか出てくるのですが、古いPaperclip用の指定なのか上手く行きません、結局ソースを読みながら試したら以下のように指定すれば良いことが判りました。

class User < ActiveRecord::Base
   ・・・
  has_attached_file :picture, 
    {:styles => {:iphone => "120x120#", :ipad    => "360x360#"},
     :storage => :aws,
     :s3_credentials => "#{Rails.root}/config/s3.yml"}
  ・・・
end

のような設定の場合は以下のように :convert_options を指定します。

class User < ActiveRecord::Base
   ・・・
  has_attached_file :picture, 
    {:styles => {:iphone => "120x120#", :ipad    => "360x360#"},
     :convert_options => {:all => "-auto-orient"},
     :storage => :aws,
     :s3_credentials => "#{Rails.root}/config/s3.yml"}
  ・・・
end

現在お手伝いしているサービス Real Coach (リアルコーチ) が日経新聞に紹介されました

現在お手伝いしている Ruby on Rails 3.1 + iPhone + iPad を組み合わせたサービス Real Coach が日経新聞に紹介されました
→記事

iPhoneで撮影した動画を専門のコーチがiPadで診断するというとても興味深いサービスです! RealCoachホームページ にある動画を是非ご覧下さい、このサービスの良さと応用範囲が広い事を感じ取って頂けると思います。



システムの方は、現在絶賛開発中です。

jQueryMobileを使って 簡単にRuby on RailsサイトをクールなiPhone対応サイトにしてみた

jQuery Mobile | jQuery Mobile を使って Ruby on Rails で作ったWebサイトを iPhoneなどのスマフォに対応したサイトに変更してみました。以下の画像は Ruby on Railsの Scaffold で作ったサイトをjQueryMobile対応した後の画面です。

クールなスマフォサイトになっています!

1. まずは普通にscaffold でアプリを作る

Railsjavascript周りが大幅に強化された3.1を使っています。

% rails new jq_mobile
% cd jq_mobile
% rails g scaffold todo due:date task:string
% rake db:migration
% rails s

2. PC と iPhone でview(layout)を切り替える

jQueryMobile用のHTMLは通常のPCサイト用とは異なりますので、テンプレートファイルやlayoutを、PCとiPhoneからのアクセスで切り替えられようにしましょう。
これは Railsの機能で直ぐに出来ます。

config/initializers/mime_types.rb ファイルにコメントアウトされている以下の行を有効にすると :iphone というフォーマットが使えるようになりテンプレートは XXX.html.erb の他に XXX.iphone.erb が使えるようになります。

# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
Mime::Type.register_alias "text/html", :iphone

あとは、コントローラー (app/controllers/application_controller.rb)で user_agent を調べ、フォーマとやlayout を切り替えることにします。

class ApplicationController < ActionController::Base
  protect_from_forgery
  layout :set_layout
  before_filter :set_iphone_format

  def set_iphone_format
    request.format = :iphone if iphone_request?
  end
  
  def set_layout
    iphone_request? ? "iphone" : "application"
  end
  
  private
  
  def iphone_request?
    request.user_agent =~ /(Mobile.+Safari)/
  end
end

3. jQueryMobileのインストール

  • jQuery Mobileのjavascript, style sheetは CDN のものを使っても良いのですが、今回は ダウンロードし、Railsプロジェクトにコピーします。
% unizp jquery.mobile-1.0rc1.zip
% cd jquery.mobile-1.0rc1
% cp jquery.mobile-1.0rc1.js XXXX/jq_mobile/app/assets/javascripts
% cp jquery.mobile-1.0rc1.css XXXX/jq_mobile/app/assets/stylesheets
% cp -r images XXXX/jq_mobile/app/assets/stylesheets/images
  • app/assets/javascripts/application.jsはPC用するのでjQueryMobileが読み込まれないように以下の行を削除します(もっと良いやり方がある気がする・・・)。
 //= require_tree . 
  • app/assets/stylesheets/application.css はPC用するのでjQueryMobileが読み込まれないように以下の行を削除します(もっと良いやり方がある気がする・・・)。
 *= require_tree . 
  • app/assets/javascripts/mobile_application.js を追加
//= require jquery
//= require jquery_ujs
//= require jquery.mobile-1.0rc1
  • app/assets/stylesheets/mobile_application.css を追加
/*
 *= require_self
 *= require jquery.mobile-1.0rc1
*/

4. iPhone用view, layout を用意

iPhone用にviewportを定義し、jQueryMobileのページ用divを置きます

<html>
<head>
  <meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
  <title>iPhone</title>
  <%= stylesheet_link_tag    "mobile_application" %>
  <%= javascript_include_tag "mobile_application" %>
  <%= csrf_meta_tags %>
</head>
<body>
  <div data-role="page">

  <%= yield %>

  </div>
</body>
</html>
  • app/views/todos/index.iphone.erb の追加

例として、Todo一覧を表示するページを書いてみましょう。
ヘッダーにaddボタンを置いたり、一覧をjQueryMobileのテーブルと表示しています。

<div data-role="header">
  <h1>Listing todos</h1>
  <%= link_to 'Add', new_todo_path, "data-icon" => "plus", "class" => "ui-btn-right" %>
</div>

<div data-role="content">
  <ul data-role="listview">
  <% @todos.each do |todo| %>
    <li data-role="list-divider" style="padding: 0.1em 15px;"><%= todo.due %></li>
    <li><%= link_to todo.task ,todo %></li>
  <% end %>
  </ul>
</div>

他のページはGitHubyuumi3/jQueryMobileRails に置きましたので参考にして下さい。

5. ajaxEnabled を false にする

4.までで、jQueryMobile対応のサイトが出来ます。
iPhoneシミュレータや ブラフザーのuser_agentを切り替えられるプラグインや開発機能を使ってアクセスしてみましょう。

動かしてみると少し動作がへんです。
Todo一覧からTodoを選択し、編集し一覧に戻ると、その行は編集出来ないなど不思議な動作をします・・・

実は、jQueryMobileは単純に HTMLを表示するだけではなく、ページをキャッシュしたり色々な管理を行っています。その為にRailsのコントロールから外れてしまうことが多々あります。
そこで設定で ajaxEnabled を false する必要があります。ただし、この設定は jQueryMobileのjsを読み込む前に行う必要があります。

  • app/assets/javascripts/jqm_setup.js を作り
$(document).bind("mobileinit", function(){
  $.extend( $.mobile, {
    ajaxEnabled: false
  });
});
  • app/assets/javascripts/mobile_application.js に追加します
//= require jquery
//= require jquery_ujs
//= require jqm_setup
//= require jquery.mobile-1.0rc1

これで、ちゃんと使えるようになります。

6. 日付設定用 jquery.mobile.datebox

Railsのdate_selectが作る年月日の3つのselectboxはjQueryMobileでも正しく動作しますが、どうもダサイです ^^;
そこで jQuery-Mobile-DateBoxを使ってみました。
_form.iphone.erbは以下の様にシンプルですが下の画像の様な日付入力が表示されます。

  <div data-role="fieldcontain">
    <%= f.label :due %>
    <%= f.text_field :due, "data-role"=>"datebox", "data-options"=>'{"mode": "flipbox"}' %>
  </div>

ただし、デフォルトは米国式表示なので、以下のような設定で日本式にできます。

jQuery.extend(jQuery.mobile.datebox.prototype.options, {
	titleDateDialogLabel: '日付設定',
	setDateButtonLabel: 'OK',
	dateFormat: 'YYYY-mm-dd',
  headerFormat: 'YYYY-mm-dd',
	dateFieldOrder: ['y', 'm', 'd'],
	monthsOfYear: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],
	monthsOfYearShort: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"]
});


GitHubに プロジェクト全体を yuumi3/jQueryMobileRails に置きましたので参考にして下さい。

Rails3.1.0 + Capistrano 2.8.0 でエラーが発生するけどデプロイ出来る

Rails3.1.0を試していて現時点で最新の Capistrano 2.8.0 と組み合わせて使うとデプロイ中に以下のログのようにエラー(画像)が発生します。

ログ・テキスト

  * executing "find /home/rails_apps/todo31/releases/20110912141706/public/images /home/rails_apps/todo31/releases/20110912141706/public/stylesheets /home/rails_apps/todo31/releases/20110912141706/public/javascripts -exec touch -t 201109121417.06 {} ';'; true"
    servers: ["176.32.95.168"]
    [176.32.95.168] executing command
*** [err :: 176.32.95.168] find:
*** [err :: 176.32.95.168] `/home/rails_apps/todo31/releases/20110912141706/public/images'
*** [err :: 176.32.95.168] : No such file or directory
*** [err :: 176.32.95.168] 
*** [err :: 176.32.95.168] find:
*** [err :: 176.32.95.168] `/home/rails_apps/todo31/releases/20110912141706/public/stylesheets'
*** [err :: 176.32.95.168] : No such file or directory
*** [err :: 176.32.95.168] 
*** [err :: 176.32.95.168] find:
*** [err :: 176.32.95.168] `/home/rails_apps/todo31/releases/20110912141706/public/javascripts'
*** [err :: 176.32.95.168] : No such file or directory
*** [err :: 176.32.95.168] 

Capistoranoはまだ完全にはRails3.1.0に対応出来てないようで、assetに移動してpublicには無くなった画像、スタイルシートJavascript ディレクトリーのタイムスタンプを更新しようとしています。


デプロイはエラー終了しないので実害はありませんが、対策としては、config/deploy.rb に以下を加えるとこの操作が実行されないので、エラーは発生しなくなります。

set :normalize_asset_timestamps, false 

Capistrano の issue に この問題 は上がっているのでいずれ直るのではないでしょうか?

Mac OS X Lion でRuby on Railsの開発環境を構築するには

今日現在で、 Mac OS X Lion でRuby on Railsの開発環境を作るには

http://images.apple.com/jp/macosx/images/overview_callout_osx.png http://rubyonrails.org/images/rails.png


とりあえず、Ruby on Rails を試してみたい方は

Lionには 最新に近い Ruby 1.8.7(P249) がインストールされています。

% sudo gem install rails sqlite3

Ruby on Rails, SQLite3をインストールすればRuby on Railsが使えます。
以前あったirbで日本語が入力出来ない問題もないようです :-)

RVM をつかって環境を構築するさいの注意

 RVMでのインストール手順 は SnowLeopardと同じですが、今日現在、普通にビルドしたRuby1.8.7は [BUG] Segmentation fault が発生します。
対処は  ruby - Why can't I install Rails on Lion using RVM? - Stack Overflow に書かれているように、以下の様にしてビルドして下さい。

% CC=/usr/bin/gcc-4.2 rvm install ruby-1.8.7 --force