Help us understand the problem. What is going on with this article?

駅すぱあとWebサービスとRuby/Gtkを組み合わせて回数券情報を表示するアプリを作ってみる

More than 1 year has passed since last update.

ヴァル研究所 Advent Calendar 2018 22日目の記事です。
今日は駅すぱあとWebサービス回数券一覧Ruby/Gtkを組み合わせて、簡単なGUIアプリを作成する手順を紹介しようと思います。

回数券一覧API

回数券一覧は「駅すぱあと」の保持する回数券の一覧を取得するWebAPIになります。

使い方としては、回数券一覧APIで回数券の名称を取得し、金額や有効期限といった回数券の詳細は回数券詳細APIで取得するという形になります。

この2つのAPIは、3日目の記事で紹介したAmazon SaaSストアで購入できる駅すぱあとWebサービスで利用可能なAPIとして提供されています。

Ruby/Gtk

Ruby/GtkRubyからGtkを利用するための拡張ライブラリです。Linuxだけでなく、macOSやWindowsでも動作するため、今回紹介するサンプルプログラムもmacOSやWindowsで動作させられるかと思います。

回数券一覧のサンプルを作成する

今回のサンプルプログラムはGitHubで公開しています。

動作イメージは以下のような感じです。

sample7.gif

WebAPIのレスポンスを把握する

Ruby/Gtkでアプリを作り込んでゆく前に、WebAPIのレスポンスを把握しておきます。

回数券一覧(/coupon/list)のレスポンスは以下のようになっています。 $.ResultSet.Coupon[].Name が回数券の名称になります。

http://api.ekispert.jp/v1/json/coupon/list?key=アクセスキーを入力してください
{
  "ResultSet": {
    "Coupon": [
      {
        "Name": "新幹線回数券(グリーン車)"
      },
      ...
      {
        "Name": "こまち4枚回数券(指定席)"
      }
    ],

ここで取得した回数券の名称を回数券詳細(/coupon/detail)のパラメータに指定することで、回数券の詳細情報を取得できます。例えば、「新幹線回数券(グリーン車)」という回数券の詳細情報を取得する場合は以下のようなリクエストになります。

http://api.ekispert.jp/v1/json/coupon/detail?key=アクセスキーを入力してください&name=新幹線回数券(グリーン車)

取得できるレスポンスは以下です。

{
  "ResultSet": {
    "Coupon": [
      {
        "Detail": {
          "Count": "6",
          "Price": {
            "Amount": "47340"
          },
          "ValidPeriod": "3",
          "Direction": "Both"
        },
        "Name": "新幹線回数券(グリーン車):東京都区内:静岡"
      },
      ...

Rubyで回数券情報を取得する

回数券詳細(/coupon/detail)のレスポンスを取得してRubyで利用できる形にするサンプルは以下になります。

#!/usr/bin/env ruby

require 'open-uri'
require 'json'
require 'uri'

ACCESS_KEY = '駅すぱあとWebサービスのアクセスキー'

coupon_name = URI.escape('東北新幹線回数券(自由席)')
url = "http://api.ekispert.jp/v1/json/coupon/detail?key=#{ACCESS_KEY}&name=#{coupon_name}"
JSON.parse(open(url).read)['ResultSet']['Coupon'].each do |item|
  next if item.class != Hash
  str = <<_EOF
    定期券名称: #{item['Name']}
    回数券の枚数: #{item['Detail']['Count']}
    合計金額: #{item['Detail']['Price']['Amount']}
    有効期限(月): #{item['Detail']['ValidPeriod']}
    - - - - - - - - - -
_EOF
  puts str
end

実行結果は以下になります。これでRuby駅すぱあとWebサービスを使用して回数券一覧のデータを取得するところまでできました。

$ ./sample.rb
    定期券名称: 東北新幹線回数券(自由席):東京山手線内:小山
    回数券の枚数: 6
    合計金額: 17880
    有効期限(): 3
    - - - - - - - - - -
    定期券名称: 東北新幹線回数券(自由席):大宮:宇都宮
    回数券の枚数: 6
    合計金額: 16020
    有効期限(): 3
    - - - - - - - - - -

今回使用するRuby/GtkのGUI部品

あとはRuby/Gtkの使い方を把握すればアプリの作成まで漕ぎ着けそうです。
今回は Gtk::WindowGtk::ComboBoxGtk::ListStoreGtk::TreeView の使い方を見てみましょう。

Gtk::Window

まずは基本的な Gtk::Window の使い方です。単にアプリケーションウインドウを表示するだけなので難しいことはありません。

require 'gtk2'

module EWS
  class SampleApp
    def initialize
      window = Gtk::Window.new
      window.set_default_size(320, 240)
      window.show_all
      window.signal_connect("destroy") { Gtk.main_quit }

      Gtk.main
    end
  end
end

if $PROGRAM_NAME == __FILE__
  EWS::SampleApp.new
end

実行すると以下のような表示になります。
Screenshot at 2018-12-23 03-49-23.png

Gtk::ComboBox

続いて Gtk::ComboBox です。文字列データを順次コンボボックスに設定するだけでOKです。また、 Gtk::ComboBox.signal_connect("changed") で選択された文字列を取得できます。
今回は回数券の名称を文字列データに使い、コンボボックスのデータが選択された際に回数券の詳細情報を取得するという振る舞いにすれば良さそうです。

require 'gtk2'

module EWS
  class SampleApp
    def initialize
      window = Gtk::Window.new

      combo = Gtk::ComboBox.new
      %w[apple grape orange banana].each do |label|
        combo.append_text(label)
      end
      combo.signal_connect("changed") do |widget|
        puts(widget.active_text)
      end

      window.add(combo)
      window.show_all
      window.signal_connect("destroy") { Gtk.main_quit }

      Gtk.main
    end
  end
end

if $PROGRAM_NAME == __FILE__
  EWS::SampleApp.new
end

実行すると以下のような表示になります。
Screenshot at 2018-12-23 03-50-28.png

Gtk::ListStore,Gtk::TreeView

最後はツリービュー(今回は表形式)です。これはちょっと複雑なサンプルになります。 Gtk::ListStore でツリービューに入れたいデータの構造を用意し、 Gtk::TreeView に表の列に相当するデータを追加する形になります。

require 'gtk2'

module EWS
  class SampleApp
    COLUMN_ENGLISH, COLUMN_JAPANESE = *(0..1).to_a

    def initialize
      @store = Gtk::ListStore.new(String, String)

      [
        %w[ apple  りんご   ],
        %w[ grape  ぶどう   ],
        %w[ banana ばなな   ],
        %w[ orange おれんじ ],
      ].freeze.each do |item|
        iter = @store.append
        item.each_with_index do |value, index|
          iter[index] = value
        end
      end

      treeview = Gtk::TreeView.new(@store)
      treeview.rules_hint = true
      treeview.search_column = COLUMN_ENGLISH

      add_columns(treeview, '英語',   COLUMN_ENGLISH)
      add_columns(treeview, '日本語', COLUMN_JAPANESE)

      sw = Gtk::ScrolledWindow.new(nil, nil)
      sw.shadow_type = Gtk::SHADOW_ETCHED_IN
      sw.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC)
      sw.add(treeview)

      window = Gtk::Window.new
      sw = Gtk::ScrolledWindow.new(nil, nil)
      sw.shadow_type = Gtk::SHADOW_ETCHED_IN
      sw.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC)
      sw.add(treeview)

      window = Gtk::Window.new
      window.add(sw)
      window.set_default_size(320, 240)
      window.show_all
      window.signal_connect("destroy") { Gtk.main_quit }

      Gtk.main
    end

    def add_columns(treeview, name, index)
      renderer = Gtk::CellRendererText.new
      column = Gtk::TreeViewColumn.new(name, renderer, 'text' => index)
      column.set_sort_column_id(index)
      treeview.append_column(column)
    end
  end
end

if $PROGRAM_NAME == __FILE__
  EWS::SampleApp.new
end

実行すると以下のような表示になります。
Screenshot at 2018-12-23 04-16-34.png

組み合わせてアプリを作る

ここまでで必要な材料がそろったので、把握できた内容を組み合わせてアプリを作ります。
サンプルコートは以下になります。これまで説明した内容を組み合わせた形になっているので、ぜひソースコードを参照してみてください。

実行画面は以下のようになります。

Screenshot at 2018-12-23 03-59-00.png

まとめ

駅すぱあとWebサービス回数券一覧を使用したアプリ作成例を紹介しました。Ruby/GtkはLinux/macOS/Windowsのそれぞれの環境で動作できるようになっている(と思う)ので、今回のアプリはちょっと便利かもしれません。
また、回数券一覧(/coupon/list)と回数券詳細(/coupon/detail)はAmazon SaaSストアで購入できる駅すぱあとWebサービスで利用可能であるため、ぜひ皆様の環境でもAPIを利用して面白い活用事例を見つけてもらえると幸いです。

valsitoh
val
経路検索システム「駅すぱあと」をはじめ、全国のデータと高い信頼性をベースにさまざまなサービスを展開。
https://www.val.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away