この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
スマフォでPC表示させているときの条件に注意。
Jpmobileの概要
RailsでPCサイトと共にスマフォサイトを作成する場合に便利なGemとして、JpmobileというGemがあります。
このGemを使うことで、アクセス端末に応じてviewを切り替えることができます。
すなわち、Jpmobileを使用することで、PCからアクセスされた場合にはPC用のviewを表示させ、スマフォからアクセスされた場合にはスマフォ用のviewを表示させることを、Webサイトの開発者が意識することなく実装できます。
また、スマフォからのアクセスかどうかを「request.smart_phone?」のように判定することができるようになります。
ここで、スマフォでアクセスした場合であっても、PC用のviewを表示したいユーザーがいることを考慮して、「PCサイトを表示する」のようなリンクを用意することがあると思います。
この場合には、「disable_mobile_view!」メソッドをコールすることで、PCサイトを表示させることができます。
※恐らく、このようなリンクがクリックされたことを、cookieやsessionに保存し、ページ遷移した後であっても、PCサイトを表示するように実装されるかと思います。
問題点
スマフォからのアクセスに対してPCサイトを表示させている状態であっても、request.smart_phone?の結果は「true」になります。
すなわち、viewが絡む部分(*1)に関して「request.smart_phone?」で条件判定をすると、意図しない動作になる可能性があります。
(*1) controllerでインスタンス変数に値を設定する場合等も含む。
例えば、
- PCの場合 → 12個のレコードをインスタンス変数に設定
- スマフォの場合 → 8個のレコードをインスタンス変数に設定
とすべき場合、本来であれば、
- PCアクセス(PC用の表示) → 12個のレコードがインスタンス変数に設定される
- SPアクセスでスマフォ用のを表示 → 8個のレコードがインスタンス変数に設定される
- SPアクセスでPC用の表示 → 12個のレコードがインスタンス変数に設定される
となって欲しいところです。
しかしながら、controllerで、
def index
count = request.smart_phone? ? 8 : 12
@records = TestTable.where(...).limit(count)
end
のように、「request.smart_phone?」を使用してしまうと以下のようになってしまいます。
- PCアクセス(PC用の表示) → 12個のレコードがインスタンス変数に設定される
- SPアクセスでスマフォ用のを表示 → 8個のレコードがインスタンス変数に設定される
- SPアクセスでPC用の表示 → 8個のレコードがインスタンス変数に設定される(←12個になっていない!!)
■ 対策
このため、viewに絡む部分に関しては、
- 判定1:アクセス端末によって切り替えるのか?
- 判定2:PC用のviewとスマフォ用のviewのどちらを表示しているかによって切り替えるのか?
を常に意識しないと思わぬバグに繋ります。
先程の例では、判定2でやらなければいけません(判定方法は、どちらのviewを表示しているかの情報が保存されたcookieやsessionを参照して判定することになると思われます)。
なお、判定1が必要になる例としては「SPアクセスでPC用の表示をしているときに、スマフォ用のviewに戻すためのリンクを表示する場合(PCでアクセスして来た人に対してスマフォ用のviewを表示することは通常ない。スマフォのときにのみ有効。但し、この例の場合には、PC用のviewを表示している場合にのみ表示させる必要有り)」が挙げられます。