このカテゴリの記事
Ruby
RubyKaigi 2026に参加してきました
お久しぶりです。 小林です。 4/22〜4/24に函館で開催されたRubyKaigi 2026に参加してきました。 弊社としては3回目、私個人としては初めてのRubyKaigiへの参加です。 https://rubykaigi.org/2026/ 先に感想を言ってしまうと、多くのエンジニアの方と技術の話ができ、とても楽しい3日間でした。 スポンサーブース kickflowさんのブースで、3種類のAI(Claude、Gemini、ChatGPT)に同じ質問をして、どのAIの回答かを当てる「利きAIクイズ」をやっていたので、挑戦してきました。 結果は、なんと全問正解でした。 私が挑戦した時点では全問正解者はいなかったらしく、ブースの方々にも驚かれていました。 (いちばん驚いていたのは私ですが……) https://x.com/koba_masa40/status/2046831103143784507 どうやら、私はAI、あるいは人類のバグだったようです(笑) 他の企業さんのブースも回り、サービスの技術スタックや開発におけるAIの活用についていろいろ話を伺いました。 数年前までは開発にAIを利用していること自体が強みだったのが、いまや当たり前となっていることを改めて実感しました。 各社さまざまな工夫をしながら活用しており、とても興味深く、勉強になりました。 また、RubyKaigiでは恒例となっているスポンサーブースのスタンプラリーもコンプリートし、無事ピンバッジを獲得してきました。 各ブースを回るきっかけにもなり、いろいろな企業の話を聞けたのも良かったです。 セッション とにかくマニアックなセッションだらけでした。 さすが、Ruby言語そのものやエコシステムを作っている方々が多く集まるイベントだけあって、とても濃いRubyの話が聞けて楽しかったです。 今回いちばん気になっていたのは、2日目のm_sekiさんのセッション「Programming with a DJ Controller - not vibe coding」でした。 https://rubykaigi.org/2026/presentations/m_seki.html これを見たときに、「頑張れば、俺の考えた最強のCAD用デバイスも作れてしまうのでは?」と思い、ぜひ聴いてみたいと思っていました。 実際にDJコントローラーを使って操作する様子を見ながら、「こんなことができるのか」「こういう発想があるのか」と、とても面白く聴くことができました。 また、おやつ休憩の時間には本来の用途であるDJとして音楽が流されており、会場全体がチルな雰囲気に包まれていたのも印象的でした。 特に面白いと思ったのは、複数のテキストエディタを操作してスクロールし、ログを眺めやすくするという活用方法でした。 確かに便利そうだと思いました。 感想 公式レセプションでもブースでも、エンジニアの方々と技術の話で盛り上がることができ、とても楽しかったです。 Rubyそのものの深い話だけでなく、普段あまり接点のない方々と交流できたのも、RubyKaigiの大きな魅力だと感じました。 来年は宮崎での開催とのことなので、また参加して、さらに多くの刺激を受けたいと思います。
Rails(ActiveSupport)のHash#slice!の罠
ご無沙汰してます。豊田です。 随分長いことブログを書いていなかった気がしますが、きっと気のせいですよね。 今回はタイトルにもあるように Rails(ActiveSupport)が提供する Hash#slice! の挙動について、書いていきたいと思います。 いきなりですが問題です こちらのコードの実行結果、わかりますか? hash1 = { a: 'hoge', b: 'fuga', c: 'piyo' } hash2 = hash1.slice!(:b) hash2 # => ??? この問題がすぐに(正しく)解ける方は、このブログは読まなくで大丈夫ですw まずは他の類似メソッドでおさらい 「いきなりそんなこと言われても...」という方もいらっしゃると思いますので、類似のメソッドの挙動をおさらいしてみましょう。 Array#slice(Ruby) Rubyの組み込みライブラリ、Arrayクラスが提供する #slice メソッドです。(公式) array1 = [100, 200, 300] array2 = array1.slice(1) array1 # => [100, 200, 300] array2 # => 200 引数で指定したindexに該当する要素を返してくれます。 ※他にも異なるパラメータを使う方法がありますが、基本的な動作は変わらないので割愛します Array#slice!(Ruby) 同じくArrayクラスが提供する #slice! メソッドです。(公式) array1 = [100, 200, 300] array2 = array1.slice!(1) array1 # => [100, 300] array2 # => 200 レシーバーを破壊的に変更する点は異なりますが、指定した箇所の要素を返すという点では #slice と同じですね。 Hash#slice(Ruby) 続いて同じく組み込みライブラリが提供する Hashクラスの #slice メソッドです。(公式) hash1 = { a: 'hoge', b: 'fuga', c: 'piyo' } hash2 = hash1.slice(:b) hash1 # => {:a=>'hoge', :b=>'fuga', :c=>'piyo'} hash2 # => {:b=>'fuga'} 指定したkeyと、対応するvalueのペアを返します。 指定した要素を取り出す。という点でArrayクラスの #slice メソッドと似ていますね。 冒頭の問題 それでは、冒頭で出した問題を改めて見てみます。 hash1 = { a: 'hoge', b: 'fuga', c: 'piyo' } hash2 = hash1.slice!(:b) hash2 # => ??? ! をつけることでレシーバーを破壊的に変更する違いはあるものの、直感的には Hash#slice と同じ結果になりそうです。 実行してみる 早速実行してみました ちょっと見づらいので、整形します hash1 = { a: 'hoge', b: 'fuga', c: 'piyo' } hash2 = hash1.slice!(:b) hash1 # => {:b=>'fuga'} # 上記では実行していませんが、実際にはこうなる hash2 # => {:a=>'hoge', :c=>'piyo'} どうでしょうか。なんか思ってたのと違いませんか? 指定したkey, valueのペアがレシーバー側に残り、それ以外のkey, valueのペアが削除されています。(そして削除されたペアは、戻り値になっています) ActiveSupportが提供するHash#slice! 気になったので調べてみたところ、Railsの公式にちゃんと書かれていました。 Replaces the hash with only the given keys. Returns a hash containing the removed key/value pairs. なるほど。そういう仕様なんですね。 この仕様の違いを私なりに解釈してみると、視点の違いなのかなと思いました。 Rubyが提供する #slice は、レシーバーから特定の要素を「切り出す」イメージ( => 切り出した側に注目している) ActiveSupportが提供する #slice! は、レシーバーから特定の要素以外を「切り落とす」イメージ( => レシーバー側に注目している) Hash#extract!というメソッドがある ActiveSupportには Hash#extract! というメソッドが用意されています。 私が Hash#slice! に期待していた挙動は、実はこちらだったりします。 Removes and returns the key/value pairs matching the given keys. hash = { a: 1, b: 2, c: 3, d: 4 } hash.extract!(:a, :b) # => {:a=>1, :b=>2} hash # => {:c=>3, :d=>4} なるほど、extract(抽出する)であれば、レシーバーから要素を抽出(取り出す)するというイメージで違和感がありませんね。(抽出した側に注目している) つまり Hash#slice の破壊的メソッドは Hash#extract! ということになります。 まとめ ActiveSupportが提供している Hash#slice! は、その他の #slice, #slice! とは挙動が(直感的に)異なる Hash#extract! が(直感的に)他の #slice, #slice! に近い挙動になる 普段Rubyのコードを書いているとき 「破壊的変更だから ! をつければ良い」と考えていると逆の挙動になるので事故る いかがだったでしょうか。 私はActiveRecordのenumの実装を読んでいるときに Hash#slice! の挙動を見て違和感を感じ、この仕様を知りました。(もしかしたら、これまでにも無意識に使って事故ってたのかもしれませんが...) オープンソースのプログラムを読むのは勉強になりますね。
RubyWorld Conference 2024に参加してきました!!
みなさん、お久しぶりです! 前回のブログ投稿から3年くらいたっての投稿になります。田中です。 12/5〜12/6に開催されたRubyWorld Conference 2024に参加してきました。 毎年11月の開催だったので、個人的には人生初の12月の島根が楽しみでもありました(笑) 出雲空港に着いてまず思ったのは、とにかく寒い!例年に比べて尋常じゃなく寒かったです。 来年以降のRubyWorld Conferenceへ参加する人達は、**「12月なら厚着」**を徹底してください! 11月の感覚で足を踏み入れた私は、この日から2日間ずっと寒い思いをします。 と、冒頭の話はここらへんにしてRubyWorld Conferenceの話をしたいと思います。 今年のカンファレンスは、Andy Piperさんの基調講演から始まりました。 内容としては、分散型ソーシャルウェブの重要性やどの様に成長してきたか等のお話をしてくださいました。 普段、使うことはしても重要性等は気にしたことがなかった私としては驚きの多いお話でした。 午前中の公演が終わり、WYRD恒例のお蕎麦を食べに行きました。 今年は神代そばへ行きました。 毎年お邪魔しているのですが、個人的にはイチオシなお店なので是非食べに行ってください! (写真撮り忘れたごめんなさい!!!!!!!!) 午後は、出店ブースなどを見たり公演を聴いたり充実したお時間を過ごさせていただきました。 公演に興味がある方は、RubyWorld Conference 2024チャンネルでアーカイブを見てください。 翻訳も用意されているので、英語が苦手な方でも安心して楽しめます。 自分も英語で内容がわからなかった場合は、このチャンネルで聴き直したりしています。 (本当に助かります...感謝) レセプションでは、色々な会社の方と挨拶させていただいたり美味しいお酒を頂きました。 まつもとゆきひろさんともお写真撮らせていただいたり、素敵な時間を過ごしました。 サムネイルに使用している写真もレセプションで撮らせていただきました! しまねっこの登場で会場がさらに和やかな雰囲気になり、みんな笑顔になっていました。 しまねっこはいつ見てもかわいい こんな感じで今年もRubyWorld Conferenceとても素敵なイベントでした! 運営に携わってくださった皆様、本当にお疲れ様でした。 余談 これもせっかくなので書くかという話題なのですが、人生初神有月ではない出雲大社に参拝してきました。 私がそもそも神社に詳しくはないのですが、ここまで大きい神社って出雲大社くらいしか行ったことがないので何回来ても圧倒されます。 毎年のノルマとして良縁を祈り続けているので、今年も達成できてよかったです(笑) あとすごく美味しい松葉蟹をいただきました。 こんな贅沢をして良いのか、って毎年思います。 この感動を与えてくれた松江と、松葉蟹に心から感謝です。Matzさんにも感謝を込めて。
Rackについて学んだこと 〜Kaigi on Railsの「Rackを理解しRailsアプリケーション開発の足腰を鍛えよう」に参加〜
こんにちは、山屋です! 先日のKaigi on RailsにてRackを理解しRailsアプリケーション開発の足腰を鍛えようというワークショップに参加しました! ワークショップについてと、Rackについて学んだことをまとめました。 ワークショップ参加のきっかけ 業務でRackミドルウェアに関するプルリクエストのレビューをする機会がありました。 Rackについてうっすら知識はあったものの、「なんかピンと来ていない…」という印象をRackに抱いてしまいました。 そんな折にRackのワークショップが開催されるということを知ったので参加を決意しました。 ワークショップの内容 こちらがワークショップの内容です。 1日目にRackアプリケーションとRackミドルウェアの作成を、2日目にRackサーバーの作成を行いました。 私はワークショップ中にRackサーバーの作成までは終了できなかったのですが、実際に手を動かしたことでRackの理解が深まりました。 終始和やかな雰囲気で、スピーカーのhogelogさんは「ここにいる全員と話すつもりで来ました」と仰っており、楽しく進めることができました。もちろん私もお話しさせていただきました! Rackについて学んだこと Rackの概要 RackはWebアプリケーションサーバーとWebアプリケーションフレームワーク間の標準仕様です。 Rackがなかった頃は特定のアプリケーションサーバーとフレームワークの組み合わせでないと動作しない…ということが発生していたようです。RailsはRackアプリであるのでUnicornやPumaなど様々なWebアプリケーションサーバー上で動作します。 Rackアプリケーションの基礎 callメソッドを定義しているものが最低限のRackアプリケーションです。 callメソッドでは[status, headers, body]の形式でレスポンスを返す、という決まりごとになっています。 レスポンスは必ずこの形式なので、役割がはっきりしていますね。 コード例はこちらです。 Rackミドルウェア 資料からRackミドルウェアの概要を引用します。 Rackミドルウェアは、Rackアプリケーションのリクエストとレスポンスの間に介在し、リクエストを加工したり、レスポンスに処理を加えたりするコンポーネントです。ミドルウェアをチェーンのようにつなげることで、複雑な処理をシンプルに組み立てることができます。 すなわち、自身のcallメソッドで加工を行いつつ、他のRackミドルウェアやRackアプリケーションのcallメソッドを呼び出して処理を続けていくことができます。 用意する必要があるメソッドはcallとinitializeメソッドの2つです。 コード例では、initializeメソッドで引数を受け取り、ミドルウェアのcallメソッドの「status, headers, body = @app.call(env)」でAppクラスのcallメソッドを呼び出しています。 その後、callメソッド内でリクエストやレスポンスを加工することができます。 (ちなみに私がレビューしたコードではcallメソッドでUser Agent文字列の加工を行っていました) Rackサーバー 重ねてですが、資料からRackサーバーの役割を引用します。 大まかに言うとクライアントからHTTPリクエストを受け取り、Rackプロトコルで定まった値を詰め込んだ env ハッシュを作成してRackアプリケーションに渡し、Rackアプリケーションから帰ってきた配列を元にクライアントにHTTPレスポンスを返すのがRackサーバの仕事です。 Rackミドルウェアにstartメソッドを追加して、サーバーの処理を記述しているようです。 ソケット通信などあまり知識がないものも多く、正直なところ、サーバーはこんなことをしているんだという大雑把な理解となってしまいました。 ただこの内容はRailsを理解する上で重要なことだと思うので、機会を作ってまた深掘りしていきたいなと思いました。 学んでみてどうだったか 今まではRackについて「サーバーと何かしらやりとりをしている。ミドルウェアを作れる。RailsはRackアプリである」くらいの認識しかなかったのですが、解像度が上がったと感じました。 改めてレビューしたプルリクエストを見返してみたところ、どんな処理なのかスッと頭に入ってきました。 手を動かして学んだことにより、理解が深まったなと感じました。 自分から積極的に学ぶにはハードルが高い分野だったので、ワークショップを開催していただけてとてもありがたかったです! 同時に知識が足りていない部分も浮き彫りになったと思います。(サーバーが何をしているのか、サーバーの違いは何なのか、Railsに他にどんなライブラリが使われているのか、などなど…) Kaigi on Railsで「Rails wayに乗りましょう」という話をいろんな方が仰っていましたし、少しずつRailsが何をしているのか学んでいこうと思います。 最後になりましたが、ワークショップを開催してくださったhogelogさん、本当にありがとうございました! 参考資料 Railsの練習帳 Chapter 09 [Rails基礎] RackとRackミドルウェア パーフェクトRuby on Rails 【増補改訂版】 3-2 RackとRailsの関係
Kaigi on Rails 2024に参加してみた〜当日編Day1〜
みなさん、こんにちは。 小林です。 10/25〜26に開催されたKaigi on Ruby2024に参加して来ましたので、前回に引き続き、そのことについて書いていこうと思います。 前回の記事はこちら↓ Kaigi on Rails 2024に参加してみた〜事前イベント編〜 残念ながら、私は26日は予定がすでに入っていたため、Day1のみの参加になります。 会期中に使えるWebアプリケーションがあったのですが、運営スタッフたちがRailsで開発したとのことでした。 しかも最近、Rails8にアップデートしたとのことで、こういうのはエンジニアとしてはニヤッとしてしまいますよね。(実際に会場は大盛り上がりでした。) アプリケーション上でプロフィールを作成して、交換をしたり(する機会はありませんでしたが)、運営からの連絡を受信できるようにしてありました。 https://github.com/kaigionrails/conference-app あとでゆっくりコードを読んでみようと思います。 それでは、イベントの内容に関して紹介していきたいと思います。 セッション 私が参加したセッションは以下ですが、 RailsのPull requestsのレビューの時に私が考えていること そのカラム追加、ちょっと待って!カラム追加で増えるActiveRecordのメモリサイズ、イメージできますか? モノリスでも使える!OpenTelemetryでRailsアプリのパフォーマンス分析を始めてみよう Rails APIモードのためのシンプルで効果的なCSRF対策 現実のRuby/Railsアップグレード Hotwire or React? 〜Reactの録画機能をHotwireに置き換えて得られた知見〜 この中でも特に気になっていた講演を紹介します。 RailsのPull requestsのレビューの時に私が考えていること 私が一番聴きたかったセッションがこちらです。 yahondaさんがRailsのコミッターとしてrails/railsプロジェクトのレビュー時に意識していることの紹介でした。 railsプロジェクト固有の話でありましたが、その中にも業務に活かせるものはないかと気になっていました。 https://speakerdeck.com/yahonda/railsnopull-requestsnorebiyunoshi-nisi-gakao-eteirukoto 特に活かせそうだなと思ったのが、バグなどの報告時の書き方に関してです。 Issues: Expected behavior あなたの望む動作を書く 過去のバージョンでどう動いていたか 私は「望む動作」は記載しますが、「過去にどうだったか」を書くことがほとんどありませんでした。 しかし、これを書くことによって、過去の事実として客観的な情報を伝えることができるので、実践していきたいと思います。 Issues: Actual behavior 再現ケースで実際の動作を肯定文で書く これは「肯定文」で記載することが大切だそうです。 言われてみればその通りで、以下の2点を踏まえると「〇〇(望む動作)をしない」と記載してしまうと情報が一切増えないので、書く意味がありません。 (ISSUEを起票している時点で)問題が起きていること 「望む動作」を記載していること 私自身、このような書き方はしていない(つもり)ですが、改めて意識していこうと思いました。 懇親会 懇親会では、小さなテーブルがたくさん用意されており、4〜5人集まり、親睦を深めるという感じでした。 みなさん、頻繁にテーブルを移動するようで、多くの方と会話することができました。 会話の内容としては、業務を絡めたRailsの話題だったり、今日のセッションの深掘りだったり、最近のトレンド等だったりと、かなり盛り上がり楽しむことができました。 私はもともとJavaで仕事をしていたのですが、そんな境遇の方が何人かおられて、 最近のJava界隈の話をしたり、Javaで使用するフレームワークとRailsの違いや共通点の議論をしたりしてきました。 運営スタッフさんとも同じテーブルになったのですが、その際にも技術的な話題で盛り上がってしまいました。 冒頭のWebアプリケーションのことやスピーカーの選定に関する裏話を聞く貴重なチャンスだったのにそれを活かすことができませんでした。 次回、参加する機会がありましたら、忘れずに聞いてみようと思います。 まとめ 参加してみての感想は、 初心者に対しては、登壇しているスピーカーの方々に経験年数の少ない方も多く励みとなり 中級者に対しては、理解はできるがまだまだ学ばなければならないことが多いことを自覚させられ 上級者に対しては、より深い領域で刺激しあえる イベントの趣旨にある通り、だれでも楽しめるイベントであったと思います。 私自身は中級者と自負しておりますが、上級者になるためにはまだまだ先は長いことを再認識させられ、改めて努力し続けるモチベーションを得ることができました!! 講演の内容はYouTubeで公開されていますので、興味があれば見てみてください。 https://www.youtube.com/c/kaigionrails
Kaigi on Rails 2024に参加してみた〜事前イベント編〜
※本記事はKaigi on Rails2024の当日までに執筆したものです。 みなさん、こんにちは小林です。 いきなりですが、Kaigi on Railsというイベントをご存知ですか?「初学者から上級者までが楽しめるWeb系の技術カンファレンス」というコンセプトで開催されているイベントになります。 実はこれまでに参加したことがなかったのですが、今年は機会に恵まれ、参加してみることにしました。 しかし、社内にも参加したことがある方がいなかったので、どのようなイベントなのかがわからず、少し不安も感じていました。そんな折にちょうど良い事前イベントを見つけたので、まずはそちらに参加してみました。 https://andpad.connpass.com/event/332751/ こちらはアンドパッド様とAsakusa.rb様の主催でタイムテーブルを解説してくださるイベントでした。運営の方々がスピーカーとして各セッションの見どころ等の解説と、どのようにスピーカーを選定したのかという小話があり、とても面白かったです。 選定は運営の方々で応募があった内容を点数化し、議論して決めるとのことでした。その中でも特に採用したいものは、採用したい人が他のメンバーに熱く語って説得させるというもので、かなり熱がこもったイベントだなと感じました。 個人的に一番ためになったのは、「有明近辺に詳しくない人向けの歩き方ガイド(仮)」でした。これがなければ当日迷子になっていたかもしれません(笑)。 実はこのイベントはKaigi on Railsの公式ホームページに掲載されていました。公式がこのようなイベントを紹介してくれるのは、初参加の人たちにはとてもありがたいことです!! あとはどのセッションに参加するかを決めて、当日に臨むだけとなります。次回は参加した感想をまとめますので、そちらもご期待ください。
Kaigi on Railsに参加しました! 〜2年目エンジニアの視点から〜
こんにちは、山屋です! 先日、Kaigi on Railsに参加しました。 特に印象に残った講演や、エンジニア2年目という段階で参加してみての感想について書こうと思います。 印象に残った講演 Railsの仕組みを理解してモデルを上手に育てる - モデルを見つける、モデルを分割する良いタイミング - https://speakerdeck.com/igaiga/kaigionrails2024 以前チーム内でリファクタリングや設計をする機会があった際に苦戦したので、設計力をつけたいなと思って参加しました。 モデルを分割する良いタイミングとして、「validatesメソッドに条件分岐が発生したとき」というのは分かりやすいな〜と思いました。 このまま進めるとだんだんしんどくなってしまうそうです。(たくさんご経験されたんだろうな…と想像してしまいました) あと繰り返し仰っていたのは「RailsにService層を入れるのはできるだけやめてほしい」ということです。 層が決まっているのはRailsのメリットであり、増やしてしまうとチーム内での理解や認識がバラバラになってしまいがちとのことです。 (基調講演でも抽象を追加する際には層を増やすのではなくアーキテクチャのどこかしらの層に入れましょうと仰っていましたね) つまりRails wayに乗りましょう。 Identifying User Identity https://speakerdeck.com/moro/identifying-user-idenity Userモデルは主キーid以外必要ないのでは?「ユーザーが存在している」ということだけ分かれば良いのでは?というお話でした。 idさえあればUser関連のほとんどの操作や分析はできるしユーザー名やメールアドレスなどは別のテーブルに分ければ扱いやすくなる、とのことで、……なるほど!と膝を打ちました。 まだ業務でその機会があるかは分かりませんが、何か大きな機能を追加するときに「存在していること」だけを表すモデルを作るアプローチはアリかなと思いました。 ワークショップ: Rackを理解しRailsアプリケーション開発の足腰を鍛えよう Rackワークショップに参加しました! こちらについては長くなりそうなので、また別記事に記載しようと思います。 面白かったです! エンジニア2年目で参加してみてどうだったか 正直な感想として、「思ったより理解できたな」と感じました。 興味のある講演を選んで聞いていたというのもありますが、スピーカーの方が伝えたいことはおおむね理解できたのではないかと思っています。 スクールに通っていた頃にオンラインで見ていたRuby Kaigiや1年ほど前に参加したRubyWorld Conferenceは、お恥ずかしながらあまりわからなかった…という感想でした。 しかし今回のKaigi on Railsは業務で実際に経験した場面についての内容も多く、全体的に理解度が上がったなという感覚がありました。 スピーカーの方の経験を聞いて業務に活かせることはないかと考えたり、講演を通して新しく知った技術について深掘りしてみたいなと思ったり、純粋に面白かったです。 難しそうだしまだ参加するのは早いかな…と最初は思っていたのですが、参加して良かったです。 今後は積極的にイベントに参加してみようと思えた良い経験でした! イベント全体を通しての感想 今回のイベントで最も印象に残った言葉は「Rails wayに乗る」でした。 基調講演だけでなく多くの講演でこの言葉が使われていました。 Rails wayを楽しく歩いていくこと、それがRailsを使っての開発における最適解なんだなということが強く印象に残りました。 まだRails wayをしっかり理解できていないのでRails wayを知るところから進めていこうと思います。これが私のKaigi on Railsの宿題です。 最後になりましたが、スピーカーの皆様、スタッフの皆様、素敵なイベントをありがとうございました! 最後までお読みいただきありがとうございました。
RubyWorld Conference 2023に参加!!
初めまして! 今年の6月に入社した冨田です。 入社して、早くも4ヶ月が経ちました。初めてブログを書く機会が来ました! 最初のテーマは、「RubyWorld Conference 2023に参加!!」です。Rubyが生まれて30年、RubyWorld Conferenceが始まって15年という節目を迎えた今年、参加することができて良かったです。 初日の冒頭では、「歴史から学ぶ」というテーマでRubyの生みの親である”まつもとゆきひろ”さん(以下、Matzと呼ばせていただきます)の基調講演から始まりました。 今までのRubyの歴史・将来のRuby・OSSコミュニティについてなどをわかりやすくお話していただきました。 特に印象的だった部分は、 We are f**ed unless we can come up with something that will excite the community, because everyone’s getting bored and going off and doing other things 「コミュニティを刺激するなにかがないと、興味を持つ人が減って、他の分野に流れてしまう」のような意味合いがあると思いますが、技術が日進月歩で発展していく中で、どのように刺激的なことを起こしていくのかという部分がとても興味深かったです。 Rubyが生まれて30年という節目で、Hype CycleのPlateau of Productivityに突入しています。これは、技術が広く受け入れられて安定期に入った段階を指します。 Matzは、技術の成熟が進み、安定期に入った段階が停滞期になっていないかと危惧していました。Rubyが更なる発展を遂げていくためには、より魅力的な言語・コミュニティになっていく必要があります。 現在、Rubyをメインに勉強している私としては、Rubyの発展のために積極的に参加し、貢献していけるよう努力していきたいなと感じました。 また、別会場では多くの企業が出展しており、各企業ブースも見学させていただきました! 特に印象に残ったブースは、Smalrubyとmruby/cを使ったMatz葉がにロボコンを共催する「しまねOSS協議会」でした。 松江工業高等専門学校の主催で、第1回 Matz葉がにロボコンが開催されるようで、ブースで宣伝を行っていました。興味のある方は紹介ムービーをぜひご覧ください。 動画の紹介でもあるように、白線に沿って動いていくようにプログラミングしていくのですが、多足歩行ロボットなので、揺れによってセンサが動いてしまい、なかなか思い通りに進まないという絶妙な難しさが良いみたいです。 メインは、小学生をターゲットとしていますが、中学生以上のオープン部門があるそうなので、一度挑戦してみたいなと思いました! その時は、スクラッチではなく素のRubyを使ってプログラミングしてみたいと思います! 以上で、初めてのブログ記事を締めたいと思います。ありがとうございました〜 写真は、本物の松葉がにです(Matz葉がにではありません)
timestampsマクロとは何者なのか?
みなさん、こんにちは。 今年は久しぶりに花粉の影響が強く苦しんでいる小林です。 また一つ、Ruby on Rails(以下、Rails)の謎が解けたので、紹介したいと思います。 今回のテーマは、こちらです。 timestampsマクロは何をしているのか? timestampsマクロは何をしているのか? timestampsマクロとは何か? timestampsを呼び出すと作成日時(created_at)、更新日時(updated_at)を自動的に作成してくれます。 # db/migrate/2023032562631_create_products.rb class CreateProducts < ActiveRecord::Migration[7.0] def change create_table :products do |t| t.string :name t.text :description t.timestamps end end end sample=# \d products id | bigint | | not null | nextval('products_id_seq'::regclass) name | character varying | | | description | text | | | created_at | timestamp(6) without time zone | | not null | updated_at | timestamp(6) without time zone | | not null | (↑うまく整形できなかったので、諦めました。) Railsガイドにも記載されています。 timestampsマクロは、created_atとupdated_atという2つのカラムを追加します。これらの特殊なカラムが存在する場合、Active Recordによって自動的に管理されます。 引用:Railsガイド#1 マイグレーションの概要 使用する分にはこれで十分なのですが、中で何をやっているのだろうと気になってしまったのが事の始まりでした。 何をしているのか? 結論から言うと、さほど複雑なことはしていませんでした。 active_record/connection_adapters/abstract/schema_definitions.rb#L460-L469 def timestamps(**options) options[:null] = false if options[:null].nil? if !options.key?(:precision) && @conn.supports_datetime_with_precision? options[:precision] = 6 end column(:created_at, :datetime, **options) column(:updated_at, :datetime, **options) end 要は、自身で以下のように書けるけど、timestampsマクロを使用すれば、記述量が減らせて楽ですよ。ということです。 # db/migrate/2023032562631_create_products.rb class CreateProducts < ActiveRecord::Migration[7.0] def change create_table :products do |t| t.string :name t.text :description t.datetime :created_at, null: false, precision: 6 t.datetime :updated_at, null: false, precision: 6 end end end 最後に 今回は、仕組みが複雑怪奇というよりも、どこで定義されているかが見つけられずにもやもやしていたので、読み込みが足りないなと痛感しました。
RubyWorld Conference 2022に参加してきました!!
みなさん、こんにちは。 小林です。 11/10〜11/11に開催されたRubyWorld Conference 2022に参加してきました。3年ぶりのリアル開催です!! 私はRuby関連のイベントへの参加自体が初になりますので、その様子をブログにまとめてみました。 1日目のMatzの講演では、Rubyに対する批評にユーモアを交えながらコメントすることから始まり、Rubyの向かう先、Ruby3.2の内容と、とても興味深い内容でした。 要約しますと、充電しておくことはとても重要だということです!! Matzの講演の後は、皆で八雲庵にお蕎麦を食べに行きました。 WYRDのお決まりのお店らしく、私は鴨南蛮そばと割子そばを食べましたが、とても美味しかったです。 昼食後は会場に戻り、Matzにご挨拶をさせていただきました。 名刺交換し、写真を撮り、サインまでいただき。いや〜、緊張しました。。。 2日目の最初はAaronの講演から始まりました。 導入部分の話ですが、JavaとRubyを比較していた際に、もともと私がJavaを主言語としていたこともあり、Rubyの良さが改めて理解できた気がします。 わかったよ!! Rubyの良さが!「言葉」ではなく「心」で理解できた! ノベルティもしっかり配ることができました。(MatzにもAaronにもお渡しできました!!) 縁結びのお守りですが、実は秘密が・・・ 気になる人は、ぜひこちらの記事をご覧になってください。 RubyWorld Conference 2022も無事に終了し、WYRD以外のRuby業界の方々とお話しすることができ、とても勉強になりました。 土曜日は皆で観光に行きました。当然、松江城にも行きました。 松江城に行くために、松江に来たと言っても過言ではありません。 松江城は現存十二天守にして国宝というとても貴重な史跡なので、松江に訪れた際には、ぜひ併せて訪れていただきたい場所です。 長くなりましたが、これにて筆を置かせていただきたいと思います。
RubyWorld Conference 2022 記念ノベルティ『縁結び』
『縁結び』について 2019年以来のオフライン開催を記念し、コロナ禍を乗り越えて新しい<縁>が結ばれることを期待してノベルティ『縁結び』を配布します。 使用方法 神社で手に入る他の御守りと同じです。常に身につけるようにしていれば問題ありません。 持ち歩くのが難しい場合は、引き出しに片付けず目の届く明るいところに飾ってください。 『縁結び』の中には 《願い札》 と 《ルビーの原石》 が入っております。原石はとても小さいので画像は割愛します、また扱いにはご注意ください。 《願い札》 にはお願い事を書いて袋に入れて大切に保管してください。 《ルビーの原石》 はプログラミング言語Rubyに因んだパワーストーンとして同梱しましたので願掛けにお使いください。 デザインについて 宝石はRuby、星の数はVer3、金と銀の星はRuby技術者認定試験に因んでおります。 弊社デザイン部および全社員の意見を取り入れた渾身の作です。 入手方法 RubyWorld Conference 2022 の開催期間2022年11月10日(木)・11日(金)に島根県立産業交流会館 「くにびきメッセ」国際会議場(3F)の入口近くのスポンサー広報配布物エリア、または当日会場でカンファレンス参加中の弊社社員にお申し付けください。数に限りがありますので、なくなり次第終了となります。
なぜRuby on Railsではrequireを実施なくてよいのか
こんにちは。 今年は花粉影響が大きく、外出するのが辛い小林です。 今回はRuby on Rails(以下、Rails)を使用するようになってから、ずっと気になっていたことが(たくさん)あるのですが、それが1つ解決しました!! その喜びを伝えたく、キーボードを執りました。 今回のテーマは、これです。 なぜ、bundlerでインストールしたgemをrequireせずに使用することができるのか? はじめに Rubyの勉強を始めたときにこういうことを覚えますよね? 外部ファイルを使用する場合はrequireにて対象のファイルをロードする 参考:module function Kernel.#require しかし、bundlerとRailsを組み合わせて使用している際に、requireを使用しませんよね? なぜなのでしょうか? なぜ、reuqireを省略することができるのか? 皆さんは、なぜだと思いますか? 実は、requireしなくても呼び出すことができる? いいえ。 それだとrequireの存在意義がなくなってしまいます笑 「requireは同じファイルを複数回ロードしない」ということは、一度ロードされてしまえば、再度requireを実行する必要ない。 つまり、すでにどこかでrequireが実行されている? よいところに目をつけましたね。 それでは、答え合わせをしていきましょう。 答え合わせ 答えは以下のファイルにあります。 config/application.rb config/apprlication.rb このファイル内で以下の記述があります。 Bundler.require(*Rails.groups) 参考:yasslab/sample_apps/blob/main/6_0/ch14/config/application.rb#L7 この処理によってGemfileに記載されているgemが依存関係を含めてロードすることができるようになります。 If you have a lot of dependencies, you might want to say "require all of the gems in my Gemfile". To do this, put the following code immediately following require 'bundler/setup': Bundler.require(:default) 参考:How to use Bundler with Ruby#Setting Up Your Application to Use Bundler ソースコード的な解説をしだすと切りがないので省略しますが、興味がある方は以下を参考にしてください。 参考:bundler/lib/bunder.rb Bundler.requireでGemfile内のgemをロードするのはわかったのですが、そもそもBundler自体もgemなので、どこかでrequireしないといけないのでは? 上記に記載がある通り、require 'bundler/setup'の後に実施するように記載されています。 該当コードを確認すると内部でBundlerをロードしています。 参考:bundler/lib/bundler/setup.rb 最後の疑問です。 config/application.rb内では、require 'bundler/setup'を実施していないではないですか。 config/boot.rb config/application.rb内でrequire_relative 'boot'を実施しています。 config/boot.rbを確認すると、require 'bundler/setup'を実施していることが確認できます。 参考:yasslab / sample_apps sample_apps/6_0_0/ch14/config/boot.rb 参考:Railsの初期化プロセス 注意事項 以下のように:require => falseと指定すると、Bundler.requireを実行しても、ロードされないので、注意してください。 Specify :require => false to prevent bundler from requiring the gem, but still install it and maintain dependencies. gem 'rspec', :require => false gem 'sqlite3' 参考:Gemfiles 最後に 最初のRails案件でプルリクエスト出した際に、「個別のrequireは不要」と指摘されて依頼、ずっと気にかけていたことなので、本当によかったです。 完全に理解しました。(Railsガイドちゃんと読まないと。。。) 他にも気になっているものは多々あるので、引き続き調査していこうと思います。 参考 Railsの初期化プロセス How to use Bundler with Ruby Gemfiles rubygems / bundler bundler/lib/bundler/bundler.rb bundler/lib/bundler/setup.rb
複数環境に対応したRailsアプリケーションの設定方法
Railsには RAILS_ENVと呼ばれる環境を切り替えるための環境変数が用意されています. 最初はこれだけでも十分ですが開発が進むと環境毎に切り替えるプロジェクトがよくあるので備忘録として自分がよくやる対応をまとめてみました. config_for config/database.ymlの様に環境毎で切り替える設定はconfig_forというメソッドがあるのでこれを使うとスッキリ書けます. Rails6 であれば、 shared でマージされるのでデフォルト値が手軽に設定できます.Rails5を使ってるのであれば、YAMLのAnchors and Aliasesを使ってマージすると便利です. # config/foo.yml --- shared: key3: "shared value" base: &base env: <%= Rails.env %> key1: "<%= ENV['MY_APP_KEY1'] || 'default' %>" key2: "hello %{user_cd}" production: <<: *base # config/application.rb module MyApp class Application < Rails::Application config.foo = config_for(:foo).deep_symbolize_keys end end ### ruby Rails.configuration.foo[:key1] # => default Rails.configuration.foo[:key2].gsub('%{user_cd}', 'dummy1') # => hello dummy1 Rails.configuration.foo[:key3] # => shared value # if Rails6 # => nil # if Rails5 設定より規約を活用して設定を減らす 普通にconfig_forを使ってるとYAMLの設定ファイルの運用が進むにつれて数が増えてきます.もしくは、既存のシステムがあるとすれば既に膨大な設定になってるかと思います.そこで設定より規約を使って最初から規約寄りにしておいた方が良いでしょう. YAMLでは値にkey1: nullとあるとNULL値(Rubyだとnil)になります. key1: 'null' の様にクォートで囲むと文字列の"null"になります. これを利用して以下の様にしていきます. # config/foo.yml --- production: key1: <%= "'#{ENV['MY_APP_KEY1']}'" || 'null' %> # config/application.rb module MyApp class Application < Rails::Application config.foo = config_for(:foo).deep_symbolize_keys end end ### something ruby implements def config_foo_key1 "${Rails.configuration.foo[:key1] || 'default'}" end config_foo_key1 の様に実装側にデフォルト値を用意することで、YAMLの設定ファイル自体がコンパクトになります. baseやshared にデフォルト値を寄せても良いと思います. このケースの良いところは全ての環境が規約だけで運用できる様になった時、YAMLファイルが不要になるところにあります. 既存のハードコードされた設定があるのであれば、これらの方法を使って減らしていくと良いと思います. bundle exec rails runner -e development 'puts config_foo_key1 'default' MY_APP_KEY1=foo bundle exec rails runner -e production 'puts config_foo_key1 'foo' 環境変数にも規約をつける アプリで固有で使う環境変数にも MY_APP_KEY1 の様に接頭辞MY_APP_の様に規約をつけると良いでしょう.grepした時に探すのも楽になるし、直感的にアプリ固有の環境変数だということがわかります. 環境毎にユニークな名前空間を使う ここでの名前空間は以下の様なものを指しています. AWS S3のバケット名 ディレクトリのパス データベース名 全文検索のインデックス名 キャッシュのキー名 通常、プロダクション環境だと、複数環境が相乗りになることは無いはずですが、デモ環境や開発環境は複数環境が相乗りになることがあります. 含める変数 Railsでは 環境変数 RAILS_ENV があるし、parallel_tests では ENV['TEST_ENV_NUMBER'] を使って並列に動作できるようにしています. さらにアプリ固有の環境変数もある場合もあります. これらを含めた名前空間にすることで開発環境の様に developmentとtestが同じPCで動かせる様になります. 例えばS3のオブジェクトのキーを考えてみましょう. 環境変数とデモ環境などの実際に動作する物理的な環境であれば MY_APP_ENV の値には demo,prd,stg, qa そして dev の様な値が入るとします. 名前空間は "#{Rails.env}#{ENV['TEST_ENV_NUMBER']}/${ENV['MY_APP_ENV']}" の様な規約にしておきます. これらの変数の組み合わせが展開されると以下の様になります. 名前空間が重なってないため柔軟に同じサーバや開発環境内に同居できる様になります. RAILS_ENV TEST_ENV_NUMBER MY_APP_ENV name space development dev development/dev production demo production/demo production prd production/prd production stg production/stg production qa production/qa test dev test/dev test 2 dev test2/dev
よく見る Capybara を利用したコードの誤った書き方
Capybara は良くクローラーとか E2Eテストで使われると思いますが、比較的E2Eテストで利用されることが多いと思います. ここでは E2Eテスト での Capybara の誤ったコードを紹介していきます. 動的なDOM 現在ではJSによって動的にDOMが変更されるため、常にDOMに変更が加わることを前提にコードを書く必要があります. Capybara APIの Check系のメソッドには対象の状態(DOM要素の存在、表示の状態)になるまでリトライされる機構があります. この辺の非同期の内容は公式ドキュメントのAsynchronous JavaScript (Ajax and friends)に書いてあります. 反対にCheck系以外の値を単純に取得する様なメソッドは、その時点のDOMから情報を取得します. 動的なDOMをテストするには以下のような3つステップを踏むことで対応ができます. 事前状態のチェック アクション 事後状態のチェック 例えば、ユーザ名の変更のユースケースを例にすると以下のように表現できる. 事前状態のチェックexpect(page).have_field('firstName', with: "old name") アクションfind("input.firstName").set("new name")find("button.update").click 事後状態のチェックexpect(page).have_field('firstName', with: "new name") input要素 には name属性 指定がない Input要素 には has_field? を使う.以下のDOMを前提に説明していきます. <div class="firstName"> <input name="firstName" value="John" /> </div> <div class="lastName"> <input value="Smith" /> </div> input要素のname属性がfirstName の入力値を確認する場合は以下の様にします. find(page('.firstName')).has_field?('firstName', with: 'John') # => true input要素のname属性がない場合は以下の様に書くことになるので直感的ではない為、避けるべきでしょう. find(page('.lastName')).has_field?(nil, with: 'Smith') # => true 配列として扱う # bad expect(all('.title').count).to eq 5 expect(all('.title')[1].text).to eql('hello') # good expect(page).to have_selector('.title', count: 5) expect(page).to have_content('.title', with:'hello', exact: true) ノードの数を調べる場合は has_selector? の count を検討するべきです. n番目のノードを取得する際は :nth-child()か:nth-of-type()を検討すると良い. all('.title').count や all('.title')[1].text が相応しくない理由は、評価時点でのDOMしか確認できないからです. count の場合は要素の数を取得しあた後にDOMに変更があった場合で期待値と異なってしまいます. [1].text の場合は2つの問題があり、1つ目は [1] でもしDOMが1つの要素の配列だった場合は nil になってしまい nil.text の様な評価をされてしまいNoMethodError が起きます. 2つ目は例え要素が2つ以上存在して取得できた場合でも、count同様その時点のDOMの評価になるため期待値と異なってしまう場合があります. 値を取得してしまう has_content? は has_text? のエイリアスで同じものです.オプションの exact のデフォルトは false なので正確に一致させる場合は true を指定する方が良いでしょう. false の場合は部分一致になります. # bad expect(find('.title').text).to eql 'hello' # good expect(page).to have_content('.title', with: 'hello', exact: true)
資格試験のご報告
こんにちは、浅野です。 前回のブログ更新からあっという間に3ヶ月が経ちました。本当に早いです。 前回は、Ruby Silverを受験するぞ!という記事を書きました。前回の記事 気になる結果ですが...無事に合格できました!!そして、勢いそのままRuby Goldも受験し、こちらも合格することができました!わーい! とは言ったものの、特にGoldの試験は難しく、参考書に載ってない問題も多く出題され、非常に焦りました。試験中は、PCに頭突きしたい衝動に苛まれ、最後の採点ボタンを押す手は震えました。無事合格できたものの、自分の知識不足を改めて痛感し、この結果に甘んじてはいけないなーと思っています。 というわけで今回は、試験で間違えたことで、新しく得た知識のアウトプットをしていきたいと思います。今回取り上げるのは、Moduleクラスのインスタンスメソッド、append_featuresです。恥ずかしながら試験を受けるまで、きちんと理解していませんでした。 早速、以下の2つのコードを見ていきましょう。 A module M def self.append_features(klass) super p klass.ancestors end end class C include M end B module M def self.append_features(klass) p klass.ancestors end end class C include M end 上記のコードでは、append_featuresというメソッドを上書きしたmodule Mが、class Cにincludeされています。違いとしては、append_features内のsuperの有無です。それぞれどのような挙動になるかを見ていきたいと思います。 そもそもappend_featuresとはどのようなメソッドでしょうか。公式リファレンスによると、 Module#include の実体 とあります。 つまり、append_featuresを上書きすることで、includeされる際の挙動に影響が出ることになります。 superがあれば、既存のappend_featuresが継承され、モジュールがincludeされますが、ない場合は、includeされません。 実際にirbで挙動を確認してみましょう。まずAのコードです。こちらはsuperを記述しています。出力結果は以下となりました。 [C, M, Object, Kernel, BasicObject] 一方、superを記述していないBはというと、 [C, Object, Kernel, BasicObject] module Mがincludeされていません。 ということで、append_featuresを上書きする際は、superを記述しないと、モジュールがincludeされなくなってしまいます。これによって想定と挙動が異なる可能性が生まれるので、注意が必要ですね。 Ruby Goldではこんな知識が問われます。普段滅多に見ないメソッドが出題され、私は結構焦ってしまいましたが、新しい知識を習得できたので良かったです。 試験範囲としてあまり知られていないところであるかと思いますので、どなたかのお役に立てば幸いです。
Rubyの正規表現
こんにちは。 WYRDの豊田です。 持ち回りブログ3週目です。 早速ですが、みなさんはお休みの日はどのように過ごしていますか? 私たちの業界は基本的に土日お休みなことが多いのですが、私は特に予定がなければ技術的な勉強(本を読んだり、調べ物をしたり)に時間を割くことが多いです。 技術は物凄いスピードで進化・進歩していて、常にアンテナを張っていないとすぐに取り残されてしまいますからね。 「これだけ学べば十分」と思える日は来ないと思っています。 少し話が逸れてしまいました。 最近、弊社内ではRuby技術者認定試験に合格しようぜ!という機運が高まっています。 この間の浅野さんのブログ記事もSilverを受験するというお話しでしたね。(ここだけの話、合格したらしいですよ) ということで、私も今更ながらGoldの合格を目指して久しぶりに試験勉強を始めました。 今回は試験勉強の中で出てきたRubyでの正規表現について書いていこうと思います。 基本的なところ Rubyでは他の多くの言語で採用されているPerl拡張正規表現が採用されています。(完全互換ではないので注意) Regexpクラス 正規表現を使ったパターンマッチングを行うにはRegexpクラスを利用します。 Regexpはregular expressionの略ですね。 Regexp.new('hoge') === 'hoge' #=> true または、正規表現リテラルを使うこともできます。(生成されるオブジェクトはRegexpクラス) /hoge/ === 'hoge' #=> true %r{hoge} === 'hoge' #=> true パターンマッチ パターンマッチには以下の方法があります。 Regexp#=== Regexp#=~ String#=~ Regexp#match? ( Symbol#match?, String#match? ) ※ 2.4以降 /hoge/ === 'hoge' #=> true /hoge/.match?('hoge') #=> true :hoge.match?(/hoge/) #=> true # `=~` はマッチした位置を返す /hoge/ =~ 'hoge' #=> 4 'hoge' =~ /hoge/ #=> 4 # String#===は挙動が異なる 'hoge' === /hoge/ #=> false String#===は同値であるかの判定しかしません。 Regexp#match Regexp#matchメソッドを使えば、マッチするかの判定に加えマッチした情報の詳細を取得することもできます。 match_data = /\d/.match('hoge9') match_data.class #=> MatchData MatchDataクラスについては、話すと長いのでここでは割愛します。 MatchData - リファレンスマニュアル 先頭と末尾 これはRubyを使っていると一度は通る道だと思います。 /\A ... \z/とすることで、文字列の先頭と末尾を明示的に指定できます。 他の言語でいうところの ^ , $ です。 Rubyでも ^ と $ も使えますが、挙動が違います。 "hogehoge\n1234567890" =~ /\A\d+\z/ #=> nil # 行単位でマッチするか確認するので、改行コードが入っていると挙動が変わる "hogehoge\n1234567890" =~ /^\d+$/ #=> 9 あと /\A ... \Z/というのもありますが、あまり使わないので割愛します。 (知りたい方はググるとたくさん良い記事が見つかります) キャプチャと後方参照 キャプチャは正規表現では結構普通に使われるテクニックになりますが、Rubyでも利用可能です。 ()で囲んだ範囲がマッチすると、マッチした文字列を同一正規表現内で使ったり確認したりできます。 # キャプチャした文字列は \1 で後方参照できる /(\w+) of \1/ === 'hoge of hoge' #=> true # Rubyの実行環境内であれば $1 でキャプチャ文字列を参照できる $1 #=> 'hoge' 複数キャプチャした場合、\1, \2, \3... , $1, $2, $3... 数字を増やすことで後方参照できます。 名前付きキャプチャ \1 で後方参照するのは直感的ではなく使いづらい気もします。 そんな時はキャプチャには名前をつけて後方参照することができます。 名前付きキャプチャは (?<name>pattern) (or (?'name'pattern) )のように書きます。 後方参照時は \k<name> (or \k'name' ) と書くことができます。 /(?<number>\d+) and \k<number> is same number/ === '1 and 1 is same number' #=> true 名前付きキャプチャと前述の数字の単純なキャプチャは併用できません。"use name" と怒られます。 numbered backref/call is not allowed. (use name) また、 Regexp#=~ を利用した場合、キャプチャした文字列はローカル変数に代入してくれたりします。 (正規表現側に #{} による文字列展開が含まれていない場合に限定) /(?<name>\w+)/ =~ 'toyoda' #=> 0 name #=> 'toyoda' 部分式呼び出し マッチした文字列ではなくて、マッチした正規表現自体を呼び出すことも可能です。 \g<1> でキャプチャした箇所の "正規表現" を呼び出せます。 # /\d+-\d+-\d+/ と同じ意味 /(\d+)-\g<1>-\g<1>/ === '123-456-789' #=> true # 名前付きキャプチャも利用可能 /(?<num>\d+)-\g<num>-\g<num>/ === '123-456-789' #=> true なんかもういろいろ出来すぎて、そろそろ覚えていられなくなってきました。 あと少しで終わりにしようと思います。 先読み、後読み ある正規表現にマッチした位置より前(先読み)または後(後読み)にある特定の正規表現にマッチさせることができます。 肯定先読み(positive lookahead) マッチさせたい文字列の後ろに、さらに特定の文字列が続く場合にだけマッチさせたい場合に使います。 わかりにくいと思うので例を示します。 肯定先読みは (?=pattern) と記述します。 # "ですかね" が続く直前の数字を取りたい /\d+(?=ですかね)/.match('たぶん20ですかね') #=> #<MatchData "20"> 否定先読み(negative lookahead) 肯定先読みの逆です。 マッチさせたい文字列の後ろに、特定の文字列が続かない場合にだけマッチさせられます。 否定先読みは (?!pattern) と記述します。 # "ですかね" が続かない直前の数字を取りたい /\d+(?!ですかね)/.match('たぶん20ですかね') #=> #<MatchData "2"> 直感的でない動作だと思った方もいるかもしれませんので、簡単に説明します。 /\d+(?!ですかね)/ が意味するところは "「ですかね」が続かない数字" です。 20という文字列のうち 0は後ろに "ですかね" が続くので否定条件に合致します。(マッチしません) 2は後ろに "0" という文字が続くので否定条件に合致しません。(マッチします) 肯定後読み(positive lookbehind) 肯定先読みは後に続く文字を指定しましたが、後読みは先に来る文字列を指定します。 肯定後読みは (?<=pattern) と記述します。 /(?<=答えは)\d+/.match('答えは3600円でした') #=> #<MatchData "3600"> 否定後読み(negative lookbehind) 否定先読みと同じ要領で、先行する文字列を指定します。 指定した文字列に続かない文字列を条件にマッチします。 否定後読みは (?<!pattern) と記述します。 /(?<!答えは)\d+/.match('答えは3600円でした') #=> #<MatchData "600"> これも、否定先読みと同じ原理ですね。 "3" は否定されますが、それ以降の "600" は該当しないのでマッチします。 最後に Rubyの勉強していたはずなのに、なぜか正規表現の勉強をしていたなんてことは良くある話で... 他にも色々ありますが今日はこの辺にしておこうと思います。 いやー正規表現は奥が深い。 興味のある方はRubyの公式リファレンスを見てみてもいいかもしれません。
Ruby World Conference 2019 レポート
今年も11/7,8で開催された年に1度のRubyの祭典 Ruby World Conference に行ってきました。今回はWYRDメンバーとパートナーメンバーあわせて総勢10名と過去最多人数での参加! 初日午前中のMatzの基調講演を聞くために前日夜入りして、まずはWYRDメンバーで軽く前夜祭^^ 翌朝は寝坊せずに会場のくにびきメッセへ! 早めに行ったつもりでしたが既にたくさんの来場者が来ていました。今年のWYRDノベルティは、メンバー似顔絵チロルチョコとマイクロファイバークロス! 午前中はMatzの基調講演「How to dominate the world」会場は超満席で立ち見も出るほどでした。当日のプログラムはこちら※各講演の資料と映像がYoutubeで見れます お昼御飯は松江城近くの八雲庵さんで美味しいお蕎麦を堪能あまりの美味しさに「鴨なんばん」と「割子そば4枚」を食し大満足! 午後は1階のサテライト会場で仕事をしながら講演を聞くスタイル。平日開催なので東京での仕事は動いてるから合間見てちょこちょこ仕事なんです。 初日の講演も終わり、夜はレセプション。美味しい島根料理に美味しい島根のお酒で、参加者の方々と近況報告したり情報交換したりおしゃべりです。 レセプション後半になるとMatzとの写真撮影行列ができるので、行列できる前にMatzにお願いしてスポンサーボード前で記念撮影! ちなみに昨年までは「Goldスポンサー」でしたが今年は新設された「Nurseryスポンサー」で協賛。ここ最近お子さん連れでこのConferenceに参加される方がちらほらいましたので、もっとお父さんお母さんエンジニアが参加しやすいようにと託児所費用を提供させて頂きました。 創作料理と島根の唄-縁(えにし)さんでのRWC2019オフィシャル2次会にも参加とっても盛り上がった1日でした! 2日目は早朝から出雲大社観光へ日中はめちゃくちゃ観光客で混むのでゆっくり参拝したいなら9時前がオススメです。今年はちょうど出雲大社での神在祭(11/7~11/13)にかぶったので、いろいろなご縁をお願いしてきました。 お昼前に出雲から松江に戻り連日の八雲庵にて早めの昼食。「鴨なんばん」に「5種割子そば」を頂きました。美味しかった^^ 2日目午後の講演も終わり、最後は実行委員会副委員長のNacl井上社長のクロージング昨年に続き今年も2年連続の来場者数1,000人超えと大盛況の会でした。 翌日は島根観光組とRWC2019ゴルフコンペ参加組に分かれて別行動。スコアは残念な感じでしたが、11月にしては暖かく晴天のゴルフ日和で楽しませて頂きました。 あれだけ蕎麦食べたのにまだ飽き足らず最後に出雲空港でラスト蕎麦^^; また来年もできるだけ多くのメンバーでRWC2020に参加したいと思います!実行委員の皆さま、事務局の皆さま、ありがとうございましたm(_ _)m
田んぼIoT in 2018 その4
あけましておめでとうございます。 WYRDの豊田です。 始まったばかりの2019年ですが、気づけばもう1月も半分が終わってしまいましたね。本当にあっという間です。 昨年末から3回に分けて弊社で取り組んできた「田んぼIoT」の振り返りをしてきました。過去の記事はこちらからご覧いただけます。 田んぼIoT in 2018 その1 田んぼIoT in 2018 その2 田んぼIoT in 2018 その3 今回は4回目、とうとう最終回です。 前回のように技術の話は少なめで、活動報告的な内容になります。 おさらい 試行錯誤の末、昨年の春に田んぼに設置した田んbotですが、なんとか稲刈りまでの約半年稼働させることができました。 田植えから稲刈りまでの期間の気温と地中の温度を計測・蓄積するという、当初の目的は達成できたのではないでしょうか。 今回の取り組みで見つかった反省点は、今年の改良版田んbotに活かしたいと考えています。 ちょっと変わった取り組み 一年間、WioLTEを使って**「温度を計測する」**というチャレンジをしてきたわけですが、データが蓄積できたら終了。というのは少し寂しいですよね。 せっかくの取り組みをもっといろんな人に知ってもらいたいと思い、その1の記事でも書いた通り、RubyWorld Conference 2018のスポンサーブースに展示(設置)しようと考えました。(WYRDはGoldスポンサーとして協賛しています) RubyWorld Conferenceとは Ruby処理系をはじめとしたRuby関連技術の最新情報や、言語仕様の標準化の動向、先進的な事例などを紹介するさまざまなセッションを通じて、Rubyがより多くの領域に普及していくことを願っています。 RubyWorld Conference 2009 開催趣意書 より 年に一度、プログラミング言語 "Ruby" を使う企業、エンジニアが集い、Rubyに関する情報交換や取り組みを発表、報告する一大イベントです。 Rubyの祭典に田んbotを展示するわけですが、(過去の記事に書いた通り)田んbotには全くRubyの要素がありませんでした。 Rubyと全く関係の無いものを展示しても面白みがありませんよね。 色々検討した結果、組み込み向けに開発されている "mruby/c" というプログラミング言語を使って、田んbotを動かそうという話になりました。 mruby/cは、Rubyの特徴を引き継ぎつつ、プログラム実行時に必要なメモリ消費量が従来のmruby(福岡で開発された組込み向けの軽量Ruby)より少ないmrubyの実装です。 しまねソフト研究開発センター「mruby/cとは」より WioLTEをmruby/cで動かそう mruby/cでWioLTEを動かす。とは言っても、最終的な(センサーから温度を取得したり、データをサーバーに送信したりといった)処理は、C言語で実装しなければならず、そこについてはこれまでの実装をそのまま流用することになります。 簡単に説明すると、C言語で実装した各種関数を、mruby/cから実行する。という仕組みになります。 mruby/cで実行するには、いくつか気をつける点はありますが、これで動作するようになります。※具体的な説明は割愛します ライブラリを更新したら、パラメータの仕様が変わってて全然動かなくなったり、相変わらずトラブルはありましたが無事稼働させることができるようになりました。 田んbot(mruby/c ver.)展示へ 無事、田んbot(mruby/c ver.)を展示することができ、開催期間中はたくさんの来場者の方に興味を持ってもらえました。(こちらの記事もどうぞ) 会場の気温を計測しサーバーに蓄積。それを表示するWebサイト(もちろんRuby on Rails)も用意して、iPadで表示させることで、とてもコンパクトな田んbotの完成です。 まとめ 2018年は本当に田んぼIoT漬けの1年間だったように思います。 この取り組みを、株式会社ソラコムさんにも興味を持っていただき、SORACOM conference "Discovery" 2018で登壇させていただくなど、本当に色々な体験をすることができました。 まだまだ小さな取り組みではありますが、少しずつできることを増やしていきたいと思います。 今年も田んぼ設置に向けて頑張りたいと思います。 面白いネタが集まったら、また記事を書こうと思いますので楽しみにしていてください。
WYRDの Ruby World Conference 2018 レポート
Ruby World Conference 、、、この言葉からどんなものをイメージしますか? 「Ruby?宝石の展示会??」→ Ruby World Conference 2018 をまずはご覧いただいてから本記事に進んでください 「Rubyのイベント!新しい情報を手に入れるぞ」→ Ruby World Conference 2018プログラム このようなプログラムで素晴らしいお話がたくさんありました。本記事では会場の雰囲気などをお楽しみください 「今年もRWCの季節か、1年が早いなぁ」→ どうぞそのままお進みください 年に1度のビッグイベント、RubyWorld Conferenceが今年も島根県松江市のくにびきメッセで開催されました Goldスポンサーとなっている我々、株式会社ウィルドもin島根でございます サービスのパンフレットやグッズ的なのはありませんが、山形で活躍した田んぼIoTキット(mruby/c)を展示! (田んぼIoTについてはきっと別の記事で語られる、、、かもしれない) 会場の温度を一定間隔でサーバーへ送り、タブレットのブラウザでグラフを表示するというパンフレットやグッズが並ぶテーブルで異彩を放つ田んぼIoTキット!! 会場の1Fではスポンサー企業が並ぶパネルを発見!どれどれ、、、 10回目を迎えた記念すべきRubyWorld Conferenceのパネル(ほぼ)中央にWYRDのロゴを発見! ありました!うん、これはもうセンターと言っても過言ではないんじゃないかな? オープニングに備える手前の2人組(この後、田んぼIoTに突然のエラー、その場で修正対応という流れ) 初日、2日目とRubyの今後や様々な分野での利用ケースなど、多彩なテーマの講演を聴いていると新しい刺激や発見が多くて次のプロジェクトへの意欲が湧いてくる感じです。やっぱりRuby業界は面白いなぁ、、、 という興奮と感動に浸るのもつかの間、抱えてるプロジェクトにより「仕事」という現実がやってくるのも様式美 今回はmruby/cに関するテーマが2日目に多くあって、田んぼIoTを製作したT氏は次なるステージに向けて良い刺激になったんだろうと(たぶん)思います。 ボクはngx_mrubyに関する講演で「リクエストに合わせてmrubyが動いてごにょごにょできるとかたまらんぜ、グフフ」という感じでした。 そして初日最後のレセプションではまつもとさんと弊社メンバー(とRuby Associationの杉原さん)とのスペシャルショットが実現! このポーズはサムズアップであり次はきっと上位のスポンs、、、げふげふというサインらしい まつもとさんとS氏(ディレクター兼ansible使い)という珍しいツーショット。楽しそうに会話してるが、、、 他メンバー:(あいつ、Rubyほとんど分かんないのに、、、まつもとさんと会話できるのか??) 「M5Stack楽しいっすよね」 「でっかいスマートウォッチ作った人いたよね」 一同:そっちかよwwww そんな和やかなエピソードもありつつ、たくさんの方々と繋がることができたRuby World Conference 2018。 今年もあっという間に2日が過ぎたなぁと感慨に胸を熱くしつつ最後のクロージングに向かった我々 スクリーンに輝く「株式会社WYRD」の文字! ご紹介ありがとうございます!これからも頑張ります!! というわけでダイジェストでお送りした「WYRDの Ruby World Conference 2018 レポート」でした!(どういうワケだってば) おまけ 空いてる時間はとにかく食べてました(昼食:そば 夕食:ラーメンのヘビーローテーション) だって美味しいんだもん!









