Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

週刊Railsウォッチ(20200127前編)Railsでキーワード引数warning退治始まる、ライブラリとフレームワークの違い、ShopifyのRails高速化記事ほか

こんにちは、hachi8833です。Burikaigiが気になります。


つっつきボイス:「富山のBurikaigiがメシのうまさを大フィーチャーしてるので🍽」「冬の富山といえばブリでしょう🐟」「まだ行ったことなくて😢」「松江もいいけど富山もね😋」

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

お知らせ: 公開つっつき会2本立て

その1: 週刊Railsウォッチ「第19回公開つっつき会」(無料)

いよいよ第19回を迎えた公開つっつき会は、来月2月6日(木)19:30〜よりBPS株式会社Pubスペースにて開催いたします。

週刊Railsウォッチの記事やここだけの話にいち早く触れられるチャンス!発言・質問も自由です。皆さまのお気軽なご参加をお待ちしております。

臨時のお知らせ: 福岡でのリモート公開つっつき会は「延期」いたします(Wingdoor@福岡)

今週木曜に予定されていた福岡での公開リモートつっつき会は延期となりました🙇。


connpass.comより

Rails: 先週の改修(Rails公式ニュースより)

公式情報とコミットリストから見繕いました。

Ruby 2.7キーワード引数のwarning退治

参考: Ruby 2.7 の変更点 - Module - @tmtms のメモ

# activejob/lib/active_job/arguments.rb#66
-     private_constant :PERMITTED_TYPES, :RESERVED_KEYS, :GLOBALID_KEY, :SYMBOL_KEYS_KEY, :WITH_INDIFFERENT_ACCESS_KEY
+     private_constant :PERMITTED_TYPES, :RESERVED_KEYS, :GLOBALID_KEY,
+       :SYMBOL_KEYS_KEY, :RUBY2_KEYWORDS_KEY, :WITH_INDIFFERENT_ACCESS_KEY
+
+     unless Hash.respond_to?(:ruby2_keywords_hash?) && Hash.respond_to?(:ruby2_keywords_hash)
+       using Module.new {
+         refine Hash do
+           class << Hash
+             if RUBY_VERSION >= "2.7"
+               def ruby2_keywords_hash?(hash)
+                 !new(*[hash]).default.equal?(hash)
+               end
+             else
+               def ruby2_keywords_hash?(hash)
+                 false
+               end
+             end
+
+             def ruby2_keywords_hash(hash)
+               _ruby2_keywords_hash(**hash)
+             end
+
+             private def _ruby2_keywords_hash(*args)
+               args.last
+             end
+             ruby2_keywords(:_ruby2_keywords_hash) if respond_to?(:ruby2_keywords, true)
+           end
+         end
+       }
+     end

つっつきボイス:「Ruby 2.7のキーワード引数対応は大変な作業😅」「そのあたりのコミットを上にまとめました」「修行感ある😆」「kamipoさんのツイート↓も喜びに満ちてますね」「たしかにruby2_keywords_hash?は欲しい機能でしょうね😋」

「あ〜確かにnon UTF-8が混じる可能性ある🥺: 自分の認識ではinspectはもともとヒューマンリーダブルにするためのメソッドなのであんまりバイナリセーフではないかも」「ふ〜む」「バイナリセーフにしたかったらMarshalあたりなのかな?🤔」

Object#inspect
オブジェクトを人間が読める形式に変換した文字列を返します。
docs.ruby-lang.orgより

# docs.ruby-lang.orgより
[ 1, 2, 3..4, 'five' ].inspect   # => "[1, 2, 3..4, \"five\"]"
Time.new.inspect                 # => "2008-03-08 19:43:39 +0900"

ふと英語のmarshalとMarshallの違いが気になりました。

marshal: 整列させる; 整理する; 案内する. [軍事] 元帥; 隊長.
Marshall: {人名} : マーシャル◆ファミリーネーム◆【語源】「馬丁」から「位の高い役人」まで広い意味を持つ、マーシャル諸島

「ちなみにちなみに素のRails 6.0.2.1とRuby 2.7では起動しただけでコンソールにこれだけwarningが出ました↓😆」「これを今後つぶしていくのは大変だな...」

/bundle/ruby/2.7.0/gems/actionpack-6.0.2.1/lib/action_dispatch/middleware/stack.rb:37: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/bundle/ruby/2.7.0/gems/actionpack-6.0.2.1/lib/action_dispatch/middleware/static.rb:110: warning: The called method `initialize' is defined here
#(略)
/bundle/ruby/2.7.0/gems/activerecord-6.0.2.1/lib/active_record/type.rb:27: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/bundle/ruby/2.7.0/gems/activerecord-6.0.2.1/lib/active_record/type/adapter_specific_registry.rb:9: warning: The called method `add_modifier' is defined here
Started GET "/" for 172.19.0.1 at 2020-01-23 08:53:58 +0000
/bundle/ruby/2.7.0/gems/activemodel-6.0.2.1/lib/active_model/type/integer.rb:13: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/bundle/ruby/2.7.0/gems/activemodel-6.0.2.1/lib/active_model/type/value.rb:8: warning: The called method `initialize' is defined here
/bundle/ruby/2.7.0/gems/activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb:12: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/bundle/ruby/2.7.0/gems/activemodel-6.0.2.1/lib/active_model/type/value.rb:8: warning: The called method `initialize' is defined here
Processing by Rails::WelcomeController#index as HTML
/bundle/ruby/2.7.0/gems/actionview-6.0.2.1/lib/action_view/view_paths.rb:11: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/bundle/ruby/2.7.0/gems/actionview-6.0.2.1/lib/action_view/lookup_context.rb:140: warning: The called method `template_exists?' is defined here
/bundle/ruby/2.7.0/gems/actionview-6.0.2.1/lib/action_view/unbound_template.rb:24: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/bundle/ruby/2.7.0/gems/actionview-6.0.2.1/lib/action_view/template.rb:130: warning: The called method `initialize' is defined here

MySQL 8.0.19でCIが落ちる問題を修正

# activerecord/test/cases/migration/change_schema_test.rb#L146
        elsif current_adapter?(:Mysql2Adapter)
-         assert_match "int(11)", default.sql_type
-         assert_match "tinyint", one.sql_type
-         assert_match "int", four.sql_type
-         assert_match "bigint", eight.sql_type
+         assert_match %r/\Aint/, default.sql_type
+         assert_match %r/\Atinyint/, one.sql_type
+         assert_match %r/\Aint/, four.sql_type
+         assert_match %r/\Abigint/, eight.sql_type

つっつきボイス:「MySQLの出力する文言が変わったというよくある修正☺️」「修正後はアサーションに正規表現が入ってきましたね」

# activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb#L80
-   assert_includes error.message, <<~MSG.squish
-     Column `old_car_id` on table `engines` does not match column `id` on `old_cars`,
-     which has type `int(11)`. To resolve this issue, change the type of the `old_car_id`
-     column on `engines` to be :integer. (For example `t.integer :old_car_id`).
-   MSG
+   assert_match(
+     %r/Column `old_car_id` on table `engines` does not match column `id` on `old_cars`, which has type `int(\(11\))?`\./,
+     error.message
+   )
+   assert_match(
+     %r/To resolve this issue, change the type of the `old_car_id` column on `engines` to be :integer\. \(For example `t.integer :old_car_id`\)\./,
+     error.message
+   )
+   assert_not_nil error.cause
  ensure
    @conn.execute("ALTER TABLE engines DROP COLUMN old_car_id") rescue nil
  end

#remove_connection#remove_connection_poolに変わる

  • #remove_connectionが非推奨になり、ハンドラで呼ばれるときは#remove_connection_poolが推奨になる。
    #remove_connectionが非推奨になった理由は、Hashの代わりにDatabaseConfigを返すことをサポートするため。#remove_connectionは6.2で削除されるので今後は#remove_connection_poolを使うこと。
    Changelogより大意

つっつきボイス:「poolが付いたのは何でなんでしょう?🤔」「おそらくですが、今後はコネクションプール単位でのみ扱うという意図があるのかもしれませんね☺️: 今はマルチプルデータベースが基本になっていますし」「ふむふむ」「configuration_hashを参照しているあたり、コネクションプール単位じゃなくてコネクション単位だと不整合が生じそうですし」

「コネクションプール自体は前からあったんでしょうけど」「以前は同じデータベースにつなぐコネクションプールしかありませんでしたね: この修正はたぶんRails 6でマルチプルデータベースになったことと関連しているでしょうし、remove_connectionだとコネクションを削除するように見えて誤解を招くと考えたんじゃないかな?🤔」「なるほど!」「まああんまりアプリ開発者が呼び出すコードではなさそうですけど😆」

# activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L1129
      def remove_connection(owner, pool_key = :default)
+       remove_connection_pool(owner, pool_key)&.configuration_hash
+     end
+     deprecate remove_connection: "Use #remove_connection_pool, which now returns a DatabaseConfig object instead of a Hash"
+
+     def remove_connection_pool(owner, pool_key = :default)
        if pool_manager = get_pool_manager(owner)
          pool_config = pool_manager.remove_pool_config(pool_key)

          if pool_config
            pool_config.disconnect!
-           pool_config.db_config.configuration_hash
+           pool_config.db_config
          end
        end
      end

cc/ @rafaelfranca @matthewd @jhawthorn @tenderlove
AR Baseのremove_connectionの値を返すように変更してよいかどうか今のところ不明だが、ドキュメントに記載がないのでこのやり方にして他を非推奨にする方法を選んだことで、オブジェクトをどこにでも引き回せるようになった。configuration_hashを返すことの問題は、返された設定がestablish_connectionに渡されるとRailsが新しいオブジェクトを生成することだった。このpublicメソッドの戻り値の変更について何か意見は?
同PRより抜粋・大意

新機能: ActionCable::Channelにストリームを個別に終了する機能が追加

ユーザーが特定のストリームのサブスクライブを解除できるよう、ActionCable::Channel#stop_stream_fromActionCable::Channel#stop_stream_forを追加した。
まとめ:
ユーザーがstream_from``stream_forを繰り返し呼ぶと1つのチャンネルで複数のストリームをフォローできるようになる。把握している限りでは、ActionCableには全ストリームのフォローを解除するActionCable::Channel#stop_all_streamsしかなかったので、ユーザーが特定のストリームをサブスクライブ解除できるようメソッドを2つ追加した。
同PRより大意


つっつきボイス:「いわゆるpub/sub」「ぱっと見startとstopかと思ったらstopだけでした😅」「fromとforは対象が違うのか」

# actioncable/lib/action_cable/channel/streams.rb#L105
+     # 名前付きブロードキャストのストリームをサブスクライブ解除
+     def stop_stream_from(broadcasting)
+       callback = streams.delete(broadcasting)
+       if callback
+         pubsub.unsubscribe(broadcasting, callback)
+         logger.info "#{self.class.name} stopped streaming from #{broadcasting}"
+       end
+     end
+
+     # モデルのストリームをサブスクライブ解除
+     def stop_stream_for(model)
+       stop_stream_from(broadcasting_for(model))
+     end

「この||= {}は?↓」「これは単にストリームが空のときは空ハッシュを返したいということです😆」「修正前は配列だったんですね」「そこが今回の修正にも関連していますね: 配列だとeachとかで取り出さないといけないけど、ハッシュにすればbroadcastingを引数にして特定の名前付きストリームを後から指定できるようになりますし」「なるほど!」「delegate :pubsub, to: :connectionとかせやなという感じ☺️」

# actioncable/lib/action_cable/channel/streams.rb#L127
      private
        delegate :pubsub, to: :connection

        def streams
-         @_streams ||= []
+         @_streams ||= {}
        end

「そんなにやらないかもしれないけど、特定のストリームのstopってたしかに使いたいときありそう、つか今までなかったのね😆」

番外: マイグレーションファイルの空行を削除

# activerecord/lib/rails/generators/active_record/migration/templates/migration.rb.tt#L33
<%- if migration_action -%>
  <%- if attribute.reference? -%>
    remove_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %><%= foreign_key_type %>
  <%- else -%>
    <%- if attribute.has_index? -%>
    remove_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
    <%- end -%>
-   <%- if !attribute.virtual? %>
+   <%- if !attribute.virtual? -%>
    remove_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
    <%- end -%>
  <%- end -%>

つっつきボイス:「公式の更新情報にしてはめちゃトリビアかなと思って😆」「誰もが消すヤツ😆: あ〜-が脱落してたのか」「ERBの-%>って改行しない指定でしたっけ?」「ですです」

参考: class ERB (Ruby 2.7.0 リファレンスマニュアル)

"-": 行末が-%>のとき改行を出力しない。また、行頭が<%-のとき行頭の空白文字を削除する
docs.ruby-lang.orgより

Rails

PunditとCanCanCanを比較しながら学ぶ


つっつきボイス:「どちらもいわゆる権限管理のgemですね」「どっちに乗るかで常に争いの火種になるヤツ🔫」「まあまあ😆」「使いたい方を使えばいいんじゃないかと😆: なお自分はCanCanCanキライじゃないんだけど、そうではない人もいましてですね🤣」「かといってPunditが好きというわけでもないと聞きました🤣」「マシという程度かも😆」

「印象としてはPunditの方が崩壊しずらいけど、CanCanCanはリクエストから原因を比較的追いかけやすい感じですかね、といってもここまでやられると↓つらそう😇」「ヤメテ〜😆」


同記事より


目次より、比較のポイント:

  • パーミッションのコード構成
  • レコードのフェッチ方法
  • テストのやりやすさ
  • パフォーマンス

個人的にはこの種のgemはパフォーマンスで選ばない方がいいと思う。既存のアプリでgemを乗り換えるのはたぶん意味ない。
個人的にはPunditがおすすめか: パーミッションをコントローラのアクション単位で定義できるし。
同記事より抜粋・大意

Active Recordメソッドを要件に合わせて選ぶ

関係ありませんが、medium.comのアカウントの試用期間が切れました。期間過ぎると有料だったとは...😇。


つっつきボイス:「初心者に優しそうな記事です」「Active Recordはメソッド多すぎですから😆」

「なるほどfind()find_by()where()とかか: この辺はぜひRails初心者に知っておいていただきたいですね〜、find()はレコードがないと404をraiseするけどfind_by()はしないとか☺️」

  • .find()
  • .find_by()
  • .where()

「そうそう、take()はなにげに速いんですよね🚄」

  • take()
  • first()last()

「とは言うものの、こういうのは結局自分で動きを追いかけないとわかってこないんですよ😅: あとSQLもある程度わかっておく必要ありますし」「たしかに」「自分の書いたコードがどんなSQLを生成するかに関心を持ってないとなかなかこういう部分を追いかけませんし☺️」

「こういうのはコードレビューを受けるうちにだんだん身に付いてくると思います: この記事のレベルに達していないコードにはこういう記事のリンクを渡して読んでもらう方が早いかも😆」「身に付けておきたい常識ということですね😊」

参考: find、find_by、whereの違い - Qiita

ライブラリとフレームワークの違い


同記事より


つっつきボイス:「ライブラリとフレームワークの違い、これもよく言われているヤツですね☺️: ところで最近のイベントでも似たようなテーマで発表しているのを見た気がしますね」「銀座Railsとかでしょうか?」「どれだったかな〜思い出せん😆」

「この種の議論にはいろんな視点がありますけど、そのイベントで聞いた見解は割と自分にとってもしっくり来たんですよ😋」「ふむふむ」

「と思ったらこの記事で引用されている図↓(引用元: differencebetween.net)にもそれに通じる見解が書いてあった: 2段目のフレームワークの『自分のコードがフレームワークを呼ぶのではなく、フレームワークが自分のコードを呼ぶ』のあたりが自分にもしっくりくる👍」


同記事より

「ライブラリメソッドはユーザーのコードから呼び出すものだし、Railsで言えば、Rails wayに沿ってコードを書けばRailsフレームワークがそのコードを呼び出す: これが自分が持つライブラリとフレームワークのイメージに近いですね☺️」

中間テーブルを疑え


つっつきボイス:「Andy Crollさんの短い記事です」「HABTM(has_and_belongs_to_many)久しぶりに見た😆」「やめとけってよく言われるヤツですね😆」「とっくにdeprecatedと思ってたけど、いつの記事?」「今年出た記事ですね」「2020年にHABTM見るとは思わなかった😆」

# 同記事より
class User < ApplicationRecord
  has_and_belongs_to_many :organisations
end

後で探すと、Rails 6になってもHABTMは一応残ってますね。

現時点のmasterで確認すると「has_and_belongs_to_manyの中間テーブルにカラムを追加することがdeprecated」ということでした。

WARNING: The use of extra attributes on the join table in a has_and_belongs_to_many association is deprecated. If you require this sort of complex behavior on the table that joins two models in a many-to-many relationship, you should use a has_many :through association instead of has_and_belongs_to_many.
github.com/rails/railsより

参考: 仕事のねた: rails3でHABTMが非推奨になってる -- 2011年の記事です


「記事の中身はというと、HABTMよりも、名前に意味のあるモデルでやろうという基本的な話かな☺️」「ふむふむ」「中間テーブルが持つエンティティに意味があるケースは多いんですけど、Railsのhas_many through:がそのまま使えるとも限らないんですよ」「記事にもhas_many through:はHABTMよりもメソッドが少ないってありますね😳」「HABTM使わなくなって長いんでもう思い出せませんけどっ🤣」

GitHub ActionsでRailsとPostgreSQLをセットアップ


つっつきボイス:「チラ見した感じでは結構いい記事っぽい!❤️」「やった!」「こういうテンプレ的なものがあるのはいいですね〜😋: GitHub Actionsやりたい人によさそう👍」「たしかに😋」「CIのコンフィグとか、全部自分で考えて構築するよりも誰かが確立したテンプレでやりたいですし☺️」「翻訳しようかな😋」「完璧かどうか知りませんけど😆、少なくとも記事のとおりにやれば動くコンフィグ書けそうですし」

目次より:

  • 必要なもの
  • 完全なワークフローの例
  • オプション: secretを環境変数として使う
  • GitHub Actionsを使ってみた所見と現状の問題点:
    • .nvmrcや.ruby-versionのサポートがない
    • ged/ruby-pgなどはlibpq-devを自分でapt installしないといけない(デフォルトにすべき)
    • 新バージョンが出たら通知してくれたらいいのに(ボットがプルリク投げてくれたらさらに嬉しい)
    • ワークフローを手動でトリガできない

Shopify流: Railsで速いコードを書く方法

つっつきボイス:「翻訳記事です」「Shopifyはスゴいですよね〜: エンジニア200人ぐらいいるらしいですけど、Railsエンジニアがそんなにいて崩壊しないところとか💪」「マジで😳」

「『クエリキャッシュを信用しすぎない』はたしかに☺️」

「Large Hadron Migrator?」「Shopifyの独自ツールみたいですね☺️」「ハドロンってやっぱり粒子加速器のアレだ: ハドロン、バリオン、メソンとか😆」「へ〜、どうやらLHMは、テーブルをALTERするとロックされるみたいなよくある問題をよしなにうまくやってくれるものみたい」「あ〜以前のウォッチでも話ありましたね」「LHMのThrottlerは、スレーブというかレプリカにそのまま投げると確実に詰まるような巨大データをよしなに絞ってくれるっぽい」「なるほど」


同リポジトリより

参考: 大型ハドロン衝突型加速器 - Wikipedia

「きっと特定のRDBMS用だろうと思ったらやっぱりMySQL用ですね: Shopifyは自分で作って自分で使ってるからいいんですけど、外部の人間としてはこのgemの挙動をきっちり理解しないと怖くて使えない😱」「😆」「データベースのマイグレーションに失敗すると悲惨ですから😇」

「それに最近耳にした噂&うろ覚えレベルでは(おそらく銀座Railsあたり?)、MySQL 8あたりからはALTER TABLEしてもロックしなくなったらしいとか、あとAWS Auroraもいけるらしいとか何とかあるみたいですし」「MySQLもいろいろ変わってきてるんですね☺️」「MySQLのissueとか注意点はいろいろあがってるので、彼らも修正しようと頑張ってますし☺️」

「お、このツールはforkを辿るとSoundCloudのリポジトリになってる: こういうgemを公開しているとは知らなかった」「ホントだ😳: gem作ってるということはどっかでRails使ってるんでしょうね」「でしょうね」

「SoundCloudって?」「およ、このアイコン↑見たことありません?」「Instagramの音楽版みたいなSNSでしたっけ」「そんな感じですね: 音楽ずっとやってたならむしろ詳しいかと思ってましたけど😆」「近年は音楽方面を努めて見ないようにしてるので😅」

その他Rails

つっつきボイス:「この間BPSの社内Slackに貼った記事なんですけど、手元では既に翻訳したので近々公開します」「そうそう、オブジェクト指向トレースの記事😋」「記事で使っているtapping_deviceにグラフ表示を追加する構想もあるそうです❤️」

「Rubyってそもそもこういうデバッグ作業がツラいんですよね😭: 特にRailsみたいに動的にクラスやモジュールをロードするような世界だとキレイなグラフを描くのは難しいですし」「う〜む」「自分たちが書いたコードに絞り込めるならやれると思うので、それができるならいいなと思いますね☺️」

「いわゆるDDDというか、ビジネスロジックをちゃんとオブジェクト指向で開発していれば、こういうツールでのグラフ化はもっとやりやすくなるでしょうけど: Railsフレームワークの動きは見ないようにして、自分たちのロジックだけにフォーカスして呼び出し依存を調べたりとか☺️」「なるほど」


「最近流行りのエントリです😆」「ソニックガーデンの伊藤さん編サイコー😆」「😆」「それにしてもよくこんなにたくさん書けるなって思いますね☺️」「怒涛の勢い🌊」「自分もこのお題で書いてみようかな?😋」

「Rubyのブロックが最初わからなかったとあるのが意外でした」「Rubyのブロックは最初はわからないと思いますよ: あれは結局のところ他の言語で言うlambdaですし」「お〜」「今でこそJavaにもlambdaありますけど昔はありませんでしたし☺️」

参考: Java 8 のイディオム: 完璧なラムダ式がたった 1 行である理由

「Rails 3.1ぐらいで初めてRuby触ったときもeachで回してdoするとか最初意味わかりませんでしたもん😆」「へぇ〜!」「ブロックが引数として渡されるという概念が当時の自分になかったんですよね: PHPならわかったんで最初はPHPの関数渡しみたいなものかな?って思ったり😆」

「ルーティングとRESTも最初わからなかったともありますね」「自分はRESTについては、あのあまりにも有名な論文↓で先に知ってたので😆」「先行する論文があったんですね😳」「ノリとしては『HTTPメソッドを見直そう』という感じで、論文が出た2000年頃ってAjaxが流行りだしたあたり」「なるほど」「そういうのを思い思いにやるんじゃなくて、RESTfulにやるのが大事だよね、という流れでしたね☺️」

参考: Architectural Styles and the Design of Network-based Software Architectures
参考: REST論文からアーキテクチャを進化させる方法論を学ぶ - Qiita


「Javaのようなきれいなアーキテクチャのある世界からRailsを見たらこういう見解になるかもしれませんね☺️: 自分はPHP沼方面から来たんですけど、PHPとかPerlのようなスクリプト言語系で、しかもみんながオレオレフレームワークを作りまくってたような何でもありな世界からRailsに来ると、ジェネレートみたいにスクリプト言語の柔軟性を活かしながら、Java的な固さも取り入れていて、これがRailsなのかな〜って思ったりしましたね😉」「なるほど〜」


前編は以上です。

おたより発掘

バックナンバー(2020年度第1四半期)

週刊Railsウォッチ(20200121後編)RubyKaigi 2020受付開始、RubyGemsとBundlerの今後、ファイル同期ツールMutagenほか

今週の主なニュースソース

ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp Slackなど)です。

Rails公式ニュース


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。