ローイングファンのプログラミング日記

ボート競技やプログラミングについて書きます

Sinatraのルーティングと日本語URL

Sinatraのルーティングはシンプルでわかりやすい
そのうえ複雑なことも可能
今回はデータベースのデータをもとにして複数のページをつくってみた
その際、日本語URLも試した

目次


今回の環境

仮想環境の構築、データベースのインストールと設定は過去の記事参照


ディレクトリ作成

テスト用ディレクトリ作成

routes_testというディレクトリをつくってそこへ移動

$ mkdir routes_test
$ cd routes_test


Gemのインストール

Bundlerを使って必要なGemをインストールする。
Gemfileを作成

$ bundle init


GemfileにGemを記入

gem 'sinatra'
gem 'sinatra-contrib'
gem 'activerecord'
gem 'pg'

bundleインストール

$ bundle install

アプリに必要なファイルをつくる

テンプレートはviewsディレクトリ内につくる
今回のテンプレートはErb

routes_test/main.rb
routes_test/views/index.erb
routes_test/views/club_info.erb


データベース作成

今回はPostgreSQLを使用
データベースを起動してrowingclubデータベース内にrowingclubsテーブルをつくる。

起動とデータベースの作成

$ sudo systemctl start postgresql
$ createdb rowingclub


テーブル作成のSQLファイルをつくる。

create_rowingclubs.sql

create table rowingclubs (
id  serial  primary key,
club_name varchar(20),
created_at  timestamp default current_timestamp,
updated_at  timestamp
);


rowingclubデータベースにログイン
\iコマンドでファイルからテーブルを作成する

$ psql rowingclub
rowingclub=> \i create_rowingclubs.sql


テーブルにテスト用のレコードを挿入する

まずレコード挿入用のSQLファイルをつくる。

insert_record_to_rowingclub.sql

insert into rowingclubs (club_name) values
('ローイングクラブ'),
('ボートクラブ'),
('漕艇倶楽部'),
('端艇倶楽部');


\iコマンドでファイルからレコードを挿入する
挿入後にテーブルからログアウト

rowingclub=> \i insert_record_to_rowingclub.sql
rowingclub=> \q


できあがったテーブルの内容
rowingclub/rowingclubs

id club_name
1 ローイングクラブ
2 ボートクラブ
3 漕艇倶楽部
4 端艇倶楽部


コーディング

main.rb

require 'sinatra'
require 'sinatra/reloader'
require 'active_record'

#モデルの作成
class Rowingclub < ActiveRecord::Base
    establish_connection(
        adapter:  'postgresql',
        host:     "",
        username: 'vagrant',
        password: "",
        database: 'rowingclub'
    )

    def allclub
        allclub = Rowingclub.all
        return allclub
    end
end

#モデルの初期化と全レコードの抽出
allclub = Rowingclub.new.allclub

#ルーティング
#トップページ
get '/' do
    @allclub = allclub
    erb :index
end

#モデルからeachメソッドでレコードを取り出して
#各々のルートを作成
allclub.each do |club|
    #idのURLを作成
    get "/#{club['id']}" do
        @club_name = club['club_name']
        erb :club_info
    end
    
    #日本語のURLを作成
    get "/#{club['club_name']}" do
        @club_name = club['club_name']
        erb :club_info
    end
end


index.erb

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta http-equiv="content-type" content="text/html" charset="utf-8">
        <title>トップページ | Sinatra ルーティングテスト</title>
    </head>
    <body>
        <p>idでURLを作成</p>
        <ul>
        <% @allclub.each do |club| %>
            <li><a href=<%= "/#{club['id']}" %> ><%= "#{club['id']}" %></a></li>
        <% end %>
        </ul>
        <hr>
        <p>club_name(日本語)でURLを作成</p>
        <ul>
        <% @allclub.each do |club| %>
            <li><a href=<%= "/#{club['club_name']}" %> ><%= "#{club['club_name']}" %></a></li>
        <% end %>
        </ul>
    </body>
</html>


club_info.erb

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta http-equiv="content-type" content="text/html" charset="utf-8">
        <title>クラブ紹介ページ | Sinatra ルーティングテスト</title>
    </head>
    <body>
        <h1><%= "#{@club_name}の紹介ページ" %></h1>
    </body>
</html>


実行する

$ ruby main.rb -o [ipアドレス]

WEBrickが立ち上がったらブラウで表示させる
ブラウザにipアドレスとポート番号を入力する
http://[ipアドレス]:4567
これでトップページが表示されれば成功

f:id:rowingfan:20190630150148p:plain
index.erb


リンクをたどってページ遷移を確認
id(半角数字)のURL

f:id:rowingfan:20190630150553p:plain
URLのPathがid(半角数字)になっている


日本語のURL

f:id:rowingfan:20190630150728p:plain
URLのPathがclub_name(日本語)になっている


どちらもURLが期待通りになっている

URLエンコード

本来URLには非ASCII文字は使えないらしい
上で試したような場合はブラウザが日本語のURLをエンコードしてくれているのでエラーにならない
しかしredirectさせたりする場合は事前にURLエンコードが必要になる
URLエンコードするにはCGI.escapeメソッドを使う

CGI.escapeの使い方

require 'cgi'

CGI.escape '変換したい文字列'


エラーになる例

redirect "/漕艇倶楽部"

#=> ERROR URI::InvalidURIError: URI must be ascii only


URLエンコードをした例

require 'cgi'

ja_url = "/漕艇倶楽部"
ascii_url = CGI.escape ja_url
redirect "#{ascii_url}"
#=>エラーなくredirectする


参考ページ

Sinatra README
Routes
http://sinatrarb.com/intro.html

Rubyリファレンスマニュアル
CGIクラス
https://docs.ruby-lang.org/ja/latest/method/CGI/s/escape.html