FactoryGirlを追加した
いつもの、ごみシリーズです。
今週土日は、自分の所属しているバドミントンクラブのHPの作成で終わってしまいました。 デザイン難しい。
さて、今回は前回 RspecでHTTPのリクエスト・レスポンスのテストを行った - takapi86のブログ で追加したテストに、テストデータを追加していきます。
こちらを参考に導入を行いました。
File: GETTING_STARTED — Documentation for factory_girl (4.8.0)
導入
Gemfile
にfactory_girl_rails
を追加して、bundle install
します。
group :test do gem 'factory_girl_rails' end
- factory_girlのテストデータを作成するコードを保管する場所として、
spec/factories/
を作成しておきます。
ファイルを作成する
区モデル(ward)、町モデル(town)のFactoryGirlファイルを作成します。 ※ward、townは1:nの関係です。
詳しくは、
- spec/factories/wards.rbを作成
FactoryGirl.define do factory :ward do # モデル名を指定 sequence(:id) ward_code 16 name '港北区' end end
- spec/factories/towns.rbを作成
FactoryGirl.define do factory :town do # モデル名を指定 sequence(:id) ward_code 16 initial_code 3 town_code 1073 name '篠原町' end end
試してみる
- test環境にコンソールで入ります。
RAILS_ENV=test bundle exec rails c
wardのデータを作ってみる
[1] pry(main)> ward = FactoryGirl.create(:ward) (0.1ms) begin transaction SQL (0.4ms) INSERT INTO "wards" ("id", "ward_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["id", 1], ["ward_code", 16], ["name", "港北区"], ["created_at", 2017-03-26 14:57:30 UTC], ["updated_at", 2017-03-26 14:57:30 UTC]] (145.8ms) commit transaction => #<Ward:0x00559a99c3ccb8 id: 1, ward_code: 16, name: "港北区", created_at: Sun, 26 Mar 2017 14:57:30 UTC +00:00, updated_at: Sun, 26 Mar 2017 14:57:30 UTC +00:00>
townのデータを作ってみる
[2] pry(main)> FactoryGirl.create(:town, ward: ward) (0.1ms) begin transaction SQL (0.3ms) INSERT INTO "towns" ("id", "ward_code", "initial_code", "town_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["id", 1], ["ward_code", 2], ["initial_code", 3], ["town_code", 1073], ["name", "篠原町"], ["created_at", 2017-03-26 14:59:00 UTC], ["updated_at", 2017-03-26 14:59:00 UTC]] (60.9ms) commit transaction => #<Town:0x00559a9daa47f8 id: 1, ward_code: 2, initial_code: 3, town_code: 1073, name: "篠原町", created_at: Sun, 26 Mar 2017 14:59:00 UTC +00:00, updated_at: Sun, 26 Mar 2017 14:59:00 UTC +00:00>
うまくいったっぽいです。 念の為、testのDBはクリアしておきます。
RAILS_ENV=test bundle exec rake db:migrate:reset
前回のテストに追加
require 'rails_helper' RSpec.describe TownsController, type: :request, json: true do let(:town) { FactoryGirl.create(:town, ward: create(:ward)) } describe 'GET /towns/:name.json' do before do get URI.escape("/towns/#{town.name}.json") end it '200 OK を返す' do expect(response.status).to eq(200) end end end
こちらもうまくいったようです。
ちなみに、ここではFactoryGirl.create
と記載していますが、クラス名は、
spec_helper.rbの Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
のコメントを外し、以下のようにファイルを追加するか、そのままconfig.include FactoryGirl::Syntax::Methods
と追記することで、省略できます。
# spec/support/factory_girl.rb RSpec.configure do |config| config.include FactoryGirl::Syntax::Methods end
ただ、このままでは2回目実行すると、以下のようなエラーが発生してしまうようです。
ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: wards.id: INSERT INTO "wards" ("id", "ward_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) # ./spec/requests/towns_spec.rb:2:in `block (2 levels) in <top (required)>' # ./spec/requests/towns_spec.rb:7:in `block (3 levels) in <top (required)>' # ------------------ # --- Caused by: --- # SQLite3::ConstraintException: # UNIQUE constraint failed: wards.id # ./spec/requests/towns_spec.rb:2:in `block (2 levels) in <top (required)>'
どうやら、続けてテストする場合は、テスト後にテストしたデータを削除する処理を入れる必要があるようです。 こちらは、次回対応していきたいと思います。
RspecでHTTPのリクエスト・レスポンスのテストを行った
rspecでHTTPのリクエスト・レスポンスのテストを行った。
今回も、ごみシリーズです。
ごみ収集日の検索をLineからできるようにした - takapi86のブログで、APIを作っていく中で、rspecでのテストでHTTPのリクエスト・レスポンスのテストができるということを知ったので、メモして起きます。
事前準備
対象
- ごみ収集日の検索をLineからできるようにした。にも書いてありますが、ゴミ収集APIには以下のエンドポイントがあります。
今回は上記のうち、収集場所名を前方一致で検索し、一覧で返すAPI
のテストを書きたいと思います。
導入
rspecのテストファイルは以下の場所 * spec/requests/towns_spec.rb
- 今回はTownsControllerのテストで、リクエストを投げて確認するため、以下のように記述します。
describe TownsController, type: :request do end
- エンドポイントはGETメソッドで、
/towns/:name
なので以下のように記述します。
describe TownsController, type: :request do describe 'GET /towns/:name' do end end
- ステータスコードは200で返ってくるのを期待するテストを追加します。
- ここでは省略していますが、事前にFactoryGirl等でテストデータを生成するようにすると良いでしょう。
describe TownsController, type: :request do describe 'GET /towns/:name' do it '200 OK を返す' do get URI.escape("/towns/#{"日吉"}") expect(response.status).to eq(200) end end end
- 事前にFactoryGirl等でテストデータを生成するようにすると良いでしょう。
- テストを実行してみましょう。
bundle exec rspec spec/requests/towns_spec.rb Finished in 0.50264 seconds (files took 3.08 seconds to load) 1 example, 0 failures
正常にテストが終了したようです。
今回は、test環境にデータが入った状態でテストを行いましたが、 先ほど言ったように事前にFactoryGirl等でテストデータを生成するようにすると良いでしょう。
ごみ収集日の検索をLineからできるようにした
前回のLINE Notifyを使ってごみ収集日を自分にお知らせしてみた。に続き、ごみシリーズです。
会社で携わっているサービスをゴリゴリAPI化していく予定(やっていき)なので、その練習も兼ねて作成しました。
今回は、Messaging API(LineBot)を使って、メッセージから横浜市のゴミ収集日を検索できるようにしました。
現在は、ざっくりイメージとして実装してみた感じなので、機能強化・リファクタリングは今後行っていく予定です。
こんな感じです。
収集場所名を前方検索し、もし、町名がドンピシャで一致していたら、収集曜日を出力。複数ある場合は「もしかして?」と収集場所名・コードを一覧出力します。
収集場所コードでも検索ができるので、収集場所名がわからない場合は、ざっくり町名などを入れて調べ→コードで検索といった流れで調べます。
環境は、
で実装しました。今回作成したAPIは以下3つ
です。Restfulな感じで作りました。
今回は、データについては横浜市のページを見て手動で作っていますが、 今後は、横浜市のHPからスクレイピングしてデータを取り込み、それを返すようにしていきたいと思います。
実は、今回APIを実装するのが初めてだったのですが、API設計や命名規則な部分で悩みました。
実はまだまだ納得がいっておりませんので、今後、バージョンアップする際には、特にこの辺を意識して取り組んでいきたいと思います。
では、また。
LINE Notifyを使ってごみ収集日を自分にお知らせしてみた
Rubyの練習も兼ねて、LINE Notifyを使ってごみ収集日を自分にお知らせしてみました。
やったこと
- LINE Notifyのマイページへログイン(スマホ版のLINEで登録したものです。)し、トークンを発行
- メッセージの送信テスト
- Rubyからメッセージを送信
- ごみ収集日のお知らせテキストを作成し、メッセージを飛ばす処理を追加
- 上記をcrontabへ登録
参考
LINE Notifyのマイページへログイン(スマホ版のLINEで登録したものです。)し、トークンを発行
特に問題なく発行出来たので割愛
メッセージの送信テスト
参考ページ コマンドラインから LINE にメッセージを送れる LINE Notifyにもある通り、curlから簡単に試すことができた
curl -X POST -H 'Authorization: Bearer [access_token]' -F 'message=foobar' https:// notify-api.line.me/api/notify
※ [access_token]の部分を発行されたトークンに置き換えます。([]は必要なし)
Rubyからリクエストを送信
以下のように実装してみた。
line_notify.rb
# coding: utf-8 require 'net/http' require 'uri' require 'openssl' class LineNotify def self.send_msg(msg, token) if token.nil? || token.empty? puts 'Tokenをセットしてください。' return end uri = URI('https://notify-api.line.me/api/notify') req = Net::HTTP::Post.new(uri.path) req.set_form_data('message' => msg) req['Authorization'] = 'Bearer ' + token http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true if uri.scheme == 'https' http.verify_mode = OpenSSL::SSL::VERIFY_NONE res = http.start do |h| h.request(req) end end end
irbでテスト
irb(main):001:0> require './line_notify' => true irb(main):002:0> LineNotify::send_msg("テストです。", "ここはトークン") => #<Net::HTTPOK 200 OK readbody=true>
送れたみたい。
ごみ収集日のお知らせテキストを作成し、メッセージを飛ばす処理を追加
schedule.rb
# coding: utf-8 require "date" require 'json' require 'yaml' require './line_notify' config = YAML.load_file("config.yml") youbi = [:日,:月,:火,:水,:木,:金,:土] wday = youbi[Date.today.wday] gomi_schedule = { 月: '燃やすごみ,燃えないごみ、スプレー缶、乾電池', 火: '缶・びん・ペットボトル', 水: 'プラスチック製容器包装', 木: '燃えないごみ', } if !gomi_schedule[wday].nil? msg = "\n今日は"+ wday.to_s + "曜日【" + gomi_schedule[wday] + "】の収集日です。" LineNotify::send_msg(msg, config['token']) end
config.yml
token: [ここにトークンを追加]
上記をcrontabへ登録
crontab -e
7時に通知が来るよう設定
0 7 * * * cd ~/ && ruby schedule.rb
きたぞっ!
明日からゴミの出し忘れは無くなるに違いない。
ThinkPad X200に Ubuntu 16.04 LTSをインストールした(OSインストール編)
自宅のThinkPad X200にUbuntu 16.04 LTSをインストールしたので、手順を残しておく
手順の範囲
Ubuntuのイメージが入っているメディアが手元にある状態。PCにメディアをセットしインストール開始〜Ubuntuにログインするところまで
OSのインストール
Ubuntuのイメージが入っているメディアをセットし、PCを起動します。
以下の画面が表示されます。画面が切り替わるまでしばらく待ちます。
言語は日本語
を選択し、Ubuntuをインストール
を選択します。
続ける
を選択します。
(アップデートはインストール後に行います。)
ディスクを削除してUbuntuをインストール
をチェックし、インストール
を選択します。
続ける
を選択します。
住んでいる場所がTokyo
になっていることを確認し、
続ける
を選択します。
キーボードレイアウトを日本語
になっていることを確認し、
続ける
を選択します。
あなたの名前
、コンピュータの名称、ユーザ名、パスワードを入力し続ける
を選択します。
しばらく待ちます。
今すぐ再起動する
を選択します。
※PCが再起動します。
再起動後、先ほど設定したユーザ名、パスワードでログインします。
ログインできたことを確認します。
ターミナルを開き、以下のコマンドでOSをアップデートします。
sudo apt-get update sudo apt-get upgrade