チラシ裏日記上等!!新館

Webアプリケーションエンジニアの雑記帳。映画とかアニメとかの記事も書きます。

RailsアプリケーションのCircleCI 2.1 の設定

自分で作ったサービスのCIが未だにCircleCI 1系だったので重い腰を上げて2系にマイグレーションしました。

マイグレーションしたと言ってもカスタマイズらしいカスタマイズもしていなかったのでほとんど0から設定の作り直しです。とりあえず最低限テストを行える状態までこぎつけたので、備忘録がてら残しておこうと思います

操作する環境

環境は以下のような感じ

名前 バージョン
Ruby 2.5.1
Rails 5.2
MySQL 5.7

.circleci/config.yml

.circleci/config.ymlは以下

version: 2.1
executors:
  default:
    docker:
      - image: circleci/ruby:2.5.1
        environment:
          BUNDLE_JOBS: 3
          BUNDLE_RETRY: 3
          BUNDLE_PATH: vendor/bundle
          RAILS_ENV: test
          DB_USERNAME: root
          DB_HOST: 127.0.0.1
      - image: mysql:5.7
        environment:
          MYSQL_USER: root
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
    working_directory: ~/app
jobs:
  checkout_code:
    executor: default
    steps:
      - checkout
      - save_cache:
          key: app-code-{{ .Environment.CIRCLE_SHA1 }}
          paths: ~/app
  bundle_install:
    executor: default
    steps:
      - restore_cache:
          key: app-code-{{ .Environment.CIRCLE_SHA1 }}
      - restore_cache:
          key: app-gems-{{ checksum "Gemfile.lock" }}
      - run: bundle install
      - save_cache:
          key: app-gems-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
  test_rspec:
    executor: default
    steps:
      - restore_cache:
          key: app-code-{{ .Environment.CIRCLE_SHA1 }}
      - restore_cache:
          key: app-gems-{{ checksum "Gemfile.lock" }}
      - run:
          name: Database setup
          command: |
            bundle exec rails db:create db:schema:load db:migrate
      - run: bundle exec rspec spec/
workflows:
  version: 2
  test:
    jobs:
      - checkout_code
      - bundle_install:
          requires:
            - checkout_code
      - test_rspec:
          requires:
            - bundle_install

せっかくなので2.1基準で作りました。

executors

executors は2.1で新しく入ったキーです。ジョブで共通で使用する実行環境に名前をつけることが出来ます。今回の例では default という名前の実行環境を定義しています。

executors:
  default:
    docker:
      - image: circleci/ruby:2.5.1
        environment:
          BUNDLE_JOBS: 3
          BUNDLE_RETRY: 3
          BUNDLE_PATH: vendor/bundle
          RAILS_ENV: test
          DB_USERNAME: root
          DB_HOST: 127.0.0.1
      - image: mysql:5.7
        environment:
          MYSQL_USER: root
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
    working_directory: ~/app

default という名前の後に docker キーで設定を書きます。ここの書き方は今まで jobs で設定していたように imageenvironment が書けます。

jobs

jobs はジョブを定義するキーです。 jobs のあとに続くマップで名前を定義し、中で実行環境と実行の手順を書いていきます。

jobs:
  checkout_code:
    executor: default
    steps:
      - checkout
      - save_cache:
          key: app-code-{{ .Environment.CIRCLE_SHA1 }}
          paths: ~/app
  bundle_install:
    executor: default
    steps:
      - restore_cache:
          key: app-code-{{ .Environment.CIRCLE_SHA1 }}
      - restore_cache:
          key: app-gems-{{ checksum "Gemfile.lock" }}
      - run: bundle install
      - save_cache:
          key: app-gems-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle

executor では executors で定義した実行環境の名前を指定します。 steps では実行するタスクを run で書いていきます。

save_cachekey で指定した名前で path で指定したディレクトリをキャッシュします。 restore_cachesave_cached でキャッシュした内容をリストアします。依存するパッケージなどをキャッシュすることで、外部からのダウンロードの時間を省きCIを早くすることが出来ます。

workflows

workflows はジョブをまとめて実行順を制御しCIを行うための設定を書きます。

workflows:
  version: 2
  test:
    jobs:
      - checkout_code
      - bundle_install:
          requires:
            - checkout_code
      - test_rspec:
          requires:
            - bundle_install

ここでは test という名前のワークフローを定義し、中の jobs で定義したジョブを呼び出しています。各ジョブ間の依存も書くことが出来 requires で依存するジョブの名前を書きます。

参考書籍

CircleCIについての書籍はあまりないのですが、このあいだ出たWEB+DB PRESSの最新号がまさにCircleCI特集で、これを見て今回のCI環境を整えました。しばらくは唯一日本語でまとまったCircleCIの資料になると思います。

WEB+DB PRESS Vol.107

WEB+DB PRESS Vol.107

  • 作者: 大竹智也,浦井誠人,平野朋也,村田紘司,上野学,末永恭正,久保田祐史,吉川竜太,上野博司,牧大輔,西郡卓矢,桑原仁雄,小林謙太,竹馬光太郎,池田拓司,はまちや2,竹原,長谷川智希,北村壮大,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/10/24
  • メディア: 単行本
  • この商品を含むブログ (1件) を見る

まとめ

CircleCI設定を書いていきました。今後やりたいこととしてはCircleCI上でDockerのコンテナをビルドしECRにデプロイするところまでをやってみたいと考えています。

Ruby技術者認定試験Silverを受けて合格しました

自分のRuby力ってどんなん?

普段Rubyを使ってお仕事をしているのですが、何となく使えてしまっているというのと、わからなくなったらすぐ調べて解決するというやり方をしているため自分がどれくらいのRuby力があるのかよくわからなくなっていました。それとRailsを使ってWebアプリケーションを作っていてRailsの便利メソッドやら何やらはわかるけど、Ruby自体は全くわかっていないんじゃないかと不安にも思っていました。

そこでちょっとバージョンは古いけど、自分のRuby力の把握と向上のためにRuby技術者認定試験を今回受けてきました。受けたのはとりあえずSIlverです。これが出来るとRubyちょっと出来るといえるんじゃないかと個人的に思いました。

結果

1ヶ月とちょっと勉強をして結果は100点中90点で合格しました。即日に結果が出るのがとても良いです。すぐ結果が出るのはPCを使って試験を行う形式の利点ですね。

一応Rubyを使って仕事をしているんだから、不合格だったら凄く落ち込むだろうなと緊張していましたが、良い成績を残せて良かったです。

落としているところは普段使わないFIleの操作の部分や、正規表現の所でした。正規表現は結構使うのでしっかりと学び直したほうが良さそうです。

勉強方法

行った勉強方法はテキストを読むのと、付属していた問題を解くことと、アプリで問題集があったのでそれをやったことです。

テキストは無難ですが公式のテキストを使用しました。

Ruby技術者認定試験合格教本 Silver/Gold対応 Ruby公式資格教科書

Ruby技術者認定試験合格教本 Silver/Gold対応 Ruby公式資格教科書

それとRuby学習のバイブルであるところのパーフェクトRubyも一通り読みました。

パーフェクトRuby (PERFECT SERIES 6)

パーフェクトRuby (PERFECT SERIES 6)

Silverぐらいであれば公式のテキストで十分だったと思います。公式のテキストでもオブジェクトの参照のあたりはとても参考になりました。

公式のテキストについている問題集は最初にまずは解いてみて自分のわかっていないところを浮き彫りにし、そこを重点的に調べたりしてわかっていないところを埋めていきました。最初と確認、最後の詰めで使えます。

アプリの問題集はRuby技術者認定試験のページで紹介されていたのを使いました。

play.google.com

電車の中で使用して勉強できるのでとても便利です。問題を全て表示するのに350円ほどかかるのと、回答が間違っているところが何個かあるので注意が必要ですが、大部分は役に立つので最初から最後まで役に立ちました。

後直前に公式ページにあった模擬問題をやるなどして対策をするなどして本番にのぞみました。

http://www.ruby.or.jp/ja/certification/examination/index.data/exam_prep_jp.pdf

感想

学生以来ちゃんと勉強したのは久しぶりのような気がします。合格して資格が取れたからと行って何か特別なことがあるわけではないのですが、勉強する過程でRubyのよくわかっていないところとかを学ぶことが出来たので有意義でした。

次はもう一つ上のGoldを今年中に取ることを目指して勉強していきたいですね。Goldを取るのは結構難しいのでパーフェクトRubyもそうですが、Effective Ruby とかメタプログラミングRubyとかもちゃんと読み込まないと駄目そうな気がします。Goldも一発で合格できるように頑張りたいところです。

Effective Ruby

Effective Ruby

メタプログラミングRuby 第2版

メタプログラミングRuby 第2版

openBDという書誌情報を扱うサービスのAPIを使えるgemを作りました

openBDという書誌・書影の情報を扱うサービスのWeb APIをたたけるgemを作りました。

github.com

gemを作るのは初めて。

使い方

使い方は

require 'openbd_api'

# isbnの番号を入れる
OpenBD.get 9784309226712

で「サピエンス全史」の書誌情報がハッシュの配列でとれます。

irb(main):004:0> OpenBD.get 9784309226712
=> [{"onix"=>{"CollateralDetail"=>{"TextContent"=>[{"Text"=>"虚構が他人との協力を可能にし、文明をもたらした! では文明は人類を幸福にしたのか? 現代世界を鋭くえぐる世界的ベストセラー!", "TextType"=>"02", "ContentAudience"=>"00"}]}, "PublishingDetail"=>{"Imprint"=>{"ImprintName"=>"河出書房新社", "ImprintIdentifier"=>[{"IDValue"=>"309", "ImprintIDType"=>"19"}, {"IDValue"=>"0961", "ImprintIDType"=>"24"}]}, "Publisher"=>{"PublisherIdentifier"=>[{"PublisherIDType"=>"19", "IDValue"=>"309"}, {"PublisherIDType"=>"24", "IDValue"=>"0961"}], "PublisherName"=>"河出書房新社", "PublishingRole"=>"01"}, "PublishingDate"=>[{"Date"=>"20160909", "PublishingDateRole"=>"01"}]}, "ProductSupply"=>{"SupplyDetail"=>{"ReturnsConditions"=>{"ReturnsCode"=>"03", "ReturnsCodeType"=>"04"}, "ProductAvailability"=>"99", "Price"=>[{"PriceAmount"=>"1900", "CurrencyCode"=>"JPY", "PriceType"=>"03"}]}}, "NotificationType"=>"03", "ProductIdentifier"=>{"IDValue"=>"9784309226712", "ProductIDType"=>"15"}, "RecordReference"=>"9784309226712", "DescriptiveDetail"=>{"TitleDetail"=>{"TitleType"=>"01", "TitleElement"=>{"Subtitle"=>{"content"=>"文明の構造と人類の幸福", "collationkey"=>"ブンメイノコウゾウトジンルイノコウフク"}, "TitleElementLevel"=>"01", "TitleText"=>{"content"=>"サピエンス全史(上)", "collationkey"=>"サピエンスゼンシ01"}}}, "Language"=>[{"LanguageCode"=>"jpn", "LanguageRole"=>"01", "CountryCode"=>"JP"}], "ProductForm"=>"BA", "Audience"=>[{"AudienceCodeType"=>"22", "AudienceCodeValue"=>"00"}], "Extent"=>[{"ExtentValue"=>"272", "ExtentUnit"=>"03", "ExtentType"=>"11"}], "Contributor"=>[{"ContributorRole"=>["A01"], "PersonName"=>{"content"=>"ユヴァル・ノア・ハラリ", "collationkey"=>"ハラリ,Y.N"}, "BiographicalNote"=>"イスラエル人歴史学者。オックスフォード大学で中世史、軍事史を専攻して博士号を取得し、現在、エルサレムのヘブライ大学で歴史学を教えている。オンライン上での無料講義も行ない、多くの受講者を獲得している。", "SequenceNumber"=>"1"}, {"ContributorRole"=>["B06"], "PersonName"=>{"content"=>"柴田 裕之", "collationkey"=>"シバタ ヤスシ"}, "BiographicalNote"=>"翻訳家。早稲田大学・Earlham College卒業。訳書にブオノマーノ『バグる脳』、コスリン/ミラー『上脳・下脳』、リフキン『限界費用ゼロ社会』、ファンク『地球を「売り物」にする人たち』など。", "SequenceNumber"=>"2"}], "Subject"=>[{"SubjectSchemeIdentifier"=>"78", "SubjectCode"=>"0022"}], "ProductFormDetail"=>"B119", "ProductComposition"=>"00"}}, "hanmoto"=>{"reviews"=>[{"han"=>"", "appearance"=>"2016-10-16", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"毎日新聞", "choyukan"=>"朝刊", "source_id"=>29, "reviewer"=>"本村凌二(早稲田大学特任教授・西洋史)", "link"=>""}, {"han"=>"", "appearance"=>"2016-10-23", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"朝日新聞", "choyukan"=>"朝刊", "source_id"=>18, "reviewer"=>"", "link"=>""}, {"han"=>"", "appearance"=>"2016-10-30", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"日本経済新聞", "choyukan"=>"朝刊", "source_id"=>23, "reviewer"=>"中村桂子(JT生命誌研究館館長)", "link"=>""}, {"han"=>"", "appearance"=>"2016-11-27", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"読売新聞", "choyukan"=>"朝刊", "source_id"=>20, "reviewer"=>"", "link"=>""}, {"han"=>"", "appearance"=>"2016-12-18", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"毎日新聞", "choyukan"=>"朝刊", "source_id"=>29, "reviewer"=>"中村桂子(JT生命誌研究館館長)", "link"=>""}, {"han"=>"", "appearance"=>"2016-12-18", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"毎日新聞", "choyukan"=>"朝刊", "source_id"=>29, "reviewer"=>"本村凌二(早稲田大学特任教授・西洋史)", "link"=>""}, {"han"=>"", "appearance"=>"2016-12-25", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"読売新聞", "choyukan"=>"朝刊", "source_id"=>20, "reviewer"=>"", "link"=>""}, {"han"=>"", "appearance"=>"2016-12-25", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"東京新聞/中日新聞", "choyukan"=>"朝刊", "source_id"=>19, "reviewer"=>"藤田一人(美術評論家)", "link"=>""}, {"han"=>"", "appearance"=>"2017-01-15", "post_user"=>"genkina", "kubun_id"=>1, "source"=>"日本経済新聞", "choyukan"=>"朝刊", "source_id"=>23, "reviewer"=>"", "link"=>""}], "datemodified"=>"2016-09-07 10:02:08", "datecreated"=>"2016-08-06 10:02:07"}, "summary"=>{"isbn"=>"9784309226712", "title"=>"サピエンス全史(上)", "volume"=>"", "series"=>"", "publisher"=>"河出書房新社", "pubdate"=>"20160909", "cover"=>"", "author"=>"ユヴァル・ノア・ハラリ/著 柴田裕之/翻訳"}}]

サピエンス全史(上)文明の構造と人類の幸福

サピエンス全史(上)文明の構造と人類の幸福

書誌情報はopenBDのAPIで返ってくるJSONをそのままハッシュにしているだけです。情報の仕様は公開されていますが、JSONの仕様じゃないので注意。複数isbnを指定できるので配列で返しています。

基本的にWeb APIで公開されているものをそのまま実装している感じです。なので coverageschema もあります。リソースのgetに対してPOSTしているメソッドがあるのですが、そこだけbulk_getという風にしています。

コマンドラインツールも作っていて、これもWeb APIで出来ることが出来る感じです。jqと組み合わせるとこんな感じで出来ます。

$ openbd coverage | jq '.[0]' | xargs openbd get | jq '.[0].summary.title' 
"Ethics and the limits of philosophy"

まだ検索の機能がWeb APIで用意されていないのですが、それが出来ると楽しくなりそうです。

実装についてあれこれ

APIキーとかないのでインスタンスにする必要はないかなと思い、全部クラスメソッドで作ったりしましたが、実はmoduleで良かったんじゃないかとか思ったりします。実装に関してはまだまだつたない部分が多いかと。

普段Railsであんまり意識しないでRubyとか使ってますが、gemとか作るとRubyで書いてるって感じがして良いですね。Web APIが進化するのに追随して学んでいければと思います。

rmagickをインストールするとき明示的にgccを指定する

rmagickをbundle installでインストールするとき以下のエラーが出た。OSはOS X EI Capitan。

checking for /usr/bin/gcc-4.2... no
No C compiler found in ${ENV['PATH']}. See mkmf.log for details.
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

どうやら/user/bin/gcc-4.2がないのが原因らしい。あるのは/user/bin/gcc。コンソールでgcc --versionで調べてみたところ。

% gcc --version                                                                      (git)-[iss-6]
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.3.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

と出たので。普通に4.2はインストールされている。これを使うように明示的に指定しないといけないっぽい。

なので以下のように実行したところちゃんとインストールできた。

CC=gcc bundle install

参考文献

stackoverflow.com

Rails所感

はじめに

転職してRuby on Railsを使い始めた。仕事をはじめてからほぼ一ヶ月経ったのでRailsを使い始めた感想などを書いてみようと思う。

技術的なことというよりはかなりポエムよりなのであしからず(ところでポエムという言葉を使うにはちょっと抵抗がある。ポエムって詩だよね?なんでみんなポエムって言葉使うんだろう?でも共通言語っぽいのでポエムにする)。

続きを読む