未分類」カテゴリーアーカイブ

話題のオープン職務経歴書を書いてみる

概要

以下の記事に一通り目を通して強く影響を受けたので、自分なりに解釈、アレンジしながら書いてみた。

名称について

参考記事では「職務経歴書OSS化」というワードが使われているが、Githubで公開してるだけでOSS要素はあまり無いと思った。本記事ではリクナビの「オープンエントリーシート」に準えて、「オープン職務経歴書」といワードを用いることにする。

といっても、後述のデメリットから職務経歴書というよりはスキルシートに近いので、「オープンスキルシート」とするのが正確かもしれないが、そうすると元の参考記事からさらに離れてしまうので、職務経歴書のワードはそのまま使うことにした。

オープン職務経歴書の概要

名の通り、グローバルに公開した職務経歴書。元記事に倣って、Githubに公開することを想定する。

職務経歴書と言えば転職活動時に使う前提のものとなるが、書き方によっては転職の意思がなくても多くのメリットが得られる。自分で書いてみた感触と、元記事で紹介されている情報をあわせて、メリット/デメリットを整理すると以下の通りになる。

メリット

  • 継続して書いておくと、いざ転職活動などで必要になった際に困らない
  • 自身の経験/スキルを客観視することができる
  • 他人に自身の経験/スキルを説明しやすくなる
  • 他人に自身の職務経歴書を校正してもらえる
  • 話のタネになる。技術アピールのきっかけになる
  • お金がかからない
  • Githubを使えばMarkdownでサクッと書いてサクッと公開できる

デメリット

  • 公開できる情報に制限がある
    — 個人情報
    — 企業情報
    — 各種製品名
  • 記載内容やフォーマットに統一性がない

オープン職務経歴書の例

職務経歴書(履歴書)を英語でCurriculum-Vitaeというらしく、Githubでこのワードを検索すると、リポジトリが山ほど出てくる。
Github Curriculm-Vitae

もちろん、本記事の内容に関係ないリポジトリも数多くあるが、適当にリポジトリを選択してみると、日本人/外国人問わず、多くの職務経歴書(履歴書)が確認できる。また、本記事ではMarkdownを想定しているが、HTMLやPDF、Texなど、様々なフォーマットでも公開されている。

記載内容

既存のオープン職務経歴書をいくつか見てみると、やはり人によって記載している内容は大きく異なる。登壇歴や出版歴など、輝かしい功績を記載している人もいれば、具体的な会社名や製品名を出した、本物の職務経歴書のような人もいる。

本記事では、私がグローバルに公開しても確実に問題ないと思った範囲についてのみ記載することにする。そのため、具体的な会社名、製品名は伏せ、どのような技術を用いた業務を行ってきたかを確認できるようにする。

公開できる範囲で、精一杯のアピールができるように、今回は以下のような構成にした。

基本情報

氏名、メールアドレス、各種SNSアカウントなど、公開できる範囲で記載。私は割りと本名をネット上で利用しているのでここは気にしなかった。流石に電話番号や住所は書かない。

資格

死角?ありません、無敵です。
とりあえずIPA資格だけ、名前と取得年月を記載。運転免許とか簿記とか、エンジニアに本質的に関わらないものは割愛。

自然言語

日本語/英語どのぐらいいけるか。あえて正直に書いた。

プログラミング言語/フレームワーク

趣味、実務問わず、一定期間以上使っていた言語及びフレームワークを列挙。それぞれの言語について、実務の経験年数と備考を記述。

実務経歴

これまで実務で関わってきたプロジェクトを、特定されないような大雑把な表現で紹介。個々のプロジェクトについて、期間及び使用技術、担当業務などを記載。

成果物

以上を元に、以下のオープン職務経歴書を作成した。
Sa2knight/Curriculum-Vitae

所感

  • 転職うんぬんでなく、経歴を客観視しつつ常に更新し続けることが醍醐味だと感じた
  • 「君、何が出来るの?」的な問に対して今後はURLを張るだけで解決しそう
  • そもそもエンジニアがこういった情報を紙で出すことが前時代的なのでは
  • Githubに置いてるので、そのままその人のソースコードを閲覧できるのはエンジニア的には大きいかも
  • 経験年数で技量を測るのはナンセンスだと思うけど現状コレが主流なので仕方ない
  • Markdownだとテーブルのスタイリング調整ができないのでちょっと辛い

RubyプログラマがPython3を勉強した話

概要

Rubyを使い始めて2年弱の私が、前々から気にはなっていたが使ったことのないPythonにようやく手を出したお話。
私がひと夏の間に行った、基本的な勉強についての備忘録を残す。

Pythonのバージョンについて

Pythonのバージョンは2.x系(Python2)と3.x系(Python3)が存在するが、2と3では互換性のない変更が多く含まれており、実質別言語として扱われることが多い。

既存システムの多くはPython2で書かれていること、Python3では動かない有用なライブラリが存在することなどから、単に新しいという理由でPython3を採用することはできないが、今回は以下の理由からPython3を採用する。

  • Python2は2010年以降更新されていないため
  • Python2は2020年で公式のサポートが打ち切られるため
  • Python3は現在も積極的なバージョンアップが行われており、今後は完全に3に以降する流れのため

Python3.6.2のインストール

今回は現在の最新のPythonである3.6.2を、Debianにインストールした。
インストールには、Pythonのバージョン管理ツールであるpyenvを用いることにした。インストール手順については、以下記事にまとめた

Python3.6.2をインストールして、Wikipediaをクロールするスクリプトを書く | QSのウェブ開発とか

Python3の基本の勉強

はじめに、Python3の基本的な使い方、文法などの勉強には以下ページを利用した。広く浅く、かつ丁寧にPython3の基本が書かれた良い記事だったので、自身を持ってオススメできる。

Python3基礎文法 – Qiita

Rubyなどのスクリプト言語をある程度経験している人なら、Python3の基本的な範囲については特に戸惑うこと無く馴染めると思う。

Python3のトレーニング

前項で基本的なPython3の書き方、文法は抑えられた。
しかし、まだまだPythonの感覚は掴めていないので、競技プログラミングの問題をPython3を用いて沢山解くことで、Pythonの感覚を掴むことにした。

今回は、私が個人的にもよく利用していたpaizaのスキルチェックを利用した。

paizaのスキルチェック問題は、以下の5段階の難易度がある

  • Dランク: ウォーミングアップレベル
  • Cランク: 初級レベル
  • Bランク: 中級レベル
  • Aランク: 上級レベル
  • Sランク: 超上級レベル

Aランク以上は、言語の使い方よりも、高度なアルゴリズム設計が求められる問題(そもそも解けないのが殆ど)となるので対象外とし、D,C,BランクをPython3を用いて解くことにした。

実際に問題を解いてみると、多言語ではすんなり書けることがPython3ではなかなか書けない。やりたいことをPython3で実現する方法が全然わらないのだ。そういった壁に直面するたびに、実現方法を調べては、Python節を身につけることを繰り返し、D,C,Bランク合わせて30問ぐらい解いたところである程度の理解は出来たと判断して終了した。

Python3によるWebスクレイピング

次に、Pythonと言えばWebスクレイピング/クローリングなので(偏見?)、HTTPライブラリと、XMLパーサライブラリを用いて色々遊んだ。
その中で作成した、Wikipediaをランダムにクロールするスクリプトについては、以下記事にまとめた

Python3.6.2をインストールして、Wikipediaをクロールするスクリプトを書く | QSのウェブ開発とか

チャットワークAPIをRubyで利用する

前提

以下の環境で実装及び動作確認を行った

要素 バージョン
debian 8.6
ruby 2.2.2

概要

チャットワークのAPIを使える状態にし、Rubyからチャットワークの各種操作を行う。今回の成果物についてはGithubから閲覧、ダウンロード可能。

チャットワークとは

ビジネス向けのチャットツールで以下の特徴がある

  • 基本無料
  • ルームを個別に作成し、複数人でチャット可能
  • ルームごとにタスクの管理が可能
  • ファイルの共有が可能
  • 音声通話/ビデオ通話も可能

チャットワークAPIとは

チャットワークの基本的な機能をプログラムから利用するためのRestFullなAPI。
現在(2017/05/20)は、プレビュー版のみの限定公開となっており、APIを利用するためには申請する必要がある

チャットワークAPIの利用準備

チャットワークAPIの利用申請

チャットワークにログインしているブラウザで、利用申請ページにアクセスし、APIの利用申請を行う。利用が可能な状態になると、チャットワークで登録しているメールアドレスに、以下のような通知メールが届くのでそれまで待機(1営業日程度?)

いつもお世話になっております。
チャットワーク サポートデスクです。

チャットワークAPI(プレビュー版)のご利用が可能となりましたので
お知らせいたします。

APIトークンの確認

メールが届いたら、ブラウザでチャットワークを開き、「動作設定」を開くと、以下のようにAPI発行メニューが追加されていることが確認できる。

パスワードを入力することで、以下のようにAPIトークンを確認することができる(画像のトークンはダミー)
トークンはこの画面で更新可能なので、必要に応じて更新する。

APIトークンはプログラムでAPIを利用するのに必須のため、環境変数に保存しておく。以下のコマンドをbashrcに追記するのがベスト

$ export CHATWORKAPI=hogehogehogehogehogehogehogehogehoge

APIの仕様確認

APIドキュメントを確認すれば、APIのシンプルな仕様を確認できるが、ここでは以下さえ抑えておけば問題ない

  • APIのエンドポイントは https://api.chatwork.com/v2
  • リクエストは必ずHTTPSを用いる
  • リクエストヘッダに”X-ChatWorkToken”というキーでAPIトークンを指定する必要がある
  • APIの制限は5分で100回程度
  • レスポンスは必ずJSONで返却される
  • ただし、APIの成否判定の多くはレスポンスヘッダに含まれている

APIの動作確認

さっそくプログラムを作っても良いが、API及びAPIトークンが正しく機能しているかを確認するため、curlコマンドで試しにAPIを呼び出してみる。

$ curl https://api.chatwork.com/v2/me GET -H "X-ChatWorkToken: hogehoge"

上記curlコマンドは、以下のHTTPリクエストを送信する

  • リクエスト先は https://api.chatwork.com/v2/me (自身のステータスを取得するAPI)
  • メソッドにGETを用いる
  • リクエストヘッダに”X-ChatWorkToken: hogehoge”を含める

すると、以下のレスポンスが返却される

{"account_id":2091543,"room_id":59255776,"name":"笹木信吾","chatwork_id":"","organization_id":1118988,"organization_name":"","department":"","title":"","url":"https://github.com/Sa2Knight","introduction":"","mail":"sasaki@91932.com","tel_organization":"","tel_extension":"","tel_mobile":"090-7067-7376","skype":"","facebook":"","twitter":"","avatar_image_url":"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}

レスポンスを見る限り、無事にチャットワークAPIを用いて、自身のユーザ情報を取得できていることがわかる。

RubyからチャットワークAPIを利用する

Chatworkクラスの作成

とりあえずチャットワークAPIをRubyで叩くためのエンドポイントとなるChatworkクラスを作成する。

require 'net/http'
require 'uri'
require 'json'
require 'date'

class Chatwork
  @@API_BASE = 'https://api.chatwork.com/v2'

  # tokenを指定してオブジェクトを生成
  # tokenを省略した場合、環境変数を参照する
  def initialize(token = nil)
    @token = token || ENV['CHATWORKAPI']
  end

end

例によって、APIトークンを指定してオブジェクトを生成する。トークンの指定を省略した場合に、環境変数”CHATWORKAPI”を参照するようにしてあるので、今回はそれを前提にする。APIのエンドポイントは全てのAPIで共通なので、クラス定数@@API_BASEで定義しておく。

HTTP通信するメソッドの実装

どのAPIでも共通となる、HTTPリクエストを投げてレスポンスを戻すメソッドを作成する。

createRequestObjectは、そのヘルパーメソッドで、指定したHTTPメソッド(:get,:post,:put,:delete)に応じた、空のHTTPRequestオブジェクトを返却する。

createHttpObject、対象のURL,HTTPメソッド,パラメータを指定すると、以下のことをしてくれる。
1. APIのエンドポイントと各APIのURLを結合し、URIオブジェクトを生成する
2. URIを元にHTTPオブジェクトを生成し、SSLを有効にする
3. (メソッドがGETの場合) URIにパラメータを付与する
4. メソッドに応じたRequestオブエクトを取得
5. リクエストヘッダにAPIトークンを付与
6. (メソッドがGET以外の場合) リクエストボディにパラメータを付与する
7. リクエストを送信し、レスポンスを戻す

## HTTPリクエストを送信する
def createHttpObject(url, method, params = {})
  api_uri = URI.parse(@@API_BASE + url)
  https = Net::HTTP.new(api_uri.host, api_uri.port)
  https.use_ssl = true
  api_uri.query = URI.encode_www_form(params) if method == :get
  req = createRequestObject(method, api_uri)
  req["X-ChatWorkToken"] = @token
  req.set_form_data(params) unless method == :get
  https.request(req)
end
## リクエストオブジェクトを生成する
def createRequestObject(method, uri)
  case method
    when :get
      return Net::HTTP::Get.new(uri.request_uri)
    when :post
      return Net::HTTP::Post.new(uri.request_uri)
    when :put
      return Net::HTTP::Put.new(uri.request_uri)
    when :delete
      return Net::HTTP::Delete.new(uri.request_uri)
  end
end

上記のメソッドを用いて、各APIに対応したメソッドを実装する。

各APIごとのメソッドを実装する

あとはAPIドキュメントを参考に、各種APIを呼び出すためのメソッドを順に実装する。全て実装するのは疲れるので、とりあえず以下を実装した。残りもおいおい実装する予定

メソッド名 内容
me 自身のユーザ情報を取得
myStatus 自身の未読数、未読To数、未完了タスク数を取得する
myTasks 自身のタスク一覧を取得する
myContact 自身のコンタクト一覧を取得する
myRooms 自信が参加しているチャット一覧を取得する
getRoom チャットの情報を取得する
createRoom 新しいチャットを作成する
updateRoom チャットの情報を更新する
getRoomMembers チャットに参加しているユーザ一覧を取得する
getRoomMessages チャットのメッセージ一覧を取得する
sendMessage チャットに新規メッセージを投稿する
getRoomTask チャット内のタスク一覧を取得する
getTask タスク情報を取得する
createTask タスクを新規登録する
getRoomFiles アップロードされたファイル一覧を取得する
getFile アップロードされたファイルの情報を取得する

※ 何故か既存のタスクを操作するためのAPIが無い。タスクを作ることは出来るのに完了したり編集したりすることがでない謎。

実装例

どのメソッドも基本的に実装内容は同じ(URL、メソッド、パラメータの有無などが異なるだけ)なので、全てを記載しないが、ここでは以下の2種類について記載する。

myStatus(自身の未読数、未読To数、未完了タスク数を取得する)

myStatusは特定のURLに対して、パラメータなしでシンプルにGETするだけなので、以下のように実装した

def myStatus
  url = '/my/status'
  res = createHttpObject(url, :get)
  return JSON.parse(res.body)
end

createTask(タスクを新規登録する)

createTaskは少しだけ複雑で、タスクを新規登録するルーム(チャット)IDとタスクの内容、担当者のユーザID一覧を指定して登録する。また、オプションでタスクの期限を指定することができる。

APIが要求するパラメータでは、担当者のユーザID一覧はカンマ区切りで、期限はUNIXTIMEで指定する必要がある。これはそのままだと使いづらいので、メソッド側では担当者のユーザID一覧を配列で、期限をDateTimeオブジェクトで受け取るようにしている。メソッド内でそれをAPI用に変換して実行している。

def createTask(room_id, body, to_ids = [], params = {})
  url = '/rooms/' + room_id + '/tasks'
  params[:body] = body
  params[:to_ids] = to_ids.join(',')
  params[:limit] = params[:limit].to_i if params[:limit].class == Time
  res = createHttpObject(url, :post, params)
  return res.body ? JSON.parse(res.body) : []
end

動作確認

本項では、以下の手順で動作確認する

  1. 動作確認用の新しいチャットルームを作成する(自分のみ参加)
  2. チャット内で適当に発言する
  3. チャット内にタスクを追加する
  4. チャットルームの情報を取得する
  5. チャットルームの発言一覧を取得する
  6. チャットルームのタスク一覧を取得する

なお、動作確認中に使用するユーザのIDを’2091543′,及び作成するチャットルームのIDを’76097933’とし、以下のようにChatworkオブジェクトを生成済みとする。

cw = Chatwork.new

チャットルームを作成

動作確認用に、「API動作確認ルーム」というチャットルームを作成する。参加者は、自身のみを管理者ユーザとして設定する。

cw.createRoom('API動作確認ルーム', ['2091543'], :description => '動作確認用のルームです')

実行すると、以下のように新規チャットルームが作成されたことがわかる。

チャット内で適当に発言する

「こんにちは,APIからの投稿です」という発言を、先ほど作成したルームに対して送信する

cw.sendMessage('76097933', 'こんにちは、APIからの投稿です')

実行すると、発言が送信されていることがわかる

チャット内にタスクを追加する

「WordPressを更新する」というタスクを、本日(5/21)を締め切りにして登録する

cw.createTask('76097933', 'WordPressを更新する', ['2091543'], :limit => Time.now)

実行すると、タスクが登録されたことが確認できる

チャットの情報を取得する

先程作成したチャットルームの情報を取得する。

cw.getRoom('76097933')

実行すると、チャットルームの基本的な情報を確認することができる

{"room_id"=>76097933, "name"=>"API動作確認ルーム", "type"=>"group", "role"=>"admin", "sticky"=>false, "unread_num"=>0, "mention_num"=>0, "mytask_num"=>1, "message_num"=>3, "file_num"=>0, "task_num"=>1, "icon_path"=>"https://appdata.chatwork.com/icon/ico_group.png", "description"=>"動作確認用のルームです", "last_update_time"=>1495307674}

チャットルーム内のメッセージ一覧を取得する

メッセージ一覧(と言っても先程の1件のみだが)を取得する

cw.getRoomMessages('76097933')

メッセージ一覧及び個々のメッセージの発言者の情報が取得できることがわかる

[{"message_id"=>"2020162066", "account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "body"=>"[info][title][dtext:chatroom_groupchat_created][/title][dtext:chatroom_chatname_is]API動作確認ルーム[dtext:chatroom_set]\n\n[dtext:chatroom_description_is]動作確認用のルームです[dtext:chatroom_set]\n\n[dtext:chatroom_member_is][piconname:2091543][dtext:chatroom_added][/info]", "send_time"=>1495307261, "update_time"=>0}, {"message_id"=>"2020162308", "account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "body"=>"こんにちは、APIからの投稿です", "send_time"=>1495307439, "update_time"=>0}, {"message_id"=>"2020162647", "account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "body"=>"[info][title][dtext:task_added][/title][task aid=2091543 st=open lt=1495378799]WordPressを更新する[/task][/info]", "send_time"=>1495307674, "update_time"=>0}]

チャットルーム内のタスク一覧を取得

こちらも先程登録した1件のみだが、タスクの情報を取得する

p cw.getRoomTasks('76097933')

実行すると、タスク及びそのメタ情報が確認できる

[{"task_id"=>68592616, "account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "assigned_by_account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "message_id"=>"2020162647", "body"=>"WordPressを更新する", "limit_time"=>1495378799, "status"=>"open"}]

所感

  • チャットワークのAPIはそれは見事なRestFull設計で感動を覚えるほど使いやすかった
  • だがまだプレビュー版で、既存タスクの更新ができないなど、痒いところに手が届かないので正式リリースが待たれる
  • APIを叩くライブラリを作ったはいいが、問題はこれをどう活用するか。そこは全然考えてない。おそらくサーバを監視して報告をチャットワークに流すとか、プロジェクト管理ツールの更新をチャットワークでも通知するとか、読み込みより書き込みがメインになるとは思う

参考

Railsでサクッと電子掲示板を作成する

前提

以下の環境で開発、動作確認を行う

要素 バージョン
Ubuntu 16.04.2
Ruby 2.4.1
Ruby on Rails 5.1.0
mySQL 14.14

また、上記環境はDockerで構築したコンテナで、環境構築についてはコチラを参照

概要

本記事では、1.前提 の環境にて、簡易的な電子掲示板サービスの開発を行う。電子掲示板サービスの概要は以下の通り。
なお、本記事ではRuby on Railsに関する基本的な説明は割愛している。railsの経験がない人が雰囲気で何か掴めれば程度の内容。

電子掲示板の概念

  • 電子掲示板には0個以上のトピックが存在する
  • トピックにはタイトルが存在する
  • トピックには0個以上の書き込みが存在し、全ての書き込みは一つのトピックに属する
  • 書き込みには投稿者名と本文が存在する

画面イメージ

  • ユーザはトップページにアクセスすると、トピック一覧を確認することができる
  • トピック一覧画面の末尾には、新規トピック投稿フォームが存在し、新規投稿を行うことができる
  • 各トピックごとに、「削除」リンクが付与されており、それをクリックするとトピックを削除することができる
  • トピック削除時に、トピックに紐付いた書き込みもあわせて削除する
  • ユーザはトピック名をクリックすることで、そのトピックの書き込み一覧を確認することができる
  • トピックの書き込み一覧画面の末尾には、新規投稿のフォームが存在し、新規投稿を行うことができる

データベーススキーマ

電子掲示板サービスのスキーマは以下の通り

実装

実装(準備編)

rails newコマンドで、railsアプリケーションの雛形を作成することができる。ここでは、使用するデータベースをmysqlに指定して雛形を作成している(デフォルトではsqlite)

$ rails new mybbs -d mysql
(省略)
$ cd mybbs

作成したrailsアプリケーションの雛形を元に、データベースを作成する。アプリケーション名(mybbs)を元に、development用とtest用の2つのデータベースが作成される。本記事ではテストを対象としないので、mybbs_developmentデータベースを基本的に使用する。

$ rake db:create
Created database 'mybbs_development'
Created database 'mybbs_test'

実装(トピック編)

本項では、複数の書き込みを束ねる「トピック」に関する実装を行う

トピックモデルを作成

ここでは、rails generateコマンドを用いて、topicモデルを作成する。
topicモデルに対応づいたtopicsテーブルに必要な属性は以下の通り。
* id
* title
* created_at
* updated_at
id,created_at,updated_atは、自動生成してくれるため、ここで明示的に指定する必要があるのはtitleだけなので、以下のようなコマンドでtopicモデルを作成する。

$ rails generate model topic title:string
Running via Spring preloader in process 1142
      invoke  active_record
      create    db/migrate/20170505141519_create_topics.rb
      create    app/models/topic.rb
      invoke    test_unit
      create      test/models/topic_test.rb
      create      test/fixtures/topics.yml

すると、以下のマイグレーションファイル(テーブルを作成するスクリプト)が生成されるので

class CreateTopics < ActiveRecord::Migration[5.1]
  def change
    create_table :topics do |t|
      t.string :title
      t.timestamps
    end
  end
end

以下のコマンドでマイグレーション(テーブル作成)実行

$ rake db:migrate
== 20170505141519 CreateTopics: migrating =====================================
-- create_table(:topics)
   -> 0.1048s
== 20170505141519 CreateTopics: migrated (0.1050s) ============================

データベース内にtopicsテーブルが作成されていることを確認

mysql> show columns from topics;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| title      | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

動作確認用Topicsレコードの作成

Railsでは、console機能を用いてCLI上でRailsアプリケーションに対するスクリプトを行うことができる。ここでは作成したTopicsモデルを用いて、console上でテストデータを登録する

$ rails console
Running via Spring preloader in process 1312
Loading development environment (Rails 5.1.0)
irb(main):001:0> Topic.create(:title => 'プロ野球について')
=> #<Topic id: 2, title: "プロ野球について", created_at: "2017-05-05 14:27:31", updated_at: "2017-05-05 14:27:31">
irb(main):002:0> Topic.create(:title => 'ラーメンについて')
=> #<Topic id: 3, title: "ラーメンについて", created_at: "2017-05-05 14:27:49", updated_at: "2017-05-05 14:27:49">
irb(main):003:0> Topic.create(:title => 'プログラミングについて')
=> #<Topic id: 4, title: "プログラミングについて", created_at: "2017-05-05 14:27:54", updated_at: "2017-05-05 14:27:54">

テーブルにレコードが追加されていることを確認

mysql> select * from topics;
+----+-----------------------------------+---------------------+---------------------+
| id | title                             | created_at          | updated_at          |
+----+-----------------------------------+---------------------+---------------------+
|  2 | プロ野球について                  | 2017-05-05 14:27:31 | 2017-05-05 14:27:31 |
|  3 | ラーメンについて                  | 2017-05-05 14:27:49 | 2017-05-05 14:27:49 |
|  4 | プログラミングについて            | 2017-05-05 14:27:54 | 2017-05-05 14:27:54 |
+----+-----------------------------------+---------------------+---------------------+
3 rows in set (0.00 sec)

トピックのコントローラとビューを作成

同様にトピック用のビューとコントローラを作成する。トピックを一覧するページ(index)と、トピックの詳細を表示するページ(show)の2つが欲しいので、以下のコマンドを実行する。

$ rails generate controller topics index show
(省略)

上記コマンドを実行することで、トピック用のコントローラ/ビュー及びルーティングの設定が作成される。

自動で生成されたルーティングだけだと少し足りないので、db/routes.rbに以下のように記述する。

Rails.application.routes.draw do
  get 'topics/index'
  get 'topics/show/:id' => 'topics#show', as: :topics_show
end

上記の例だと、’topics/show/:id’へのアクセスは、tpicsコントローラのshowメソッドが受け取る。このルーティングに対して、tpics_showという識別子を付与することで、プログラムからルーティングを特定することができる。

トピック一覧を画面に表示する機能を実装

実装の第一段階として、”/topics/index”アクセス時に、データベースに登録されているトピックの一覧を画面上に表示する。

コントローラの設定

/topics/indexアクセスは、topics_controllerのindexメソッドで受け取るので、そこでトピックの一覧をDBから取得し、ビューに受け渡す。
Tpic.allは、topicsテーブルの全ての行を取得する。

class TopicsController < ApplicationController
  def index
    @topics = Topic.all
  end
end

ビューの設定

railsでは、標準でテンプレートエンジンとしてERBを採用している。そのため、以下のようにHTML内でRubyスクリプトを挿入することができるので、コントローラから受け取った@topicsの数だけ、トピックのタイトルを表示している。

link_toは、railsのヘルパーメソッドで、aタグを生成してくれる。

<h1>トピック一覧</h1>
<ul>
  <% @topics.each do |topic| %>
    <li><%= link_to topic.title, topics_show_path(topic.id) %></li>
  <% end %>
</ul>

動作確認

以上より、/topics/indexにアクセスした際の画面が以下の通り。動作確認用に登録したトピックの一覧が画面に表示されていることが確認できる。

トピックを新規登録する機能を実装

本項では、トピックの新規登録機能を実装する。新規登録用のフォームはトピック一覧画面の一番下に設置し、そこからタイトルを入力して登録できるようにする。

ルーティングの追加

新規登録用フォームから、’tpics/create’に対してPOSTすることで新規登録を実行できるようにしたいので、ルーティングに以下を追加する

post 'topics/create' => 'topics#create'

コントローラの設定

新規登録用フォームは、トピック一覧ページに表示するため、topicコントローラのindexメソッドにて、@newTopicを生成する。これは、後述するform_forメソッドで必要になるので、ここでは割愛する。

def index
  @topics = Topic.all
  @newTopic = Topic.new
end

また、createメソッドは、新規登録用フォームからPOSTされたデータを受け取るので、ここでPOSTデータを元に新たにtopicsレコードを生成する。生成後は、トピック一覧画面にリダイレクトする。

def create
  @topic = Topic.new(params[:topic].permit(:title))
  @topic.save
  redirect_to topics_index_path
end

ビューの設定

ビューでは、railsのヘルパーメソッドである、form_forメソッドを用いてフォームを自動生成する。
form_forでは、formが登録する対象のモデル(ここでは@newTopic)を指定することで、良い感じのフォームを作成してくれる。

<h1>トピック新規登録</h1>
<%= form_for @newTopic, :url => {:action => 'create'} do |f| %>
  <%= f.text_field :title %>
  <%= f.submit %>
<% end %>

動作確認

以上より、トピックの新規登録ができるようになった

トピックを削除する機能を実装

トピックの削除は、トピック一覧のトピック名の横に「削除」というリンクを作成し、それをクリックすると”topics/delete/:id”にDELETEリクエストを送信するようにする。

ルーティングの追加

まず、topics/delete/:idにdeleteリクエスト送信時に、topicsコントローラのdeleteメソッドが受け取るようにルーティングを追加する

delete 'topics/delete/:id' => 'topics#delete', as: :topic_delete

コントローラの設定

topicsコントローラでは、削除リクエストを受け取った際に、該当するトピックを削除する。削除後、トピック一覧画面にリダイレクトする
def delete
  @topic = Topic.find(params[:id])
  @topic.destroy
  redirect_to topics_index_path
end

ビューの設定

ビューには、トピックごとに以下の削除リンクが表示されるように追記する。confirmは、リンククリック時に通知されるconfirmで、「OK」をクリックした場合にのみリンクが実行される。

<%= link_to '[削除]', topic_delete_path(topic.id), method: :delete, data: {confirm: "削除してもよろしいですか?"} %>

動作確認

以下のように、「削除」リンクをクリックすると、確認ダイアログが表示され、「OK」をクリックするとトピックが削除されたことが確認できる

実装(書き込み編)

本項では、トピックごとに0件以上存在する「書き込み(post)」について実装を行う。トピック(topic)の実装と重複する内容が多いので、サクッと流していく

書き込みモデルの作成

まずはトピック同様に、postのモデルを作成する。postは、投稿者名(name)と、本文(body)と、トピック番号(topic_id)が必要になる。以下のtopic:referencesのように指定すると、topicテーブルに外部キー制約を持つtpic_id列が生成される。

$ rails generate model Post name body:text topic:references
Running via Spring preloader in process 2470
      invoke  active_record
      create    db/migrate/20170505154158_create_posts.rb
      create    app/models/post.rb
      invoke    test_unit
      create      test/models/post_test.rb
      create      test/fixtures/posts.yml

マイグレーション実行

$ rake db:migrate
== 20170505154158 CreatePosts: migrating ======================================
-- create_table(:posts)
   -> 0.1274s
== 20170505154158 CreatePosts: migrated (0.1277s) =============================

postsテーブルが作成されたことが確認できる

mysql> show columns from posts;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | YES  |     | NULL    |                |
| body       | text         | YES  |     | NULL    |                |
| topic_id   | bigint(20)   | YES  | MUL | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

動作確認用のPostsレコードを作成

トピックと同様に動作確認用のPostsレコードを、console上で作成する。内容が重複しているので結果のみ以下に示す

mysql> select * from posts;
+----+-----------+--------------------------------------------------------------+----------+---------------------+---------------------+
| id | name      | body                                                         | topic_id | created_at          | updated_at          |
+----+-----------+--------------------------------------------------------------+----------+---------------------+---------------------+
|  1 | ササキ    | プロ野球について一緒に語りましょう!                          |        2 | 2017-05-05 15:49:29 | 2017-05-05 15:49:29 |
|  2 | サトウ    | オススメのラーメン屋など教え合いましょう                     |        3 | 2017-05-05 15:49:52 | 2017-05-05 15:49:52 |
|  3 | ヤマダ    | 皆さんの得意な言語はなんですか?                             |        4 | 2017-05-05 15:50:11 | 2017-05-05 15:50:11 |
+----+-----------+--------------------------------------------------------------+----------+---------------------+---------------------+
3 rows in set (0.00 sec)

書き込みコントローラ/ビューの作成

$ rails generate controller Post
Running via Spring preloader in process 2508
      create  app/controllers/post_controller.rb
      invoke  erb
      create    app/views/post
      invoke  test_unit
      create    test/controllers/post_controller_test.rb
      invoke  helper
      create    app/helpers/post_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/post.coffee
      invoke    scss
      create      app/assets/stylesheets/post.scss

書き込み一覧を表示する機能を実装

“/topics/show/:id” にアクセスすることで、該当のトピックに関する書き込み一覧を表示させる

コントローラの設定

“/topics/show/:id”は、topicコントローラのshowメソッドにルーティンぎしているので、showメソッドにて、以下のようにTopicモデルと対応する書き込み一覧を取得してビューに引き渡す

def show
  @topic = Topic.find(params[:id])
  @posts = Post.where(topic_id: params[:id])
end

ビューの設定

ビューでは、トピックのタイトルと合わせて、コントローラから受け取った書き込み一覧を表示する

<h1><%= @topic.title %></h1>
<% @posts.each_with_index do |post , idx| %>
  <p>
    <%= idx + 1 %>. <%= post.name %> : <%= post.body %>
  </p>
<% end %>

動作確認

以下のように、書き込み一覧が表示されることが確認できる

新規書き込みを登録する機能を実装

新規書き込みの登録は、書き込み一覧ページの一番下に設置する新規投稿フォームを用いて登録する

ルーティングの追加

新規書き込み登録のリクエストは、’posts/create’にPOSTし、postコントローラのcreateメソッドが受け取るようにしたいので、以下のようにルーティングを追加する

post 'posts/create' => 'post#create', as: :post_create

コントローラの設定

まず、トピックの新規登録と同様に、書き込み一覧画面でform_forメソッドを使うために、topicコントローラのshowメソッドにて、新しいPostモデルを生成しておく

def show
  @topic = Topic.find(params[:id])
  @newpost = Post.new(:topic_id => params[:id]) #ここを追加
  @posts = Post.where(topic_id: params[:id])
end

postコントローラのcreateメソッドには、新規書き込みの内容がPOSTされるので、postsレコードを生成して書き込み一覧画面にリダイレクトする

class PostController < ApplicationController
  def create
    @post = Post.new(params[:post].permit(:topic_id, :name, :body))
    @post.save
    redirect_to topics_show_path(params[:post]['topic_id'])
  end
end

ビューの設定

書き込み一覧画面のビューに、以下を追加する。トピックの追加と同様にform_forメソッドを用いてformを自動生成する。

<h3>新規書き込み</h3>
<%= form_for @newpost, :url => post_create_path do |f| %>
  <p>お名前</p>
  <p><%= f.text_field :name %></p>
  <p>本文</p>
  <p><%= f.text_area :body %></p>
  <%= f.hidden_field :topic_id %>
  <%= f.submit %>
<% end %>

動作確認

以下のように、新規書き込み登録フォームを用いて書き込みを追加できるようになったことが確認できる

まとめ

以下のような簡易的な電子掲示板ができあがった

所感

  • 初めてRailsで1からアプリケーションを作ったが、想像以上に何でもフレームワーク側でやってくれて驚き
  • 元々触れたことがあったLaravelと似ている部分が多かったので、適応しやすかった
  • テーブル間の関連付けはもっとフレームワークの機能で出来た気がする(トピック削除時に自動で対応する書き込みを削除したり、トピック取得時に自動で書き込み一覧を取得したり)
  • 命名などの制約が非常に厳しいが、それに従うことで色々自動化出来る上、定まったルールの元で開発できるのが良い
  • ネット上に情報が膨大にあるので、他のフレームワークよりも遥かにググりやすい

その他

本記事で作成したRailsアプリケーションは、以下のリポジトリで公開している。記事内で作成したコードから微妙に改良したりしているので、記事と内容が合致しない部分もある。
https://github.com/Sa2Knight/rails-bbs

参考

Mysqlで大きなデータの高速インポート

様々な解決法がありますが、簡単でしたので共有。
環境:PHP/Mysql
参考:http://qiita.com/studio-kakky/items/a1f943b5476e0cbbe47b

mysqlのデータインポート時、データ量が多くマシンスペックが強く無い場合には
エラーを吐かずウンともスンとも言わない状況に陥る事があると思います。

参考URL内記載のリンク先からBigDump(zipされたPHPファイル)を入手し、
PHPが動く環境でWEBアクセス可能なディレクトリにダンプファイルと共に配置。

アクセスするとダンプファイルがピックアップされているので、
Start Importをクリックしてインポート開始するだけ。