- Ruby / Rails関連
週刊Railsウォッチ(20181009)Rails 6の新機能:WYSIWYGエディタ「Action Text」、Rails 6の青写真スライド、Apache POIはスゴイほか
こんにちは、hachi8833です。休日があると平日が減ってむしろ大変です。
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話です👄
今回は「Railsウォッチ 公開つっつき会 第3回」の日でした。おかげさまで本編・懇親会ともに盛り上がりました🎊🍻。参加いただいた皆さま、ありがとうございます!🙇
つっつきボイス:「(開始前の雑談)Action Text出ましたね」「そうそう、今回はそれがトップです」「え、そんなのが出てた?!😳」「ではぼちぼち始めま〜す🎬」
最初Active Textと書き間違えたりしてました💦。
⚓臨時ニュース: Rails 6で新機能: ブラウザ向けリッチテキストエディタTrixを取り入れた「Action Text」が導入(Rails公式ニュースより)
- 公式: Introducing Action Text for Rails 6 | Riding Rails
- リポジトリ: rails/actiontext: Edit and display rich text in Rails applications
- BasecampのTrix: Trix: A rich text editor for everyday writing
- リポジトリ: basecamp/trix: A rich text editor for everyday writing
先週ぐらいにBasecampがTrixをリリースしたというDHHのツイート↓を見かけたのですが、その時点では様子がよくわからなかったので保留にしていました。TrixはBasecampでは前から使われていたらしく、公開間もないのに★が11000超えです。みんな欲しかったんでしょうね。
Celebrating the big 1.0 of our WYSIWYG editor Trix with a lovely new website by @AdamStddrd. It powers all textareas in Basecamp. And you can have it for free!
Congrats to @javan and @sstephenson for reaching this milestone! https://t.co/uMompjGKkA
— DHH (@dhh) September 26, 2018
既存のブラウザ用リッチテキストエディタのほとんどがIE5.5のcontenteditable
やexecCommand
のAPIを引きずっていたのを、新たにCoffeeScriptで作り直し(コンパイルはBladeを使用)、コードからの制御がうんとやりやすくなったということのようです。
<form …>
<input id="x" type="hidden" name="content">
<trix-editor input="x"></trix-editor>
</form>
つっつきボイス:「BPS社内Slackでも話題になってたヤツ」「どれ、動画↑をポチッと」「15分あるので飛ばし飛ばしで」「(動画を見つつ)scaffoldしてちょろちょろっと何か書いて...おぉ〜〜?!テキスト入力にいきなりデスクトップから画像をドラッグアンドドロップしてるし😋」「これ自力でやろうとすると面倒なヤツ」「DHH、GCPをGCSと言い間違えてたっぽい😆」「はい〜じゃこの辺で🎬」「😆」
同動画10:10より
# 同動画より post.rb
class Post < AppicationRecord
has_rich_text :content
end
<!-- 同動画より _form.html.erb -->
<%= form_with(model: post, local: true) do |form| %>
...
<div class="field">
<%= form.rich_text_area :content %>
</div>
...
<% end %>
<!-- 同動画より show.html.erb -->
...
<%= @post.content %>
...
「ところでこの手のWYSIWYGエディタ機能って使ったことあります?」「あります〜: そのときはWYSIWYGエディタで検索して出てきたものをもう片っ端から試したんですけど、結局どれを使ってもつらかった😭」「これ↓に載ってるCKEditor、自分も使ったな〜」「TinyMCEも」「結局どれもつらいんですよね~」
参考: 商用でも利用できる、イケてるWYSIWYGエディタ7選 2017年版 - ランサーズ(Lancers)エンジニアブログ
「この手の汎用的なWYSIWYGエディタってJavaScriptで書かれているんですけど、どれを使おうと結局アップロードのエンドポイントは自分でサーバー側に用意しないといけないんですよね😅」「それそれ!」「PHPのサンプルコードぐらいはあったりするけど当然そのまま使えるはずがないので、エディタ側の制約に合わせて一生懸命エンドポイントを作り込まないといけないし、UIを日本語化したり不要な機能をオンオフできるようにするconfigを書いたりとか、YouTube動画を埋め込むためにカスタムタグを作ったりとかしようとすると、面倒が無限に続く😇」「froala使ったときとかapplication.jsとかCSSとかをひたすら書きまくったし」「WYSIWYGやった人は誰もがそうなる」
「つまりAction Textがここまで簡単になったのはバックエンドがRailsという前提が置けるからですね」「ちょうどWordPressも今度WYSIWYGをリニューアルするとか言ってるけどあれも同じ」「例のGutenberg↓ですね」
参考: WordPressの新しいエディタGutenberg(グーテンベルク)の長短所について
「Action Textが使えるのはRails 6からか〜」「TrixそのものはRails前提?」「独立してるはずですが、CoffeeScriptで書かれます(コンパイルはBladeで)」「こーひーすくりぷとか〜😅、フロントエンジニアからめっちゃマサカリが飛んできそう⚔️」「私も普段から『CoffeeScript滅べ』って言ってるし」「自分もCoffeeScriptはもういいや」「(Trixのリポジトリを開きながら)var
使ってる↓の見つけた😆」「🤣」「🤣」「CoffeeScript以前にES2015ですらない😆」「🤣」
# bascamp/trixより
var element = document.querySelector("trix-editor")
element.editor // is a Trix.Editor instance
「ともあれTrixはRailsがなくても使えるということね」「だから★が11000超えなのかも」「Rails専用だとここまで★取れないでしょうね」
「まあ、ぺろっと貼るだけで使えるWYSIWYGエディタなんてものはこの世にありませんから😆」「🤣」「ちなみにWordPressのWYSIWYGが出力するHTMLって見たことあります?空の<div>
タグとか、かなり物凄いのが出てくる🤯」「今度はWordPressにほこ先が😆」
「ついでにお見せすると、TechRachoのWordPressにはMarkdownプラグインを導入しています↓」「おぉ〜😊」「とは言え一部のスタイルでまだHTMLタグ必要ですが」「Markdownならローカルのエディタで書いてさっと貼り付けられるので(画像はしょうがないけど)」
「やっぱりMarkdownかなっ❤️」「プログラミングとかに興味のない人に普及しなさそうだけど😢」「WYSIWYGももう少し秩序のあるコードが書けるものだったらいいんですけどね〜ほんに☺️」
「果たしてAction Textはどうなるかな?」「フロント勢から『これだからRailsは』が飛んでくる予感が少々😆」「画像アップロードなんかが入ってくると設計的にフロントエンドとバックエンドのどっちの責務なのかが怪しくなってきそうで、そこが難しいっすね🤔: たとえば画像にカスタムタグのボタンを付けたりすると今度はサーバー側でもちょっとタグに手を加えてから保存するとか、やりたくなってくるわけですよ」「うんうん」
⚓Rails: 先週の改修(Rails公式ニュースより)
今回の公式情報が豊作だったので自分でコミットログを掘り起こさずに済みました。
⚓credentialを複数環境でサポート
# 同PRより
rails credentials:edit --environment staging
現在の環境で特定のcredentialファイルが存在する場合はそれを優先する。
これによってproduction環境ではENV["RAILS_MASTER_KEY"]
からマスターキーで取得したconfig/credentials/production.yml.encを最初にチェックし、またはconfig/credentials/production.keyを読み込む。
デフォルトの振る舞いはconfig.credentials.content_pathかconfig.credentials.key_pathで変更可能
credentials
APIドキュメントより
# railties/lib/rails/application.rb#L445
def credentials
- @credentials ||= encrypted("config/credentials.yml.enc")
+ @credentials ||= encrypted(config.credentials.content_path, key_path: config.credentials.key_path)
end
つっつきボイス:「--environment staging
を指定できるようになったと」「ありそうでなかった」「credentialを環境で切り替えたいことがどのぐらいあるのかはさておいて😆」
「このcredentialって何でしたっけ?🤔」「そこに書かれているconfig/credentials.yml.enc
がcredentialファイルなんですが、鍵を暗号化してこのファイルに保存することでGitとかのリポジトリに登録できるようにする機能です🗝」「これで鍵変更の履歴も追えるようになる」
「サーバーのデータベースパスワードなどは、本来なら履歴を追えるGitリポジトリのような秘密を保てない場所に登録すべきではなくて、デプロイスクリプトとかAWSのKMSから引っ張ってくるべきなんですが、こういうのって地味に大変じゃないですか: 特にHerokuを使っている場合、サーバー側で任意のスクリプトを実行しようとするときに面倒なので、リポジトリに登録できて安全かつ楽に使えるようにしようというのがcredential機能ですね」「なるほど〜そういうノリでしたか😊」
パスワードをうっかりGitリポジトリに登録してしまい、後から消そうとしても以後のハッシュがごっそり変わってしまうのでチーム全員に迷惑がかかるというのはよくありますね。
参考: GitHub にパスワードとかセンシティブなファイルを push してしまったときの対処法 - Qiita
「鍵を環境変数に入れる手ももちろんあるんですけど、環境変数の容量も無限ではないんですよね: その点credentialならyamlに保存するのでサイズを気にしないで済むというメリットもあります😊」「その代り、このファイルは直接編集できない」「vimとかで開いたらあかんし、そもそも読めないという」「rails credentials:edit
コマンドで編集することで指定のエディタが開いて、暗号化と復号を自動でやってくれる☺️」「なるほど、ちゃんとこれを使いましょうということですね☺️」
「個人的にはそれほど好きな機能ではないけど、この機能が欲しい人がいるのはワカル」「確かRails 5.2で入った機能でしたね」
「なお、credentialの肝心のマスターキーが流出したらその瞬間に全滅する💥」「🌋」「credentialを使うと、たとえばチーム開発でメンバーが退職したら即マスターキーを変更しないといけなくなるので、そこが自分にはちょっと美しくないかな😅」「そういえば以前のウォッチでもその話になりましたね」「マスターキーをKMSに保存する手もありますけど」
⚓Action Cableチャンネルの単体テストをサポート
ActionCable::Channel::TestCase
が新たに導入されます。
# actioncable/lib/action_cable/channel/test_case.rb#L21
+ module ChannelStub
+ def confirmed?
+ subscription_confirmation_sent?
+ end
+ def rejected?
+ subscription_rejected?
+ end
+ def stream_from(broadcasting, *)
+ streams << broadcasting
+ end
+ def stop_all_streams
+ @_streams = []
+ end
+ def streams
+ @_streams ||= []
+ end
+ # Make periodic timers no-op
+ def start_periodic_timers; end
+ alias stop_periodic_timers start_periodic_timers
+ end
つっつきボイス:「この間も似たようなヘルパーが導入されてなかったっけ?」「私もそんな気がしてたので後で調べます↓」
以前のウォッチの「ActionCableのテストに便利なアダプタを追加」だったようです。
「ActionCableを手動でデバッグするのは絶対ヤダ😝」「ActionCableって使うことあります?」「ちょろっと作りたいときにはActionCableは便利だと思いますね: 何か処理が終わったときに右上あたりにピコっと通知を表示したいなんてことはよくあるんですが、そういうシンプルな通知機能を作るときなんかにいい」「そのためにワーカースレッドを1つ使うことになりますが😆、管理画面ぐらいだったらユーザー数が少ないので問題なくやれる」
⚓サポート外のストアにあるキャッシュキーを誤って使わないよう修正
# activerecord/lib/active_record/railtie.rb#L91
+ initializer "Check for cache versioning support" do
+ config.after_initialize do |app|
+ ActiveSupport.on_load(:active_record) do
+ if app.config.active_record.cache_versioning && Rails.cache
+ unless Rails.cache.class.try(:supports_cache_versioning?)
+ raise <<-end_error
+You're using a cache store that doesn't support native cache versioning.
+Your best option is to upgrade to a newer version of #{Rails.cache.class}
+that supports cache versioning (#{Rails.cache.class}.supports_cache_versioning? #=> true).
+ Next best, switch to a different cache store that does support cache versioning:
+https://guides.rubyonrails.org/caching_with_rails.html#cache-stores.
+ To keep using the current cache store, you can turn off cache versioning entirely:
+ config.active_record.cache_versioning = false
+end_error
+ end
+ end
+ end
+ end
+ end
つっつきボイス:「リサイクラブル!」「プルリク投げたschneemsさんは、TechRachoでも何度か翻訳記事出しています」「この設定↓が追加されるそうです」「しれっとマージされたっぽいけど、もしやバグ?😆」
config.active_record.cache_versioning = true
「あー、キャッシュエンジンがバージョニングに対応しているかどうかで挙動を変えないといけなかったってことか」「なるほど〜」「ファイルストアなのかmemcacheストアなのかとかmemoryストアなのかnullストアなのかで変えると」「それぞれにファイルが分かれてダックタイピングしてる」
# 同PRより
# activesupport/lib/active_support/cache/memory_store.rb
# Advertise cache versioning support.
def self.supports_cache_versioning?
true
end
「フレームワークが個別のキャッシュエンジンにどこまで対応するかというのはあるけど、Railsは割と積極的に対応する方ですね: MySQLとPostgreSQLとかも既に独自のものが入ってきてるぐらいだし、キャッシュもそういう感じで独自のものが入ってくると」「😃」
⚓モデル生成に--migrations-paths
オプションを追加
# 同PRより
bin/rails g model Room capacity:integer --migrations-paths=db/kingston_migrate
invoke active_record
create db/kingston_migrate/20180830151055_create_rooms.rb
scaffoldとマイグレーションどちらでも使えるようです。
--migrations-paths
は8月末に#33760で追加されたばかりなので、どちらも新しいですね。
他にも--database
オプションが#34021で追加されました。
# activerecord/lib/rails/generators/active_record/migration.rb#L26
def db_migrate_path
- if migrations_paths = options[:migrations_paths]
- migrations_paths
- elsif defined?(Rails.application) && Rails.application
- Rails.application.config.paths["db/migrate"].to_ary.first
+ if defined?(Rails.application) && Rails.application
+ configured_migrate_path || default_migrate_path
else
"db/migrate"
end
end
+ def default_migrate_path
+ Rails.application.config.paths["db/migrate"].to_ary.first
+ end
+ def configured_migrate_path
+ return unless database = options[:database]
+ config = ActiveRecord::Base.configurations.configs_for(
+ env_name: Rails.env,
+ spec_name: database,
+ )
+ config&.migrations_paths
+ end
つっつきボイス:「マイグレーションパスを指定って...デフォルトでやろうよみんな😅」「db/migrate/
以外にも置けるんですか」「デフォルトのマイグレーションフォルダ以外のものを使いたいときってあるのかな?」「どうしてもdb/migrate
にだけは置きたくない人用だったりなんかしてね😆」
「何でそんな闇を作るんですか🤣」「マジでどんな使いみちが...?🤔」「db/migrate
の下でフォルダを分けたいとか?」「うーん、あるとすれば、たとえばRailsアプリを複数の顧客に納品していて、顧客ごとに違うdb:migrate
をやりたい、とか?」「あるいは、experimental用のマイグレーションパスを用意しておいて、masterにはexperimentalなコードをどんどんマージするけど、そのパスでマイグレーションしないとexperimentalなコードが発動しない、とか?」「うーん」「使い方間違ってる気がするけどな〜😅」
「下の方を見ると、マルチDBのdatabase.ymlに使えるんじゃ?みたいなコメントがありますね」「ははぁ、今のRailsは1マイグレーションで1つのDBにしか対応していないので、--db
と組み合わせて使えば複数データベースのマイグレーションができる、みたいな感じかな?その場合マイグレーションパスを変えないと破綻するし」「あ、確かに〜」「こんなことしないといけない状況って...とっほっほ〜😭」「自分ならridgepoleとか使うなっ😎」「ridgepole、以前のウォッチでも扱いましたね」
「おそらくですが、最近のRailsがマルチDBをサポートしたことの一環なんじゃないかな?」「あ、それならわかる😋」「マルチDBをサポートするならマイグレーションもマルチDBを使えないとね、ってことなのかも: 使うかどうかはともかく」「もうちょいスマートなやり方はありそうなので、Rails 6が出るまでにまた変わるかも😊」
⚓productionでのAR属性の定義をlazyからeagerに変更
# activerecord/lib/active_record/railtie.rb#L140
+ initializer "active_record.define_attribute_methods" do |app|
+ config.after_initialize do
+ ActiveSupport.on_load(:active_record) do
+ descendants.each(&:define_attribute_methods) if app.config.eager_load
+ end
+ end
+ end
#29559↓でコントローラのアクションをeagerに定義したのと同じような要領でやったそうです。
# actionpack/lib/action_controller/railtie.rb#L80
initializer "action_controller.eager_load_actions" do
ActiveSupport.on_load(:after_initialize) do
ActionController::Metal.descendants.each(&:action_methods) if config.eager_load
end
end
つっつきボイス:「バグ修正でしょうか?」「パフォーマンス改善かなという気もするけど、productionモードなのに想定どおりじゃなかったからバグだったのかも」
「それにしてもeagerな処理になってるかどうかをどうやってテストするんだろうか?🤔」「テストコードを見るとassert_includes Post.instance_methods, :title
でeagerかどうかがわかるってことなのかな...」「いいのかそれで😆」「なぜこれでテストできているのかはわからないけどっ🤣Rubyの挙動的にそうなのかもしれない」
⚓.psqlrcファイルを無視する-X
オプションを追加
- PR: Ignore psqlrc files when executing psql commands by dark-panda · Pull Request #33906 · rails/rails
# activejob/test/support/integration/adapters/queue_classic.rb#L3
def start_workers
uri = URI.parse(ENV["QC_DATABASE_URL"])
user = uri.user || ENV["USER"]
pass = uri.password
db = uri.path[1..-1]
- %x{#{"PGPASSWORD=\"#{pass}\"" if pass} psql -c 'drop database if exists "#{db}"' -U #{user} -t template1}
- %x{#{"PGPASSWORD=\"#{pass}\"" if pass} psql -c 'create database "#{db}"' -U #{user} -t template1}
+ %x{#{"PGPASSWORD=\"#{pass}\"" if pass} psql -X -c 'drop database if exists "#{db}"' -U #{user} -t template1}
+ %x{#{"PGPASSWORD=\"#{pass}\"" if pass} psql -X -c 'create database "#{db}"' -U #{user} -t template1}
QC::Setup.create
QC.default_conn_adapter.disconnect
QC.default_conn_adapter = nil
@pid = fork do
worker = QC::Worker.new(q_name: "integration_tests")
worker.start
end
rescue PG::ConnectionBad
puts "Cannot run integration tests for queue_classic. To be able to run integration tests for queue_classic you need to install and start postgresql.\n"
exit
end
structure.sqlファイルも同様に-X
で無視されます(#34001)。
つっつきボイス:「database.ymlと.psqlrcの設定がかぶるのをどうにかする感じ?」「そのようです」「どれ、psql --help
してみると...むむ、自分のマシンには今psqlが入ってない、なぜならDockerでやってるから😅」「こちらで見ると-X, --no-psqlrc do not read startup file (~/.psqlrc)
となってました」「じゃやっぱりpsqlのオプションだ🎯: .psqlrcに起動時のシグネチャ表示設定とかあるとゴミが入って容易にバグるし」
⚓ActiveJobのテストで実行ジョブの引数のサブセットをチェックできるようになった
# activejob/lib/active_job/test_helper.rb#L362
def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil)
expected = { job: job, args: args, at: at, queue: queue }.compact
expected_args = prepare_args_for_assertion(expected)
if block_given?
original_enqueued_jobs_count = enqueued_jobs.count
yield
jobs = enqueued_jobs.drop(original_enqueued_jobs_count)
else
jobs = enqueued_jobs
end
matching_job = jobs.find do |enqueued_job|
deserialized_job = deserialize_args_for_assertion(enqueued_job)
- expected_args.all? { |key, value| value == deserialized_job[key] }
+ expected_args.all? do |key, value|
+ if value.respond_to?(:call)
+ value.call(deserialized_job[key])
+ else
+ value == deserialized_job[key]
+ end
+ end
end
assert matching_job, "No enqueued job found with #{expected}"
instantiate_job(matching_job)
end
つっつきボイス:「job_args
↓で引数を取れるようになったとかそういう感じかな?」「上のif value.respond_to?(:call)
↑があるからLambdaを取って、それをハッシュ的に使うようになったっぽい: ActiveJobのデータのとり方に関係あるんだと思いますが」「ちょっと理解を超越気味🤯」
# activejob/test/cases/test_helper_test.rb#L
def test_assert_performed_with_selective_args_fails
args = ->(job_args) do
false
end
assert_raise ActiveSupport::TestCase::Assertion do
assert_performed_with(job: MultipleKwargsJob, args: args) do
MultipleKwargsJob.perform_later(argument2: { b: 2, a: 1 }, argument1: 1)
end
end
end
⚓Rails
⚓スライド:「The Future of Rails 6 -- Scalable by Default」(Rails公式ニュースより)
今年4月にピッツバーグで開催されたRailsConf 2018で発表されたスライドです。上のAction Textのプレスリリースにありました。
つっつきボイス:「Rails 6の青写真がだいたいここで説明されているようです: これまでウォッチでコミットを追いかけてきたこともあって、実際この通りに進んでいるものをいくつも見かけました」「(スライドをめくりながら)Rails 6ではスレッドベースのワーカーがデフォルトになるとか、マルチスレッドのテストがデフォルトになるとか」「ほぉ〜😳」「ここにもマルチデータベースやる宣言が出ているし、スケーラビリティがテーマになっている感」「database.ymlも書式が変わる↓」
# 従来
production:
<<: *default
database: db_production
production_animals:
<<: *default
database: db_animals_production
# 今後: 3-tier database.yml
production:
primary:
<<: *default
database: db_production
animals:
<<: *default
database: db_animals_production
「さっきの#33994のマイグレーションパスの話もある」「で、こんなふうにモデルでコネクションを指定できる↓: おそらくApplicationModel的なところでこれを指定すれば個別のモデルにはいちいち書かなくていいはず」「マルチデータベースなら名前空間切るっしょ普通😎」
# app/model/animals_base.rb
class AnimalsBase < ActiveRecord::Base
self.abstract_class = true
establish_connection :animals
end
「で、マイグレーションでもestablish_connection
を指定できる↓: これを使うのがいいのか、switchpointみたいに実績のあるgemにするのがいいかというのはあるにしても」
path = Rails.root.to_s = "/db/animals_migrate"
desc "Migrate the cluster db"
task migrate: :environment do
ActiveRecord::Migrator.migration_path = path
ActiveRecord::Base.establish_connection(:animals)
ActiveRecord::Taks::DatabaseTasks.migrate
db_namespace["db:schema:dump"].invoke
end
「ちなみにswitch_pointはマスター/スレーブ形式の割とメジャーなマルチDBのgemですね: 以下のuse_switch_point
が今のestablish_connection
に相当する感じです」「ほほぉ〜👀」「switch_pointもこの間のウォッチで(略」
# switch_point READMEより
class Article < ActiveRecord::Base
use_switch_point :blog
end
⚓active_storage_validations gem(RubyFlowより)
# 同リポジトリより
class User < ApplicationRecord
has_one_attached :avatar
has_many_attached :photos
validates :name, presence: true
validates :avatar, attached: true, content_type: 'image/png'
validates :photos, attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg']
end
以前のウォッチで取り上げたlog_analyzerと同じ作者です。
つっつきボイス:「こういうバリデーターってRails標準にもありそうだけど?」「自分が欲しくて作ったのかも: 入れ違いでRailsにも同じのができるか既にあるかもしれないので慌てて入れなくてもいいのかな🤔」「content_type
はセキュリティ問題につながることが多いから、こういうバリデーターは欲しい😍」
⚓GitHubがRailsを3.2->5.2.1にアップグレード
先週追加で貼った記事です。
つっつきボイス:「この記事読んでびっくりした~🤓」「3.0からかなと思ったら3.2だったという」「記事はあっさり目ですが苦労が偲ばれます」「もちろん何年もかけて準備してたでしょうね👍」
「何かこんなif
文↓使ってるんですけど😅」「これも時間をかけて少しずつデプロイしてるからでしょうね: バージョンが変わっても同じコードで動くようにしておかないといけないだろうし、まあしょうがない😆」「きっとユーザーも一斉に切り替わるんじゃなくて、たとえば1/10のユーザーを人柱的に新しいバージョンに移して、様子を見ながらユーザーを少しずつ移すなんてこともしてるでしょうね」
# 同記事より
if GitHub.rails_3_2?
## 3.2 code (i.e. production a year and a half ago)
elsif GitHub.rails_4_2?
# 4.2 code
else
# all 5.0+ future code, ensuring we never accidentally
# fall back into an old version going forward
end
「記事最後の教訓にも『勢いが大事』ってありますね🏄♀️」「だらだらアップグレードしていると永遠に終わらないし、その間にRailsのバージョンがまた1つ先に進んじゃったりするし😆」「😆」
⚓remote_bootstrap_modal: 外部リンクをBootstrapのモーダルダイアログに読み込むgem(RubyFlowより)
- リポジトリ: glaucocustodio/remote_bootstrap_modal
- 元記事: 5 Steps to Add Remote Modals to Your Rails App – JTWay
Railsエンジン型式だそうです。
- アプリにBootstrapをインストールしておく
- Gemfileにこのgemを追加
- アプリのレイアウトファイルに
<div id="modal-holder"></div>
を追加(ここでモーダルがレンダリングされる) - app/assets/javascripts/application.jsでjQueryよりも後に
//= require remote_bootstrap_modal
を追加 respond_to
に応答させるフォーマットを設定(:html
や:json
など)- コントローラで
respond_modal_with
に必要な引数を渡して呼び出す - モーダルに読み込みたいリンクに
data: { modal: true }
を渡す(例:link_to 'Customers', customers_path, class: 'btn btn-default', data: { modal: true }
)
つっつきボイス:「↓こういうことができるみたいです」「data: { modal: true }
とすると指定したURLがこうやってモーダルの中でさくっと開くということね😋最初の方しか見てないけどやりたいことはだいたいワカル」
「モーダル、使うかなぁ?」「たとえば単語の意味をWikipediaで引いてモーダルで表示したいなんてときに使えるかも: 実はこういうgemってあると地味に便利😍」「おぉ〜😋」
⚓Railsでjoinするときの生SQLを見つつ最適化する(Hacklinesより)
つっつきボイス:「これに近い最適化はたまにやるかな: 割とよくあるヤツ」「最終的にexec_query
してるし😆: まあ生SQLで書くと結局こうなるし」
# 同記事より
# Find Payment RMH
rmh_raw_query = "SELECT ri.name, ri.amount, inv.id FROM remittances ri LEFT JOIN invoices inv ON LOWER(ri.name) = LOWER(inv.number) WHERE ri.payment_id = #{payment.id} ORDER BY remittance_sequence_number ASC"
rmh_records = ActiveRecord::Base.connection.exec_query(rmh_raw_query).rows
payment_rmh = rmh_records.map{|rme| {name: rme[0], amount: rme[1].to_f.round(2),invoice_id: rme[2]}}
⚓Dockerコンテナを複数プロジェクトで共有する(Hacklinesより)
つっつきボイス:「お、まるで今日自分が社内で発表した内容みたいだ」「今日たまたま見つけた記事なんですが、怖いくらいシンクロニシティを感じてしまいました」「複数のdocker-compose.ymlがあってそれらを連携させるという、まさに今日話した内容😆: そうそう、networks:
にはこうやってexternal:
オプション↓を付けないと参照できない」
# project_one/docker-compose.yml
version: '3.2'
networks:
default:
external:
name: my_net
services:
# ...
「今日話したときは、これ以外にconfigファイルを生成するときにenvsubstを使わないと2つのdocker-compose間での環境変数を同期できなくてつらかった話なんかもしたナ」「そうでしたね😋」
「docker-compose使います?」「大好きですね〜😋」「docker-composeを複数使い始めると、なぜKubernetesが必要になるのかがとってもよくわかってきますよ😭」「自分は複数使ってたっけか...?あ、1つあった気がする: 確かにつらいです😭」「Kubernetesで言うpodが、1つのdocker-composeに相当する感じで、Kubernetesならpod間の連携も定義できる💪」「なるほど〜」「こういう連携をやり始めるあたりが、いわゆるオーケストレーションツールが必要になってくる境目でしょうね: 個人的にはしばらくdocker-composeでもう少し頑張りたい気はするけど」「まだKubernetesに魂は売りたくないです〜🤣」「少なくともKubernetesクラスタを自前で管理するのは絶対やりたくない🤣」「🤣」
参考: Pods - Kubernetes
参考: オーケストレーション (コンピュータ) - Wikipedia
⚓Ransackパラメータをsearch_form_for
なしで作成する(Hacklinesより)
# 同記事より
# in index.html.erb
<%= search_form_for @q do |f| %>
# Search if the name field contains...
<%= f.label :name_cont %>
<%= f.search_field :name_cont %>
<%= f.submit %>
<% end %>
つっつきボイス:「あぁこのぐらいなら全然大した複雑さじゃないし: もっと極まったのがいくらでもあるし😎」「😆」「何か複雑なサンプルはと...これでも全然やさしい方だし↓: Ransackの本当の地獄はorとandが出てきてからでしょう、やっぱ💀」「😆」「😆」「そういえば以前のウォッチでも教わりました」「orやandが出てくるとJSONがネストし始めるので、JSONを自分で組み立てる気がなくなる感がヤバい😭」
参考: Complex Object Searching in Rails with Ransack | Lewis’ Blag
# 参考記事より
class Ticket < ActiveRecord::Base
belongs_to :person
def self.search(query = nil)
if query
params = {
full_name_cont: query,
subject_cont: query,
id_eq: query
}
end
ransack(params).result(distinct: true)
end
end
週刊Railsウォッチ(20180702)Ruby 2.2メンテ正式終了、Ransackがつらくなるとき、書籍『Domain-Driven Rails』、GitHubの高可用MySQLほか
⚓その他Rails
流しのRSpec講師業やりたいな〜。リモートで画面共有しながら、お手持ちのRailsアプリにテストを追加していく方法を教えます!みたいなの。独学ではマスターしづらいfeature/system specなんかは人に教えてもらうのが一番速いと思うんだよねー。と、RSpecで困っている人を見かけるたびに思ってしまう😅
— Junichi Ito (伊藤淳一) (@jnchito) October 3, 2018
つっつきボイス:「このツイート↑が反響を呼んでました」「この間もそんな話になりましたけど、RSpecの書き方って最初に誰かが『これです!』って教えてくれないと本当に迷う😅」「そういえばmizchiさんがこの間出した良記事があるんですけど」「お、その記事この後に貼ってあります💪」「その記事にもあったように、新しいフレームワークなどが出たときに最初の時点できれいな雛形を書いてくれる人がいると、後の人はそれを追いかけるだけでよくなるのでとってもありがたい❤️」「最初が肝心」
参考: Everyday Rails - RSpecによるRailsテスト入門 Aaron Sumner 著 et al. [Leanpub PDF/iPad/Kindle]
参考: 【英語論文TIPS】意外に知らないet al.
の書き方、読み方 | 英語猿
「et al.?」「上のEveryday Railsのリンクタイトルにあって気になったので: エトセトラ(etc.)のラテン語版みたいなやつだそうです」「ああ確かに論文ではよく見かけますね😋: ちょいとカッコつけてる感😆」「漢文の熟語みたいな感じで😆」
⚓Ruby trunkより
⚓提案: 配列に共通集合があるかどうかをチェックするArray#intersect?
つっつきボイス:「はてな付きのArray#intersect?
だそうです」「ああ、(a1 & a2).any?
のショートハンドね」「元々#intersect?
ってなかったっけ?」「Set
クラスの#intersect?
はあるようなので、それのArray
版が欲しいということみたい」「そうそう、Set
なら&
でできるんだった」
参考: instance method Set#intersect? (Ruby 2.5.0)
⚓日本の新元号のUnicode合字どうするよ?
つっつきボイス:「martin先生からの㍽
/㍼
/㍻
の次をRubyではどうしようかという問いかけです」「次の年号っていつ決まるんでしたっけ?」「改元の1か月前だった気がする」「マジで!😰」
参考: 新元号公表、改元1カ月前に システム改修対応促す :日本経済新聞
「コードポイントに空きが1個だけあったような気がするけどどうだったかな...」「Macの文字パレットで見るとこんなんなってますけど↓」「くわっ😱」「空きがあるっちゃあるけど、㍻
の前後に半端に空きがあるし」「今後どうする気なんだろう😅」「まあ空きさえあれば実装はできますけどね」「コメントでnaruseさんが面白がってるのは、きっと開き直ってる😆」「『今後の展開が楽しみです』的な😆」
「元号が決まったら、例のwareki gemが即対応するだろうな」「wareki?そんなものがあったんですか😳」「皇紀も含めて日本の昔の元号もやたら充実してます↓」「何これ〜🤣」「漢数字も対応してます💪」「『作者は暦の専門家ではまったくありません』という一文が😆」「こんなの使うところあるんですか?」「特に官公庁は公式文書が元号ベースなので、普通に業務アプリでよく使われてますよ😋」
- リポジトリ: sugi/wareki
参考: 神武天皇即位紀元 - Wikipedia
# warekiリポジトリより
# 和暦のパース (標準 Date インスタンス)
Date.parse("㍻一〇年 肆月 晦日") # => #<Date: 1998-04-30 ...
Date.parse("安政七年 弥生") # => #<Date: 1860-03-22 ...
Date.parse("元仁元年閏七月朔日") # => #<Date: 1224-08-17 ...
Date.parse("萬延三年 5月 廿一日") # => #<Date: 1862-06-18 ...
Date.parse("皇紀二千皕卌年") # => #<Date: 1580-01-17 ...
Date.parse("正嘉元年 うるう3月 12日") # => #<Date: 1257-04-27 ...
# Wareki::Date を直接扱う場合
Date.today.to_wareki_date # => Wareki::Date インスタンス
Wareki::Date.parse("正嘉元年 うるう3月 12日") # => Wareki::Date インスタンス
Wareki::Date.new("明治", 8, 2, 1).to_date # => 標準 Date インスタンス 1875-02-01
「そういえば省庁が順次西暦に切り替えると発表してましたね↓」「やるならぜひ一律でやって欲しい😅」
参考: 省庁データ、西暦に一本化=証明書など元号継続-政府:時事ドットコム
⚓Ruby
Railsのエントリが多かったので今回は控えめです。
⚓JRubyに移行する理由(Hacklinesより)
つっつきボイス:「JRubyのノウハウを持っている人がいるならやってもいいけど」「JRubyを使う理由というと、Javaを愛しているからでなければ、後はJavaのライブラリを使いたい場合かな」「それはありますね」「私も最初に触ったRailsはJRubyで動いてました☕️」
「Javaのライブラリで使いたいものと言えば、やっぱりApache POIでしょう↓」「POI?!」「丸めてポイ?」
「POIは信じられないほどよくできていて、世の中にあるExcelを操作できるJavaのライブラリとして最も優れているのがこれ」「知らなかった〜!😳」「POIはJavaの世界ではもう必須😎」「POIなら、人間にしか作れなさそうな神Excelですらグラフなんかも含めて作れるし」「マジで!?」「RailsとかでExcelを扱うgemは他にもいろいろありますけど、画像貼ったりグラフを作ったり、あとマクロも入れられるんだったかな?」「画像は実装したことある
」「しかも画像の位置調整や印刷のサイズ合わせまでできるので、Excelを印刷フォーマットと思っている人の要求にも応えられるほど再現性が高い」「言葉が出てこない...😳」
「POIってExcelの外部仕様を元に作ったんでしょうか?」「何でここまで作り込まれているのかは謎: こういうのが欲しい人が作ったんでしょうね」「RubyからJava経由でPOIを呼び出すこともできるけど、それだと遅いので、そういう人がJRubyを使いたいんじゃないかな🤔: 個人的には他にJRubyを使う理由が思いつかないけどっ😆」「POIはSIな人ならきっと知ってる😆」「とにかく信頼性というか実績が凄い: セル結合されているファイルとか、隠しワークシートなんかを正しく読めると確信できるのは、たぶん他にはない」「パスワードロックなんかも対応できそう」「Encryptionサポートがあるからできますね」「バイナリのExcelでも扱える」「えぇ〜!😳」「何しろ歴史が長いから(最初のバージョンが出たのは2001年)、XLSXじゃなくても扱える」「Excel 97以降が扱えるんですか!」「Excelより先にOSの期限が切れそう😅: Excel 97が動くWindowsって今あるんだろうか?」
「個人的には使わずに済めばそれに越したことはないけど😆、いざというときの最終手段としてPOIは知っておきたい」「いいこと聞いた😋」「きりがないので次行きましょう〜」
⚓あなたがたぶん知らない5つのRuby技(Hacklinesより)
つっつきボイス:「このHash.new
にブロックで渡すやつ↓、あまり使ったことないけど、キーと値を入れ替えるときか何かで使った気がする: まあこういうコードは正直書いて欲しくないけど😆」
# 同記事より
h = Hash.new { |h, k| h[k] = {} }
h[:layer_1] # => {}
h[:layer_1][:layer_2] # => nil
「ああヒアドキュメントにメソッドチェインするヤツか↓: <<-SQL.gsub("\n", ' ').squish
みたいな書き方ができる」「え、ここにメソッドチェインするの?😳」「squish
はRailsのメソッドか」
# 同記事より
sql = <<-SQL.gsub("\n", ' ').squish
SELECT MIN(u.popularity)
FROM users u
WHERE
u.created_at <= #{Time.now} AND u.created_at >= #{Time.now - 7.days}
SQL
puts sql
参考: Active_supportのString#squishで邪魔な改行文字や空白を綺麗にする - Bye Bye Moore
「ちなみにですが、ヒアドキュメントはあのRubyMineですらシンタックスハイライトがうまくいかなかったりします」「難易度高そう😭」
「最後のは単項演算子のオーバーライド↓はやって欲しくないヤツ」「True
なんてクラス、Rubyにありましたっけ?」「あ、true.class
するとTrueClass
が出てくるから独自クラスか」
# 同記事より
class True
def -@
false
end
def +@
true
end
end
t = True.new
p -t
p +t
「まあRubyの隠し機能なんて、『Ruby隠し機能カルタ』なんてのが作れるぐらいいくらでもありますから😆」「😆」
⚓GitLabコントリビュータにインタビュー(Hacklinesより)
つっつきボイス:「GitLabのWeb IDEが好きだそうです」「Full stack developer!」「強い😆」「そういえばGitLabのコミッターに日本人が1人いた気がする」
⚓クラウド/コンテナ/インフラ/Linux/Serverless
⚓オンラインプロジェクト管理
つっつきボイス:「Backlogは最近BPS社内でも一部使われ始めてて、機能がシンプルでわかりやすい分、細かなことはできなかったりもする」「ところでBacklog使ってます?」「この間使いにくいって別のツールに移りました😝」「お、そうでした?」「そういう人はどういうツールを使ってます?Jiraとか?」「Asanaです」
「プロジェクト管理ツールもさまざまですけど、個人的には機能が少ないものが好き❤️」「GitHubがこれまで日本語化してこなかったので、日本のそうしたシェアをBacklogがかなり取っているらしいと聞きました」「Backlogはシェア大きくて、官公庁の仕事でよく使われています: おそらくポイントは日本語が100%とおって、日本語サポートがあって、あと円で決済できること」「それ重要!」「Redmineだと難しいと思う人もいそうですね」「Redmineは細かく設定できる分複雑なので、サーバーのおもりをする人も必要🤔: Redmineはチケット職人がいると運営がとてもスムーズだし(いないとつらいけど)、秩序立てて管理することを徹底できればとてもいい」
「BacklogはMarkdownに対応しているのがとりあえずありがたい(Redmineはアドオンが必要)」「Backlogは、メンバーに非エンジニアがいる比較的小さな案件で導入しやすいですね😋: BacklogにはGitのリポジトリ機能もあるけど、エンジニアには物足りないかもしれない」
「こういうツールは好みや案件との相性などもあるので一概には言えませんが、Backlogはその中では割といい線行っていると個人的には思います😋」
⚓SQL
⚓sqlfmt: 独断に基づくSQLフォーマッタ(DB Weeklyより)
つっつきボイス:「↓こうやって縦を揃えたい派っぽい」「あーなるほど👀」「書籍に印刷されるSQLにこういうスタイル多いですよね」「気持ちはわかるけど😆」
「まあたとえばWHERE
とAND
をどういうスタイルで配置する人が多いのかなというのはちょっと気になるところかも: AND
の後で改行する人と、AND
を次の行の頭に書く人とか」「AND
を行の頭に書くと他のSELECT
やINSERT
と同じところに並ぶのがいや、という意見もありそうだし」「ありそう〜」
⚓JavaScript
⚓mizchiさんの「TypeScript入門以前ガイド」
つっつきボイス:「さっきもお話に出たmizchiさんのブログです」「そうそう、これはいい記事😍: 上から順に読んでいけばJavaScriptの大きな流れが押さえられるようになっている」「ミジンコから人間へ進化する過程というか😆」「最後の方でちょっと力尽きた感があるのがまた親しみが持てるし😆」「普段からTypeScript書いている人にはだいたい当たり前の話ですが、初めてTypeScriptを書く人やES2015をちゃんと書いたことのない人にはうってつけの力作❤️」
⚓CSS/HTML/フロントエンド/テスト
⚓WordCamp: WordPressの巨大コミュニティによるイベント
イベントは既に終了していますが。
WordPressコミュニティはRubyコミュニティの数倍程度の規模で、かつ集まっている方々のWebデザインの水準が非常に高いと小耳に挟みました。
つっつきボイス:「WordPressのコミュニティは知らない世界」「デザイナーがたくさん集まっていて水準も高いらしいです」「あとSEO関係者も😆」「WordPressとパフォーマンスに関するスピーチ↓もある」「KUSANAGIみたいな高速WordPressホスティングサービスがあるぐらいなので、WordPressのパフォーマンスへの関心は高いと思う: 自分もWordPress高速に動かしたいし🚅」「TechRachoもこういうところに置けたらいいなと思ったりします😃」「今のTechRachoは?」「自前サーバーです」
「話は少し違いますけど、私たちのところではLOLIPOP!を使うことがありますね」「え、そのレンタルサーバー知らなかった💦」「昔からありますよ?」「普段AWSとさくらぐらいしか耳にしてなかった...😅」
⚓AsciiDoc: パブリッシングを意識したマークアップ言語
- サイト: AsciiDoc Home Page
拡張方法が仕様で定められていて、Markdownよりもレイアウトを細かく記述できるようです。Markdownユーザー向けというより、XMLを捨てたい人向け?
参考: AsciiDoc - Wikipedia
参考: AsciiDoc入門 - Qiita
つっつきボイス:「日本の企業ユーザーが多いらしいです」「へぇ、こういうポストMarkdown的なドキュメントエンジンだとSphinx↓の方が有名かと思ってた」「お、知りませんでした💦」
「Sphinxは歴史も長いし、LaTexも含めてひととおりのフォーマットに対応してるし↓、ドキュメントエンジンでいろんなフォーマットに出したいというとたいていSphinxという印象💪」「Pythonベースみたいですね」「それもたぶんあまり気にされてないかも: 自分は使ったことないし使うこともたぶんないと思うけど😆」
⚓言語よろずの間
⚓icecream: C++の分散コンパイラicecc
参考: Icecream - らるるの自宅と職場を往復する人生@それをすてるなんてとんでもない!
つっつきボイス:「babaさんの日報で知りました」「分散コンパイラは全然詳しくないなー: たぶんクラスタでどかんとビルドするんだろうけど」「ちなみにbabaはBPSのCTOで、超縦書↓というブラウザベースのEPUBビューアを主にやっているんですが、あれほどの規模になると分散コンパイルが必要なのは想像できるし、何しろそのためだけに超高速のSSDをマシンのPCI Expressに直接ぶっ刺してるほど: ディスクがどうしてもボトルネックになるから」「おー😳」「『コンパイルが30分で終わる❤️』って喜んでました😊」「(以下昔のビルド話)」
⚓その他
⚓全米のスマホで「大統領アラート」試験が実施
The first ever “Presidential Alert” for emergencies will be tested on cell phones nationwide October 3
https://t.co/9E7dBAjH2D @stewartyerton pic.twitter.com/o9jmc56lfh
— Honolulu Civil Beat (@CivilBeat) September 20, 2018
これが全米のスマホに一斉表示されたそうです。
つっつきボイス:「Facebookで知人がこれを見てびっくりしたと言ってたので」「これはびっくりするヤツ😨」「大統領アラート、何に使うんでしょうね?」「やっぱりミサイルが飛んできたときかしら🚀」
⚓番外
⚓太陽を周回する新天体「ゴブリン」が発見
Dwarfとなっていますが、質量はもしかすると地球並かそれ以上かも?
つっつきボイス:「Dwarf planet?」「惑星未満の準惑星ってことみたいです」「この軌道がめちゃめちゃアウトしていてスゴイ」「地球の近くまで来たら何か起きるかな?👽」「そのときボクら生きてるんでしょうかね😆」「公転周期どえらく長そうだし😆」「お、予定時間ピッタリに終わった🎉」「ではこのまま親睦会に移りましょう🍻」
参考: 準惑星 - Wikipedia
参考: 東京新聞:太陽との距離、海王星の80倍 新天体を米チーム発見:社会(TOKYO Web)
今回は以上です。公開つっつき終了後の親睦会もいつものように盛り上がりました🍻🍕。ご参加いただいた皆さま、お疲れさまでした&ありがとうございました!🙇
バックナンバー(2018年度後半)
週刊Railsウォッチ(20181001)Railsアップグレード記事と各種支援ツール、CLI向けRubyワンライナー集、Rubyアプリをワンバイナリ化ほか
- 20180925 Rails大規模支払サービス開発のノウハウ、RailsのMySQLがutf8mb4に移行、Rpush gemほか
- 20180918 ビューテンプレート探索が高速化、mini_scheduler gem、レガシコントローラのリファクタリングほか
- 20180910 公開つっつき会#2、RSpecは何を参考にするか、イベントソーシング、marginalia gem、負荷テストツールvegetaほか
- 20180903 次世代アップローダーgem「Shrine」、RSpecをどこまでDRYに書くか、Rubyのmainオブジェクトの秘密、GitLabのCookie利用許諾機能はエライほか
- 20180827 Ruby Prize 2018募集開始、Interactor gemとReader Object、書籍『Real World HTTP』、Basecampのヒルチャート機能ほか
- 20180820 Railsで構築されたサイト40選、Deviseはつらいよ、ARのスコープとクラスメソッドの使い分けほか
- 20180813 Rails 5.2.1リリース、sanitize_sql_arrayは5.2からpublicだった、Dev.toがRailsアプリのソースを公開ほか
- 20180806 Rails 5.2.1.rc1リリース、Railsガイド日本語版が5.1に対応、Regexp#match?ほか
- 20180723 Railsdm Day 3 Extremeを後追い、PSDにはZeplin.io、好みの分かれるJSX、負荷テストツール比較ほか
- 20180709 Rails Developers Meetup Day 3 Extreme今週末開催、RailsのSTI/キャッシュ/添付ファイル/Redis/PDF出力、ECMAScript 2018、プロフェッショナルIPv6ほか
- 20180702 Ruby 2.2メンテ正式終了、Ransackがつらくなるとき、書籍『Domain-Driven Rails』、GitHubの高可用MySQLほか
- 20180622 Railsの需要未だ巨大、Unicode 11.0リリース、WebDriverがW3Cで勧告、Flutter.io、2封筒問題ほか
- 20180615 TTY gemとHTTPClient gemは優秀、Rubyの謎フリップフロップ、ちょいゆるRubyスタイルガイドほか
- 20180608 特集「RubyKaigi 2018後の祭り」、
Enumerable#index_with
は優秀、コントローラから@
を消し去るほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。