4
4

More than 5 years have passed since last update.

Railsでスマートフォン用ページのControllerを分ける

Last updated at Posted at 2019-07-02

はじめに

レスポンシブデザインではなく、PC用のViewとスマートフォン用のViewを分けて実装する場合があるかと思います。
その際に、ActionPack Variantsを利用して、1つのControllerでデバイス毎にViewを切り替える方法が一般的かと思います。

しかし、PCページだけ先にVue.jsにリニューアルするなど、PCとスマートフォンでControllerを分けたい時などがあります。
本記事では、デバイスごとにControllerを切り替える方法をご紹介します。

やり方

大まかな方法としては以下のようになります。
1. requestからユーザーがアクセスしているデバイスを判定する
2. routingのconstraintsを使ってPC用のControllerとスマートフォン用のControllerと振り分ける

検証環境

Ruby 2.5.5
Ruby on Rails 5.2.3

準備

PCとスマートフォンそれぞれのControllerとViewを用意しておきます。

app/controllers/pc_page_controller.rb
class PcPageController < ApplicationController
    def index
    end
end
app/controllers/smartphone_page_controller.rb
class SmartphonePageController < ApplicationController
    def index
    end
end
app/views/pc_page/index.html.erb
PC用のControllerから表示されました。
app/views/smartphone_page/index.html.erb
Smartphone用のControllerから表示されました。

アクセスしているデバイスの判定

今回はrack-user_agentというgemをつかってデバイスを判定します。
Gemfileにrack-user_agentを追加しておきます。

Gemfile
gem 'rack-user_agent'

以下のようにrequestが拡張されて、デバイスを判定できるようなメソッドが追加されるので、簡単に判定できます。

class HomeController < ApplicationController
    def index
        request.from_pc?         #=> true
        request.from_smartphone? #=> false
    end
end

その他の機能はGithubのレポジトリを参照してください。
k0kubun/rack-user_agent: Rack::Request extension for handling User-Agent

constraintsを使ってルーティングを設定

constraintsを使うとルーティングにマッチさせる条件を設定することが出来ます。
参考:Rails のルーティング - Rails ガイド

基本的な使い方

config/routes.rb
get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ }

/photos/A12345のようなパスの場合photos#showが呼ばれますが、/photos/893はマッチしないため呼ばれません。

独自のConstraintを作成する

constraintsは独自のConstraintを作成することで、柔軟な判定をすることが出来ます。
matches?メソッドがtrueを返す場合、そのルーティングにマッチします。

app/constraints/smartphone_constraint.rb
class SmartphoneConstraint
    def self.matches?(request)
        request.from_smartphone?
    end
end
config/routes.rb
get '/', to: 'smartphone_page#index', constraints: SmartphoneConstraint
get '/', to: 'pc_page#index'

このように設定すると、routes.rbの上から順に判定されるため、
スマートフォンからのアクセスだとsmartphone_page#indexが呼ばれ、それ以外はpc_page#indexが呼ばれることとなります。

確認してみる

  • PCからアクセスした場合
    スクリーンショット 2019-07-02 23.08.25.png

  • スマートフォンからアクセスした場合
    スクリーンショット 2019-07-02 23.09.16.png

ちゃんと切り替わっていますね:thumbsup:

おわりに

既存のRailsアプリのフロントエンドをVue.jsにリニューアルしたくて、まずはPCページだけ導入してみようと思い今回の方法を使ってみました。
基本的にはデバイス毎にViewだけを切り替えたほうが分かりやすいとは思いますが、Controllerも切り替える必要があればこんな方法はいかがでしょうか。

Github: boronngo/rails-sp-routing

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4