トレタ開発者ブログ

飲食店向け予約/顧客台帳サービス「トレタ」、モバイルオーダー「トレタO/X」などを運営するトレタの開発メンバーによるブログです。

Rails Developers Meetup #7を開催しました #railsdm

f:id:m_nakamura145:20171127143220j:plain

サーバサイドエンジニアの中村です。 11月16日(木) に弊社のカフェスペースにてRails Developers Meetup#7 を開催しました。

イベントの詳細はteckplayのページからご覧ください。 techplay.jp

Rails Developers Meetupは今回の第7回で定期開催が最後ということで、最終回に弊社のオフィスを会場に選んで頂いてありがたく思っています。今後は規模を大きくしたMeetupを行うとのことなので非常に楽しみですね。

本記事では当日の発表内容を簡単にレポートします。

RailsでECサービスをゼロから作ってみて

発表者: 株式会社spice life 赤松さん(@ukstudio)

赤松さんは、オリジナルTシャツ販売サービス「STEERS」でプロダクトマネージャー兼アプリケーションエンジニアを担当されており、新規サービス開発でプロダクトマネジメントを行いつつうまく開発を行うためにやったことについてお話していただきました。

スタートアップでのRails開発/運用でやってよかったこと

発表者: 株式会社トレタ 沢田(@swdyh)

スタートアップでのRails開発/運用でやってよかったこと

弊社の沢田からは、スタートアップでの開発におけるログの集め方や定期処理のやり方についてお話しました。トレタはリリースから約4年間運用されており、その経験から迅速に機能開発を行いながら、運用面で問題になる部分をどうやって整備していくかをまとめてもらいました。

グローバルサービスを作る時に考えておくこと

発表者: 株式会社トレタ 中村(@m_nakamura145)

私からはグローバルサービスを作る時に考えておくこととして、タイムゾーンの話やトレタにおけるグローバルサービスとして大事な要素である祝日とSMS機能についてお話しました。

クックパッドでの Webアプリケーション開発 2017

クックパッド株式会社 鈴木さん(@eagletmt)

鈴木さんからは、マイクロサービス化を進めてきたクックパッドさんの現在のWebアプリケーション開発についてお話していただきました。

コンテナは友だち! in Rails Developers Meetup

発表者: GMOペパボ株式会社 近藤さん(@udzura)

近藤さんからはGMOペパボさんの新卒研修でも用いられた、プロセスをはじめとしたシステムプログラミングについてお話していただきました。

ちなみに近藤さんは福岡からこんな感じでリモート登壇されてました。

f:id:m_nakamura145:20171127143254j:plain

おわりに

Rails Developers Meetupは私も何度か参加させていただいてるのですが、毎回実践的なRails開発の知見が共有されており、素晴らしいMeetupだなと思っていました。そのような場で自分も発表出来て非常に良い経験になりました。

次回開催のRails Developers Meetup 2017 では弊社CTOの増井も登壇予定です。参加予定の方はぜひ懇親会で増井にトレタというプロダクトについて色々聞いてみてください!

techplay.jp

RubyKaigi2017参加報告

サーバーサイドエンジニアの中野です。

大分期間が空いてしまいましたが、9/18〜9/20に広島で開催されたRubyKaigi2017のレポートです。3日目のBundler2のセッションの紹介をしたいと思います。

1系は1.16.xxが最後になる予定

1.16は現在開発中でまだstableではないですが、1系では1.16.xxが最後にバージョンになります。
もし1.15を使用している場合にbundle installコマンドを実行すると↓のようなワーニングが出力されます。

$ bundle install
The latest bundler is 1.16.0.pre.3, but you are currently running 1.15.4.
To update, run `gem install bundler --pre`

このワーニングの必要性に関しては個人的にも気になっていたのですが、開発中のバージョンを使ってもらうことでバグを洗い出したり仕様の問題などを見つけたいなどの理由があるようですが、意図せずバージョンを上げてしまう危険性もはらんでいる等の意見もあったりでこの問題を扱ったissueで活発に議論されました。
ちなみに、bundle config disable_version_check trueをすればでこのワーニングは表示されなくなります。

Bundler2について

興味深かったものをいくつか紹介していきます。
Bundler2のRFCの草稿はこちらで見ることができます。

コマンドを指定しないでbundleを実行するとhelpが出力される

1系では、コマンドを指定しないでbundleを実行するとbundle installが実行されていたのですが、2系からはhelpが出力されるように変更されます。個人的には便利で多用してたので少し残念な変更です。issueはこちら

Gemfile、Gemfile.lockがそれぞれgems.rb、gems.lockに変更される

この変更は話題にもなったためご存知の方も多いと思います。
2系でもGemfileとGemfile.lockはそのまま使用できますが、bundlerのバージョンが2系でrails newをした場合にはgems.rbとgems.lockが作成されるようになります。
名前変更の経緯を知りたかったのでissueをあさってみたところ、2010年にUNIXのLOCK拡張子があるのに異なる用途で同じ拡張子を使用するのはどうなの?というissueが立てられており、結果としてファイル名を変更することになったようです。

Gemfile内のgemをすべてアップデートする bundle update--all オプションの指定が必須になる

2系からGemfileのgemをすべてアップデートするために--allが必須になります。
理由としては、Gemfileに新たなgemを追加した時に bundle install すべきところにbundle updateしてしまう例が多かったためらしいです。自分もrailsを触り始めたばかりの頃にbundle updateしてしまって関係のないgemまですべてアップデートしてしまうことがあったので有り難い仕様変更だと思います。issueはこちら

githubやbitbucketなどに置いてあるgemをインストールするためのショートカットが使用できなくなる

gemにパッチをあてて使用してる場合にGemfileでそのgemを置いてあるサービス名をキーにしてuser/repoを指定するとインストールできてたのですが、これができなくなります。ただrailsの場合、5.0.1移行でrails newした際に作成されるGemfileには

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

が追加されておりgithubだけはショートカットが使えるようになってます。他のサービスも↑のように書くことでショートカットが使用できるようになります。

Bundle Plugin

Bundlerにはpluginという機能があり目的に応じた機能を追加することが可能となっています。
pluginの機能が用意されたのは、bundlerが大きくなるに連れ機能の要望が増え、開発、そしてメンテナンスしていくことが困難になってきたので、pluginという形で機能追加をする場を用意することで開発者各々が独自機能をbundlerのリリースを待たずに追加できるようにしたかったという経緯があります。バージョン1.13から用意されているのですが、まだドキュメント無くほとんど知られてないためドキュメント含め一緒にpluginを開発してくれる人大歓迎!とのことでした。

pluginの作り方

作り方はgemのそれとほとんど同じで、違いは一番上の階層にplugins.rbというファイルを用意しpluginのコードを書きます。
例としてbundle hogeと入力するとHogeと出力されるpluginの作り方を簡単に紹介します。hogeというgemを作成し↓のようなplugins.rbを用意します。

module Hoge
  class Plugin < Bundler::Plugin::API
    command "hoge"

    def exec(command, args)
      puts "Hoge"
    end
  end
end

これを通常と同じくrubygems.orgにアップすると、bundle plugin install hogeのようにして作成したpluginをインストールすることができるようになります。インストールが完了するとpluginが使用できるようになります。

$ bundle hoge
Hoge

おわりに

簡単ではありますがBundler2についての紹介をさせていただきました。
11月に開催されるRubyConfでは、Bundlerを初期から長くメンテをしているAndré Arkoがbundlerの歴史についてのセッションを行うので個人的にとても楽しみです。

なお、弊社では国内外のカンファレンス参加費用の補助制度があり、今回のRubyKaigiは会社の経費で参加させて頂きとても感謝しています。来年の仙台で開催されるRubyKaigiに参加したい方は是非ご応募下さい。

www.wantedly.com

RubyKaigi 2017に参加してきました

サーバーサイドエンジニアの芹沢です。

以前書いた私のエントリーにて、弊社のRubyKaigi参加者がそれぞれレポートを書くよという話をしましたが、その2人目のレポートです。

tech.toreta.in

私のレポートでは、2日目に行われたセッションから、Progress of Ruby/Numo: Numerical Computing for Rubyを紹介させていただきたいと思います。

スライドはこちら

speakerdeck.com

Ruby/Numo Projectとは

Rubyで機械学習や科学技術計算を行うためのライブラリを開発しているプロジェクトです。
一般に、機械学習界隈ではPythonで実装されたライブラリがよく使われていると言われており、実際私もnotebookやpandasをよく使うのですが、そういったライブラリが解決することをrubyでも解決することを目指しているプロジェクトのようです。*1

Rubyで機械学習を行うための別のアプローチとして、PythonのコードをRubyでも実行可能にするためのbinding機構であるPyCallがあります。今回のRubyKaigiでもセッションとワークショップが行われましたが、こちらはNumpy, pandasといったPythonのライブラリ資産をそのままrubyでも実行できるようにbindingすることを目指しています。

現在複数のgithub repositoryがこのプロジェクト配下に存在しますが、今回のセッションでも説明が多かったNumo::NArrayについて紹介します。

Numo::NArrayとは

多次元配列の計算を高速に行うためのライブラリ(という理解です。。)です。RubyにもArrayやMatricsの標準ライブラリがありますが、用意されているメソッドはPythonの行列計算ライブラリであるNumpyに近いインターフェースとなっています。
numpyとの対応表がwikiにありますが、かなりの割合のnumpyのメソッドを網羅していることが分かります。実際、Numpyの363個ある関数のうち217個をカバーしており、今後さらに91個が追加予定になっているとのことです。

Numo::NArrayを手元で試す

実際にNumo::NArrayを手元で動かしてみました。
Numo::NArrayのgithub repositoryのREADMEにはspecific_installを使う方法が記載されていますが、普通にGemfileを作ってbundle installしてもインストールできるのでこちらを採用しました。

こんな感じのGemfileを書いて bundle install します。

# frozen_string_literal: true
source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem 'numo-narray', git: 'https://github.com/ruby-numo/narray.git'

irbで動かしてみます。

irb(main):001:0> require 'numo/narray'
=> true
irb(main):002:0> a = Numo::NArray[[1,2,3,4,5]]
=> Numo::Int32#shape=[1,5]
[[1, 2, 3, 4, 5]]
irb(main):003:0> a * 2
=> Numo::Int32#shape=[1,3]
[[2, 4, 6, 8, 10]]
irb(main):004:0> a.shape
=> [1, 5]
irb(main):005:0> b = Numo::NArray[[2],[3]]
=> Numo::Int32#shape=[2,1]
[[2],
 [3]]
irb(main):006:0> c = a * b
=> Numo::Int32#shape=[2,5]
[[2, 4, 6, 8, 10],
 [3, 6, 9, 12, 15]]

最後の行でやっている計算はbroadcastingという機能を使って実現されています。

これは、行列同士の四則演算を行う際に、両者の行列の形状が異なる場合であっても、次元が少ない方の配列を拡張して計算できるようにしてくれるものです。

これをrubyのArrayだけでやろうとすると結構複雑なmap処理をしないと実現できませんがNumo::NArrayを使うとシンプルに記述することができます。

また、今回のセッション中でも紹介されていたマスク処理という機能があります。これは配列内の各値に対して、条件にマッチしれいれば1,そうでなければ0の配列を返す機能です。

irb(main):001:0> a = Numo::NArray[1..10]
=> Numo::Int32#shape=[10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):002:0> a < 6
=> Numo::Bit#shape=[10]
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0]

これと同じことをRubyで書こうとすると以下のようになると思います。

 a = (1..10).map { |i| i < 6 ? 1 : 0 }

ステップ関数を配列の全要素に対して適用して二値ベクトルを得る時などに直感的に書けそうな感じがしてこのsyntaxは個人的にはすごく気に入りました。

ですが、パフォーマンスが悪ければ実用は厳しいので、実際にこのマスク処理のベンチマークを取ってArrayのみで実装した場合と比較してみました。

require 'numo/narray'
require 'benchmark'

base = (1...1000_000).to_a
compare = 1000

nbase = Numo::NArray[base]

Benchmark.bm do |r|
  r.report 'narray' do
    (nbase < compare).to_a
  end

  r.report 'map' do
    base.map do |v|
      v < compare ? 1 : 0
    end
  end
end
       user     system      total        real
narray  0.030000   0.010000   0.040000 (  0.029366)
map  0.060000   0.010000   0.070000 (  0.087115)

Numo::Int32のMask処理の方がArrayのmap処理のみで実装したサンプルよりも2倍ほど早い結果が出ました。

ただ、勘のいい人はお気づきのように、これはrubyのArrayオブジェクトをNumo::Int32のオブジェクトに変換する処理をBenchmark対象に入れていない場合の結果です。変換処理もベンチマーク対象に含めてみると

       user     system      total        real
narray  0.140000   0.000000   0.140000 (  0.156649)
map  0.070000   0.010000   0.080000 (  0.077548)

ベンチマーク結果が逆転します。Numo::Int32オブジェクトに変換する処理はかなりオーバーヘッドが大きい処理と考えられます。そのため、オーバーヘッドを無視できるほど同じ配列を何度も使用するようなケースであればともかく、基本的にはパフォーマンス面ではArrayを使った方が有利のようです。

まとめ

簡単ではありますがNumo::NArrayの紹介をさせていただきました。普段Pythonでscriptを書くこともある身としては、RubyでもNumpyのsyntaxで配列操作をできるようになるのはとてもありがたいことなので、projectの今後の発展に期待したいところです。
また、Arrayからのオブジェクト生成時のオーバーヘッドが大きいと本文中に書いたものの、それを無視できるユースケースであればNumo::NArrayの配列計算は相当パフォーマンスが良いと思われるため、うまくハマるユースケースがあれば使っていきたいと思います。

なお、今回のカンファレンスは会社の経費で参加させて頂きました。今年のRubyKaigiのclosingセッションでも「仕事としてRubyKaigiに参加している人はいますか?」というa_matsudaさんの質問に沢山の手が挙がる様子が見受けられましたが、このようなカンファレンスに業務として参加させていただけることはとてもありがたいことだと思います。

最後に、お約束になりますがトレタはサーバーサイドエンジニアを募集しております。来年のRubyKaigiは仙台なので、牛タンと萩の月と笹かまぼこが食べたい方は是非ご応募ください。*2(そうでない方もご応募ください) www.wantedly.com

*1:もし違ったらすみません…

*2:ちなみに今回はお好み焼きを食べ損ねました…

© Toreta, Inc.

Powered by Hatena Blog