ソースコードから理解する技術-UnderSourceCode

手を動かす(プログラムを組む)ことで技術を理解するブログ

Ruby on Rails - Mobile対応サイトの作成とRSpecのテスト

Ruby on Railsにて、PC向けのページと、Mobile向けのページを切り替える方法と
RSpecによるテストについてです。

仕様としては、クライアントのブラウザを判定し、それぞれ向けのLayout、
Viewファイルを表示します。

■ブラウザと表示するファイル
iPhoneSafariの場合は、ファイル名が「~.iphone.erb」のLayout、View
Androidの場合は、「~.android.erb」のLayout、View
・それ以外の場合は、「~.html.erb」のLayout、View

尚、クライアントからのアクセスを判定し、PC向け、Mobile向けと
ページを切り替える方法については下記サイトを参考にしました。

参考サイト
jQueryMobileを使って 簡単にRuby on RailsサイトをクールなiPhone対応サイトにしてみた - @yuumi3のお仕事日記

以下、ソースの解説です。

1.mine typeの登録

iPhone向け、Android向けのLayout、Viewファイルを定義します。

/config/initializers/mime_types.rb

Mime::Type.register_alias "text/html", :iphone
Mime::Type.register_alias "text/html", :android

2.ブラウザの判定と、表示するLayout・Viewの設定

全てのページに共通することなので、ApplicationControllerに記述します。

/app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  layout :set_layout
  before_filter :set_format

  def set_format
    request.format = :iphone if iphone_request?
    request.format = :android if android_request?
  end

  def set_layout
    return "mobile" if (iphone_request? || android_request?)
    return "application"
  end

  private
  def iphone_request?
    request.user_agent =~ /(Mobile.+Safari)/
  end

  private
  def android_request?
    request.user_agent =~ /(Android)/
  end
end

先ずはブラウザを判定する、iphone_request?()、android_request?()メソッドについてです。
user_agentを参照し、iPhone Safariを表す文字列があるか、Androidを表す文字列があるかで
ブラウザを判定しています。

次にLayoutファイルを設定する、set_layout()メソッドについてです。
上記のiphone_request?()、android_request?()メソッドを呼び出し
iPhoneもしくはAndroidの場合は、Layoutファイル名が「mobile.~」となり
それ以外は「application.~」となるように値を返却しています。

最後にViewのファイルフォーマットを設定する、set_format()メソッドについてです。
上記のiphone_request?()、android_request?()メソッドを呼び出し
iPhoneの場合は、Viewのファイル名が「~.iphone.erb」となり
Androidの場合は、「~.android.erb」となるように値を返却しています。

ここで使用している「:iphone」「:android」は、上記「mine typeの登録」で定義した値です。

3.RSpecによるテスト

ApplicationControllerについて、ユニットテストを記述すると以下のようになります。

/spec/controllers/application_controller_spec.rb

require 'spec_helper'

describe ApplicationController do
  controller do
    def index
      render :template => 'public/index'
    end
  end

  describe "iphone format, layout" do
    before(:each) do
      request.user_agent = "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_6 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B651 Safari/9537.53"
      get :index
    end

    it "should correct format" do
      request.format.symbol.should eq(:iphone)
    end

    it "should correct layout" do
      response.should render_template(layout: "mobile")
    end
  end

  describe "android format, layout" do
    before(:each) do
      request.user_agent = "Mozilla/5.0 (Linux; U; Android 4.0.3; ja-jp; AT570 Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"
      get :index
    end

    it "should correct format" do
      request.format.symbol.should eq(:android)
    end

    it "should correct layout" do
      response.should render_template(layout: "mobile")
    end
  end

  describe "non mobile format, layout" do
    before(:each) do
      get :index
    end

    it "should correct format" do
      request.format.symbol.should eq(:html)
    end

    it "should correct layout" do
      response.should render_template(layout: "application")
    end
  end
end

ここでのポイントは、「controller do・・・」ブロックでAnonymous controller
定義していることです。
この、いわばダミーのコントローラを定義することにより、下のテストコード内で
「get :index」という形式でGet要求を投げ、Responseを取得してテストすることが
可能となっています。

後は見ての通り、iPhoneAndroid向けにuser_agentを設定し
それぞれのLayout、Viewが正しく設定されているかをテストしています。

4.Layoutファイル

Layoutファイルは、以下の4つを作成しました。

・application.html.erb ・・・ iPhoneAndroid以外のLayout
・mobile.html.erb ・・・ iPhoneAndroidの共通Layout
・mobile.android.erb ・・・ AndroidのLayout
・mobile.iphone.erb ・・・ iPhoneのLayout

ここでのポイントは、iPhoneAndroidでそれぞれLayoutを用意していることと
共通のLayoutとして「mobile.html.erb」を用意していることです。

iPhoneAndroidでそれぞれLayoutを用意したのは、上記のApplicationController内で
ファイルのフォーマットが「~.iphone.erb」「~.android.erb」となるよう
設定したためです。

iPhoneAndroidでデザインが共通する部分については
「mobile.html.erb」内に記述し、「~.iphone.erb」「~.android.erb」から
参照する形としました。

5.Viewファイル

Viewファイルは、今回はpublicフォルダ内に以下の3つを作成しました。

・index.html.erb
・index.android.erb
・index.iphone.erb

ファイルのフォーマットが、ApplicationControllerのset_layout()メソッドで指定した
形式となっています。

【まとめ】
以上です。
user_agentを判定し、ブラウザ毎に表示するViewのフォーマットを
指定することで、Mobile対応サイトを作ることができます。

RubyMineに既存のRailsアプリケーションを読み込む

既存のRailsアプリケーションを、RubyMineで読み込み
デバッグ実行したいことがあるかと思います。

今回はその手順についてです。
尚、公式ドキュメントを読んだわけではないので
完全に俺流のやり方になります。

1.[File]-[New Project]を押下。

2.[Create New Project]ダイアログにて
[Location]は対象のアプリケーションのフォルダを選択。
[Project Type]は[Rails Application]を選択。

3.[Create New Project]ダイアログにて、存在するプロジェクトの変わりに
新しいプロジェクトを作るか?(超訳)、と聞いてくるので[No]を選択。

4.[Rails Application Settings]ダイアログにて
[Use existing Rails Application]を選択する。
他、適切なRubyRailsのバージョンを選択し、[OK]ボタンを押下する。

【まとめ】
以上で出来ました。
既存のプロジェクトを取り込むのに、[New Project]から始まるのが
他のIDEとは違うと感じるところです。
(「Project」とはRubyMineのProjectを指しているためだと思われる。)

GitHub for Windows コミット~タグ付け

GitHub for Windows を使い、コミットを行い
タグを付けるまでの手順について
毎回調べているので纏めておきます。

1.コミット

GitHub for Windowsで対象のリポジトリを開くと
コミットしていない場合は「Uncommitted changes」と左上に表示されます。

「Summary」や「Description」を記入し、「Commit to master」を押下すると
コミット完了です。

2.sync

コミットしただけでは、サーバのリポジトリには反映されていません。
サーバのリポジトリに反映させる(pushを行う)には、右上の「sync」を押下します。

3.タグ付け

タグを付けるには、シェルを起動してコマンドを実行します。

リポジトリを右クリック - 「Open a shell here」を押下すると
シェルが起動します。

以下、よく使うコマンドです。

$ git tag
    タグを確認します。

$ git tag -a タグ名 -m "メッセージ"
    タグをローカルリポジトリに作成します。

$ git tag
    タグを確認します。

$ git push --tags
    タグをサーバのリポジトリに反映します。

4.まとめ

以上です。
GitHub for Windowsを使う場合、GUICUIを適時使い分けるのが
初心者には使いやすいのかなと思います。

RubyMine - Ctrl + L で行選択する

タイトル通りの設定を行う、チョイねたです。
Sublime Text 2 と同じように操作するために設定しました。

以下、手順です。

1.[File]-[Settings]を選択する。
2.[Settings]ダイアログより、[Keymap]-[Editor Actions]-[Select Line at Curet]を右クリック。
3.[Add Keyboard Shortcut]を選択する。
4.[Enter Keyboard Shortcut]ダイアログにて、Ctrl + L を設定する。

以上です。

RubyMineでRSpec + Sporkを動かしデバッグする

タイトル通り、RubyMindeでRSpecをSporkサーバ上で動かし
デバッグする手順についてです。

Sporkサーバ上でRSpecを動かすと、RSpecの起動が早くなります。

以下、手順です。

■下準備
1.RubyMineでRails Applicationを作成する。

2.「Rails Application Settings」で「Skip Test:Unit files」にチェックを入れる。

3.Gemfileに以下を追記し、bundle installする。


gem 'therubyracer'
gem 'execjs'

group :development,:test do
gem 'rspec-rails'
gem 'spork', '1.0.0rc3'
end

4.RSpecをinstallする。
$ rails generate rspec:install

5.Controller、Viewを作成する。
$ rails g controller sample index

6.routes.rbに以下を記入し、index画面をルートページとする。


root 'sample#index'

7.アプリを起動し、ブラウザよりindex画面が表示されることを確認する。

■Sporkサーバの準備
1.[Tools]-[Run Spork DRb Server...]を押下する。

2.[Spork DRb Launch]ダイアログにて、[Choose test framework]は[RSpec]を選択する。
 [Perform bootstrap]に初回はチェックを入れ、[Run]を押下する。
 (初回以外はチェックを入れない)

3.コンソールに[pork is ready and listening on 8989!]と表示され、Sporkサーバーが
 起動していることを確認する。

4.[Run]-[Stop]を押下し、一旦Sporkサーバを停止する。

5. .rspecファイル内に以下を追加し、RSpecの起動オプションとしてSporkサーバを指定する。


--drb

RSpec、Sporkの起動とデバッグ
1.[Run]-[Debug]を押下し、[Debug]ダイアログより[RSpec with Spork DRb server:アプリ名]を押下する。

2.コンソールに[pork is ready and listening on 8989!]と表示され、Sporkサーバーが
 起動していることを確認する。

3.RSpecやController内にブレークポイントを設定する。

4.[Project]ウィンドウより実行したいRSpecファイルを右クリックし、[Debug 'Run spec・・・]を押下し
 RSpecを起動する。

5.ブレークポイントにて処理が止まることを確認する。

シェル内でsudoしてコマンドを実行する

sudoしてコマンドを実行する処理を、シェルにて行ったので
ちょい記事ですが備忘録として残しておきます。

ubuntuで実行したので、$ sudo su を行い
ヒアドキュメントを使っています。


#!/bin/bash

sudo su << COMMAND

cd 対象のディレクトリ
以下、実行したいコマンドを記入

COMMAND

以上です。

UbuntuでAngularJSを動かしてみる

以前に少し触っただけのAngularJSについて、もっと知ろうと思い
AngularJSのチュートリアルをやってみました。
AngularJS

今回はUbuntu上でやってみたので、AngularJSを動かすまでの
手順を以下にメモっておきます。

■動作環境
Ubuntu 13.10
・AngularJS 1.2.12

■手順
基本的にはAngularJSの通りですが
メッセージやエラーが出たので、以下の点を変えて行いました。

1.Node.jsのインストール
Node.jsが必要とのメッセージが出たため、以下のコマンドでインストールしました。

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update

2.npmのインストール
npmのインストール時にUNKNOWN, symlink ・・・というエラー発生しました。
結局、以下のコマンドでインストールしました。

npm install --no-bin-links

3.Chromeのインストール
AngularJSのテストを実行すると、以下のエラーが発生しました。
RROR [launcher]: Cannot start Chrome
Can not find the binary google-chrome
Please set env variable CHROME_BIN

テストで使用するKarmaは、Chromeが必要なようです。
なのでChromeをインストールしましたが、こちらはブラウザでChromeを検索し
以降はGUIでインストールしたので手順は省略します。

以上です。