Sinatra+ActiveRecord+MySQLで、簡単APIサーバ構築

  • 219
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

サーバを使ったiPhoneアプリを作りたかったので、簡単にサーバ側作れないか調べてみました。結論として結構簡単に出来る事が分かったのでメモメモ。

参考にした記事

Sinatra+ActiveRecord+SQLite3で,軽量なWeb-DB連携例 | tamo's blog

大分参考にさせて頂きました。ありがとうございます!
仕事ではMySQLを使う事が多いので、SQLite3ではなくMySQLを使う事にしました。

手順

  1. Ruby,MySQLをインストール
  2. データベースを作成
  3. Gemfileを作成とインストール
  4. database.ymlを作成
  5. Rubyファイルを作成
  6. 実行
  7. 動作確認

1. Ruby,MySQLをインストール

結構な量になったので別記事にまとめました。ここが一番面倒(´Д`)
- Ruby,MySQLの環境を構築する(Mac版) #MySQL #Mac #Ruby #homebrew - Qiita
- Ruby,MySQLの環境を構築する(Linux版) #MySQL #Ruby #Linux - Qiita

2. データベースを作成

MySQLの初歩的なコマンドを知っていれば、ここは問題ないと思います。
ActiveRecordの流儀で、テーブル名は複数形にする必要がある事だけ注意!
サンプルとして、タイトル, 詳細文, 作成日時, 更新日時を持つ、topicsテーブルを生成してみます。

mysql> create database hoge;
Query OK, 1 row affected (0.00 sec)

mysql> use hoge
Database changed

mysql> create table topics ( 
    ->  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    ->  title VARCHAR(255) NOT NULL,
    ->  description VARCHAR(255) NOT NULL,
    ->  created_at DATETIME NOT NULL,
    ->  updated_at DATETIME NOT NULL,
    ->  PRIMARY KEY(id)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> desc topics;
+-------------+------------------+------+-----+---------+----------------+
| Field       | Type             | Null | Key | Default | Extra          |
+-------------+------------------+------+-----+---------+----------------+
| id          | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| title       | varchar(255)     | NO   |     | NULL    |                |
| description | varchar(255)     | NO   |     | NULL    |                |
| created_at  | datetime         | NO   |     | NULL    |                |
| updated_at  | datetime         | NO   |     | NULL    |                |
+-------------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

サンプルデータを登録

動作確認をする為のサンプルデータを入れておきます。

mysql> insert into topics values(1, "title1", "description1", now(), now());
Query OK, 1 row affected (0.00 sec)

mysql> insert into topics values(2, "title2", "description2", now(), now());
Query OK, 1 row affected (0.01 sec)

mysql> insert into topics values(3, "title3", "description3", now(), now());
Query OK, 1 row affected (0.00 sec)

mysql> select * from topics;
+----+--------+--------------+---------------------+---------------------+
| id | title  | description  | created_at          | updated_at          |
+----+--------+--------------+---------------------+---------------------+
|  1 | title1 | description1 | 2013-05-19 21:29:21 | 2013-05-19 21:29:21 |
|  2 | title2 | description2 | 2013-05-19 21:29:29 | 2013-05-19 21:29:29 |
|  3 | title3 | description3 | 2013-05-19 21:29:38 | 2013-05-19 21:29:38 |
+----+--------+--------------+---------------------+---------------------+
3 rows in set (0.01 sec)

3. Gemfileを作成とインストール

次に、使用するgemファイルを管理するファイルを作ります。

# ひな形ファイルの作成
$ bundle init
Writing new Gemfile to /home/u1/hoge/Gemfile

# 編集
$ vi Gemfile
source "https://rubygems.org"

gem "activerecord"
gem "mysql2"
gem "sinatra"

# 必要なGemのインストール
$ bundle install --path vendor/bundle

ActiveRecordとMySQLを使うのでそれぞれのgemを記入。
RubyからMySQLを使いたい時はmysql2というのを使うようです。

参考:RubyでMySQLに繋ぐためのruby-mysqlとmysql2 - tagomorisのメモ置き場

4. database.ymlを作成

プログラムからDBにアクセスする為に、DB情報を書いた設定ファイルを作ります。
各値は、自分の環境に合わせて設定して下さい。

development:
  adapter: mysql2
  database: hoge
  host: localhost
  username: root
  password: xxxxxx
  encoding: utf8

5. Rubyファイルを作成

ようやくコードを書きます。長かった。。
使うのはタイトルにある通りSinatraです。

# coding:utf-8
require 'active_record'
require 'mysql2'
require 'sinatra'

# DB設定ファイルの読み込み
ActiveRecord::Base.configurations = YAML.load_file('database.yml')
ActiveRecord::Base.establish_connection('development')

class Topic < ActiveRecord::Base
end

# 最新トピック10件分を取得
get '/topics.json' do
  content_type :json, :charset => 'utf-8'
  topics = Topic.order("created_at DESC").limit(10)
  topics.to_json(:root => false)
end

# トピック投稿
post '/topic' do
  # リクエスト解析
  reqData = JSON.parse(request.body.read.to_s) 
  title = reqData['title']
  description = reqData['description']

  # データ保存
  topic = Topic.new
  topic.title = title
  topic.description = description
  topic.save

  # レスポンスコード
  status 202  
end

基礎的な機能として、

  • 最新トピック10件分を取得する GET /topics.json
  • トピックを登録する POST /topic

を作ってみました。

6. 実行

書いたコードを動かします。ここでもちょっとはまった事があったので注意!(参考:Sinatraがデフォルトでは外部から繋がらなくなってたよ #Sinatra #Ruby - Qiita [キータ]

$ bundle exec ruby hoge.rb -o 0.0.0.0
[2013-05-19 21:37:56] INFO  WEBrick 1.3.1
[2013-05-19 21:37:56] INFO  ruby 1.9.3 (2013-02-06) [x86_64-linux]
== Sinatra/1.4.2 has taken the stage on 4567 for development with backup from WEBrick
[2013-05-19 21:37:56] INFO  WEBrick::HTTPServer#start: pid=10667 port=4567

7. 動作確認

最新のトピックを取得

プログラムを動かしてるサーバの /topics.json にリクエストを送って動作確認をします。仮にlocalhostで動かした場合は、http://localhost:4567/topics.json
GETリクエストを送ると、以下のようなJSON形式のレスポンスが返ってきます。これをベースに変更を加えていけば使えそう。

[
    {
        "created_at": "2013-05-19T21:29:38+09:00", 
        "description": "description3", 
        "id": 3, 
        "title": "title3", 
        "updated_at": "2013-05-19T21:29:38+09:00"
    }, 
    {
        "created_at": "2013-05-19T21:29:29+09:00", 
        "description": "description2", 
        "id": 2, 
        "title": "title2", 
        "updated_at": "2013-05-19T21:29:29+09:00"
    }, 
    {
        "created_at": "2013-05-19T21:29:21+09:00", 
        "description": "description1", 
        "id": 1, 
        "title": "title1", 
        "updated_at": "2013-05-19T21:29:21+09:00"
    }
]

トピックの登録

http://localhost:4567/topic に、以下のようなBodyのPOSTリクエストを送ります。すると202レスポンスが返ってきます。
ちなみにPOSTリクエストを送るのは、Chrome拡張機能のDevHTTPClientを使ってます。

{
  "title": "title4",
  "description": "description4"
}

ちゃんと登録されてるかを、GET /topics.json で確認。

[
    {
        "created_at": "2013-05-19T21:48:56+09:00", 
        "description": "description4", 
        "id": 4, 
        "title": "title4", 
        "updated_at": "2013-05-19T21:48:56+09:00"
    }, 
    {
        "created_at": "2013-05-19T21:29:38+09:00", 
        "description": "description3", 
        "id": 3, 
        "title": "title3", 
        "updated_at": "2013-05-19T21:29:38+09:00"
    }, 
    {
        "created_at": "2013-05-19T21:29:29+09:00", 
        "description": "description2", 
        "id": 2, 
        "title": "title2", 
        "updated_at": "2013-05-19T21:29:29+09:00"
    }, 
    {
        "created_at": "2013-05-19T21:29:21+09:00", 
        "description": "description1", 
        "id": 1, 
        "title": "title1", 
        "updated_at": "2013-05-19T21:29:21+09:00"
    }
]

おわり

いやーほんとに簡単に書けますね。
あとは、Sinatra と ActiveRecord を勉強しながらちゃんと実装していこうと思います。あと色々自動化していきたいなー。

何か間違ってる所とかありましたらご指摘お願いしますm(_ _)m