[Rails] viewファイルや静的ファイルをデバイス別に分けて管理する


## やりたいこと

- ユーザがアクセスしてくるデバイスに応じて、表示するviewを変えたい。
- viewファイルや静的ファイルはデバイス別にディレクトリを分けて管理したい（以下イメージ）。

```
views
│
├── pc
│   │
│   ├── sample
│   │   ├── index.html.erb
│   │   └── new.html.erb
│   │   
│   └── layouts
│       └── application.html.erb
│
└── smartphone
    │
    ├── sample
    │   ├── index.html.erb
    │   └── new.html.erb
    │   
    └── layouts
        └── application.html.erb

assets
│
├── images
│   │
│   ├── pc
│   │   └── foo.png
│   └── smartphone
│       └── bar.png
│   
├── javascripts
│   │
│   ├── pc
│   │   └── application.js
│   └── smartphone
│       └── application.js
│   
└── stylesheets
    │
    ├── pc
    │   └── application.css.scss
    └── smartphone
        └── application.css.scss        
```

## 調べてみると

まず、「デバイス別にほげほげする」という文脈では、
jpmobileという国産gemが良さそうなことが分かりました。

jpmobile
https://github.com/jpmobile/jpmobile


#### 参考

Rails 3.2 + jpmobile でスマートフォン対応したみた
http://blog.inouetakuya.info/entry/20120418/1334750857

今最もモテる組み合わせのRails3.1 + jp_mobile でサイトを作った際のメモ
http://a-newcomer.com/23


## しかし

jpmobileの活用事例では、基本的にviewファイルの管理方法が
以下のように`ファイル名自体にデバイス情報を含めて管理する形`でした。


```
views
│
│── sample
│   ├── index.html.erb
│   ├── index_smart_phone.html.erb
│   ├── new.html.erb
│   ├── new_smart_phone.html.erb
│   ├── show.html.erb
│   └── show_smart_phone.html.erb
│   
└── layouts
    ├── application.html.erb
    └── application_smart_phone.html.erb
        
```

これでも良いのですが、「PC版のみ（orスマートフォン版のみ）いろいろ調整したい」
というシーンが増えてくる（サービスの運用フェーズでは基本的にこれが多い）と、
views配下が徐々に雑然としていきそうでした。


ということで、「やりたいこと」で書いたようなpc/smartphone毎にディレクトリを
分離した構造にする方法を以下メモ。


## デバイス毎に利用するviewファイルを切り替える

- jpmobileの機能でデバイス（pc/スマホ）を判別
- 判別に応じて、参照するviewsのパスを決定（ActionController::Base#prepend_view_path）

```ruby:application_controller.rb

class ApplicationController < ActionController::Base

  include Jpmobile::ViewSelector
  before_filter :set_view_path
  ~
  private
  def set_view_path
    path =  request.smart_phone? ? 'smartphone' : 'pc'
    prepend_view_path(Rails.root + 'app/views' + path)
  end

end

```

viewファイルの振り分けはこれだけでok。
次に、読み込むassetsファイル（css/js/画像）の調整です。

## css/jsの管理

### 各application.html.erbで、読み込みたいassetsのディレクトリを制御する

#### pc

```app/views/pc/layouts/application.html.erb
  <%= stylesheet_link_tag    "pc/application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "pc/application", "data-turbolinks-track" => true %>

```

#### smartphone

```app/views/smartphone/layouts/application.html.erb
  <%= stylesheet_link_tag    "smartphone/application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "smartphone/application", "data-turbolinks-track" => true %>

```


### 各application.css.scssで、インクルードするcssファイルを制御する

#### pc

```app/assets/stylesheets/pc/application.css.scss
/*
 ~
 *= require_self
 *= require_tree ../pc
 */
```

#### smartphone
```app/assets/stylesheets/smartphone/application.css.scss
/*
 ~
 *= require_self
 *= require_tree ../smartphone
 */
```

### 各application.jsで、インクルードするjsファイルを制御する

#### pc

```app/assets/javascripts/pc/application.js
~
//= require jquery
//= require jquery_ujs
//= require_tree ../pc
```

#### smartphone
```app/assets/javascripts/smartphone/application.js
~
//= require jquery
//= require jquery_ujs
//= require_tree ../smartphone
```

## 画像の管理

画像については、各viewファイルから、ディレクトリとファイル名を指定して呼び出してやるだけです。
（cssやjsと違い、application.css/jsといった親ファイルにインクルードする必要がないので。）

#### pc

```pc/sample.html.erb
<%= image_tag "pc/foo.png" %>
```
#### smartphone

```smartphone/sample.html.erb
<%= image_tag "smartphone/bar.png" %>
```

これで完成です。