- Ruby / Rails関連
週刊Railsウォッチ(20180330)春のリリースラッシュ: Rails 5.1.6/5.0.7とRuby 2.5.1など、Ruby 2.2は3月でメンテ終了ほか
こんにちは、hachi8833です。Rails Developers Meetup 2018が無事終了しましたね。終わった後は久々のスタミナゼロ状態でした。関係者の皆さま、本当にありがとうございました。
I just published “Rails Developers Meetup 2018 を終えて” https://t.co/mxqwQFSsU0
— 無題のドキュメント (@yoshi_hirano) March 27, 2018
年度末の忙しさの中、桜咲く3月最後のウォッチ、いってみましょう。
今回からh2タグとh3タグにアンカーを付けました。
⚓臨時ニュース
⚓Rails 5.1.6と5.0.7リリース
Rails 5.2.0より先に既存の更新がリリースされました。railtiesのChangelogを見た感じでは、後述のRuby 2.2.10リリースを受けて出されたという一面もあるようです。
⚓Ruby 2.5.1リリース: バグ/セキュリティ修正中心(Ruby公式ニュースより)
- プレスリリース: Ruby 2.5.1 Released
- 同日本語版: Ruby 2.5.1 リリース
本体および標準ライブラリのバグやセキュリティ修正です。過去のバージョンにもバックポートされました。
- プレスリリース: Ruby 2.4.4 Released
- プレスリリース: Ruby 2.3.7 Released
- プレスリリース: Ruby 2.2.10 Released
記念写真というより証拠写真でしょうか。
中の人のブログ↓も公開されています。
社内esaに超有用情報が書かれていたので、公開してもらいました / “3/28に公開されたRubyの脆弱性情報についてのポエム的解説 - pixiv inside” https://t.co/STmD6sOrix
— はるかさん (@harukasan) March 29, 2018
つっつきボイス: 「webrickの脆弱性などなど」「webrickを本番で使う人はまずいないでしょうねー」「確かに」
いるのかな?
参考: ruby/webrick
「#unpack
って例のC言語のprintf
みたいないやらしーやつでしたっけ」「16進まみれのw」「pack
/unpack
この間しぶしぶ使ったけど、@
指定できるとか知らんわー」
参考: Rubyリファレンスマニュアル String#unpack
⚓Ruby 2.2系は3月いっぱいでメンテナンス期間終了
- プレスリリース: Ruby 2.2.10 Released
同じプレスリリースです。極めて重要なセキュリティ修正を除き、今後2.2は更新されなくなります。
つっつきボイス: 「Rubyは毎年リリースされているから終了も毎年あるわけですね: 3月はさよならのシーズンというか」「サポートなくても動くは動くけどなっ」「2.2以下のRuby、あのアプリとかこのアプリとかあったかなー」「それより先にRails 5にアップデートせいという感じか」「Rubyをアップグレードする方が楽かな」
⚓Rails: 今週の改修
今回の公式情報はまとめ的な感じです。masterなので基本的にRails 6向けですね。
公式で紹介されている今回のコミットログはいつになくあっさりしているので、気軽に読めますね。
⚓Active StorageでAWS S3 SDK認証オプションを完全サポート
# activestorage/lib/active_storage/service/s3_service.rb#L9
class Service::S3Service < Service
attr_reader :client, :bucket, :upload_options
- def initialize(access_key_id:, secret_access_key:, region:, bucket:, upload: {}, **options)
- @client = Aws::S3::Resource.new(access_key_id: access_key_id, secret_access_key: secret_access_key, region: region, **options)
+ def initialize(bucket:, upload: {}, **options)
+ @client = Aws::S3::Resource.new(**options)
@bucket = @client.bucket(bucket)
@upload_options = upload
つっつきボイス: 「**options
で素直にまるっと渡せるようになったってことか」「渡しても全然大丈夫だったと」「パラメータで{}
と**
が隣り合っていると一瞬ドキっとしちゃいます: どっちに落っこちるんだみたいな」「そんなんばっかしですよもうw」
⚓MySQL2のサポート
# activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L6
-gem "mysql2", "~> 0.4.4"
+gem "mysql2", ">= 0.4.4", "< 0.6.0"
バージョン書き換えただけです。
⚓i18nの@virtual_path
置換え結果をメモ化
# actionview/lib/action_view/helpers/translation_helper.rb#L124
private
def scope_key_by_partial(key)
- if key.to_s.first == "."
+ stringified_key = key.to_s
+ if stringified_key.first == "."
if @virtual_path
- @virtual_path.gsub(%r{/_?}, ".") + key.to_s
+ @_scope_key_by_partial_cache ||= {}
+ @_scope_key_by_partial_cache[@virtual_path] ||= @virtual_path.gsub(%r{/_?}, ".")
+ "#{@_scope_key_by_partial_cache[@virtual_path]}#{stringified_key}"
else
raise "Cannot use t(#{key.inspect}) shortcut because path is not available"
end
つっつきボイス: 「@virtual_path
とな?やってることはメモ化だけど」「あ、#t
のあたりか!: どこでどうなってるのかようわからんやつ」
参考: ActionView::Helpers::TranslationHelper#translate
-- #t
はこれのエイリアスです
「ついでに質問しちゃいますけど、ActionView
にあるRails備え付けのビューヘルパーと、自分で書いたビューヘルパーって、どこかで一箇所に集まっちゃうというかまとめてグローバルになっちゃうんですよね?」「そうですね、同じところというかview_context
っていうのがあって、レンダリングではそいつが大もとみたいな感じになってるんですよ」「あー」「そしてそいつにヘルパーどもがインクルードされまくってるんですよ」「なるほどねー!」「自分でビューヘルパーひとつも書いてなくても、既にヘルパーが大家族状態ってことか」
参考: view_context
「ActionViewヘルパーの他にもActionController::Helpers
やらAbstractController::Helpers
やらもあって、そういうのが大挙してview_context
に押し寄せてる感じなんですよ(爆)」「やべー」「やべー」「インスタンス変数とかもこいつにどんどんアサインされていって居座るし」「おとろしい...」
「Railsでコントローラに書いたインスタンス変数をビューで参照できるなんて、裏でこっそり何かやってないとできるはずがないですからね」「そうそう、その設計思想がどうもなー: ビューに渡したいものがあったら自分で書きたいわ」「ビューに渡したくないインスタンス変数だってあるのに、全部渡されちゃう」「でインスタンス変数を増やすとだんだんわけわからなくなってくると」
⚓追伸
morimorihogeさんから補足情報をいただきました。オプションで変えられるということです。
RailsにおけるControllerのインスタンス変数からViewへの値渡しですが、これはRails 3.0からはApplicationController.view_assignsでフィルタリングできるようになっていたという記録が昔のCrafting Rails 4 Applications読み会の資料に残っていた pic.twitter.com/GHwtrvLzt9
— Masato Mori (@morimorihoge) March 30, 2018
確認したところ今のRailsでもAbstractController#view_assigns をoverrideすれば、Viewに渡したくないインスタンス変数は渡さない様にできますね。当該メソッドのコメントにも「You can overwrite this configuration per controller」とあるのでoverrideしてよさそうです https://t.co/xDW2ulq8pd
— Masato Mori (@morimorihoge) March 30, 2018
なお当時の読み会の資料はこちら2014年って4年前か。懐かしい https://t.co/CfnIri1tzG
— Masato Mori (@morimorihoge) March 30, 2018
参考: views_assigns
⚓ActionDispatch::Static
のパスをUS-ASCIIからASCII-8BITに変更
さようなら.html
のような日本語ファイル名も使えるようにということのようですが、極力したくないかも。
# actionpack/lib/action_dispatch/middleware/static.rb#L37
if match = paths.detect { |p|
- path = File.join(@root, p.dup.force_encoding(Encoding::UTF_8))
+ path = File.join(@root, p.b)
begin
File.file?(path) && File.readable?(path)
rescue SystemCallError
false
end
}
- return ::Rack::Utils.escape_path(match)
+ return ::Rack::Utils.escape_path(match).b
end
end
つっつきボイス: 「static/とかのhtmlファイルなんかが対象ってことですかね」「fixtureにあるactionpack/test/fixtures/公共/foo/さようなら.html
の「公共」ってsharedのことなんでしょうけど、日本人のセンスではなさそう」
⚓Active JobでQu gemのサポートを廃止
4年も更新のないQuがRails 5.1と互換性がなくなったためで、互換性が戻ることがあればまた追加するようです。
# activejob/test/integration/queuing_test.rb#L84
test "should supply a provider_job_id when available for immediate jobs" do
- skip unless adapter_is?(:async, :delayed_job, :sidekiq, :qu, :que, :queue_classic)
+ skip unless adapter_is?(:async, :delayed_job, :sidekiq, :que, :queue_classic)
test_job = TestJob.perform_later @id
assert test_job.provider_job_id, "Provider job id should be set by provider"
end
参考: bkeepers/qu
⚓Ruby 2.6ではURI#unescape
にモンキーパッチを当てない
これは自分で見繕いました。
# activesupport/lib/active_support/core_ext/uri.rb#L3
require "uri"
str = "\xE6\x97\xA5"
-parser = URI::Parser.new
-needs_monkeypatch =
- begin
- str + str != parser.unescape(str + parser.escape(str).force_encoding(Encoding::UTF_8))
- rescue Encoding::CompatibilityError
- true
- end
-
-if needs_monkeypatch
+if RUBY_VERSION < "2.6.0"
require "active_support/core_ext/module/redefine_method"
URI::Parser.class_eval do
silence_redefinition_of_method :unescape
つっつきボイス: 「Rubyでunescape
をちゃんとできるようになったから、バージョンを見てパッチをやめるってことですね」
⚓Rails
⚓ダウンタイムなしでスキーマ変更するには(Ruby Weeklyより)
つっつきボイス: 「後半ぐらいから『こうだったらいいのに』みたいな雰囲気ですね」「マイグレーション内のafter_deploy
ってRailsのメソッドか?と思ったら見当たらないから手作りというか、こんなのが欲しいってことなんでしょうね」「何をもってしてafter_deployを判断するんだろか?」「マイグレーションにそういうフックがあったとしても怖くて使えないw」
「コメント欄の方も気になっちゃって: こんな条件付きマイグレーション↓ができたらすごくうれしいんだけど方法が見当たらない...と」「それたぶんコントロールしきれないと思うヨ: おとなしく移行のバッチなりrakeタスクなりでやった方がええんではないかしら」「マイグレーション、ただでさえ複雑なのに」
# コメント欄より
class RemoveColumn < ActiveRecord::Migration[7.0]
on_next_deploy_after RenameColumn
# ↑こういうのとか↓こういうのとか
when RenameColumn, deployed_for: 1.week
def up
remove_column :posts, :name
end
end
ダウンタイムなく安全にdbのスキーマ変更するための方法について。参考になる / “Managing db schema changes without downtime” https://t.co/5RwGLnOuVJ
— willnet (@netwillnet) April 2, 2018
⚓RailsとTDDとDHHと
先日のこれ https://t.co/gxiH3gb1EL を思い出す。『Hanamiフレームワークに寄せる私の想い(翻訳)』 https://t.co/eQC5Cq46En
— Takuma SHIRAISHI (@ts7i) March 29, 2018
- マニアが潰したテスト駆動開発〜『健全なビジネスの継続的成長のためには健全なコードが必要だ』対談 (5)
- 2014-04-24 - やっとむでぽん -- DHHの”TDD is dead. Long live testing.”の翻訳です
つっつきボイス: 「ツイートでリンクされていた永和システムマネジメントさんのブログ記事がとても面白かったので: かの有名なt_wadaさんとの対談シリーズですね」
「『テスト駆動開発自体が自己目的化してしまった』とか」「手段と目的が入れ違ってというか」「何がしたかったのか思い出せなくなったというか」「このあたりとか考えさせられます↓」
だけど、先鋭化したテスト駆動開発や、例えばクリーンアーキテクチャーのような依存を逆転させて清潔にしたレイヤリングとRuby on Railsの強みは明らかに対立関係にあったんですね。
同対談より
「クリーンアーキテクチャってたしかこれ↓じゃ?」「あーそうだった!: morimorihogeさんが勉強会で見せてくれてた」
https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.htmlより
「こうしてみるとRailsは元々プロトタイプを素早く作る感じで、そもそもクリーンアーキテクチャとは目指すものが違うというか、だいたいコントローラにアクションが全部集まってるし」「この間のSOLID記事にも反してるし: まあ記事書いた人は反してないって言ってますけどw」「『ここは俺の家だ!』みたいな」
「でDHHが『TDDは死んだ』と宣言してセンセーションを巻き起こしたと」「たしかその当時、ケント・ベックとマーティン・ファウラーとDHHの対談がストリーミングで流れてて、『どうしてこうなった』みたいな話をしてましたね」「お、探します」
↓こちらです。Part IVまであってめちゃ長いのでPart Iのみです。
「ところで教条主義って言葉は私の年だと微妙に懐かしいんですけど、これって昔の学生運動のときによく使われた言葉だったんですよね: 『この教条主義者ガー』みたいな感じで」
⚓書籍『Refactoring』(Martin Fowler)第二版がリリース
同書はJava向けですが、Ruby向けのRefactoring for Rubyも定番です。惜しくも日本語版は割とすぐに絶版かつ中古で高値が付いています。
つっつきボイス: 「ちょうどそのMartin Fowlerさんの本ですね」「日本語の『リファクタリング:Rubyエディション』、中古で8000円かよ!」「これ、社内に1冊あったはず」「(社内の図書管理システムを参照して)お、あったあった」「これは借りなきゃ損損」「お、図書記録にhachi8833さんが『翻訳がとてもよい』って書いてるゾ」「(忘れてた...)」
⚓Railsで双方向関連付けをテストする(Hacklinesより)
# 同記事より
associations.each do |assoc|
# stuff from previous example
if too_hard
next
# self join (model has an association to the same model)
elsif assoc.klass == model
assert assoc.options[:inverse_of].present?, "Only half of a self-join association is defined in app/models/#{model.to_s.underscore}.rb. The inverse of :#{assoc.name} is not defined."
assert model.first.respond_to? assoc.options[:inverse_of], "The inverse of :#{assoc.name} is not functioning correctly. Check app/models/#{model.to_s.underscore}.rb."
# Explicitly defined inverse association. Must have an inverse defined in both models.
elsif assoc.options[:inverse_of].present?
assert associated_object = assoc.klass.to_s.singularize.camelize.constantize.first, "#{assoc.name.to_s.camelize} not present in fixtures. Check test/fixtures/#{assoc.name.to_s.pluralize.underscore}.yml.\nAssociation name: #{assoc.name}\nAssociated object: #{assoc.klass}"
model_method = assoc.options[:inverse_of].to_s
assert associated_object.respond_to?(model_method) || associated_object.respond_to?(model_method.pluralize), "#{associated_object.class.to_s.camelize} is not properly associated with #{model.to_s} via :#{model_method}. Check for the correct association in app/models/#{model.to_s.underscore}.rb."
# Using an alias to reference another model. Should probably have inverse relationships explicitly defined.
elsif assoc.name != assoc.klass
assert associated_object = assoc.klass.to_s.singularize.camelize.constantize.first, "#{assoc.name.to_s.camelize} not present in fixtures. Check test/fixtures/#{assoc.name.to_s.pluralize.underscore}.yml"
model_method = model.to_s.underscore
assert associated_object.respond_to?(model_method) || associated_object.respond_to?(model_method.pluralize), "#{associated_object.class.to_s.camelize} is not properly associated with #{model.to_s} using :#{model_method} as the inverse of :#{assoc.name}. Check for the correct associations and :inverse_of attributes in app/models/#{assoc.klass.to_s.underscore}.rb and app/models/#{model.to_s.underscore}.rb."
# Normal bidirectional association
else
# do the stuff from earlier
end
end
つっつきボイス: 「な、何だこれはw」「こんなにしてまでアソシエーションが抜けてないかどうかをテストする意味ってあるんだろか?」「コード書き終わったらいらないですよね、確かに」「テスト残す価値ないわ」「文章まだ読んでませんが、もしかしてたとえば外注先のコード品質が信用できなくて、怒りに任せてこういうテストを書いてから発注したとかですかね?」「テストファーストの匂いがする」
「ApplicationRecordにだったらこれっぽいのを書きたいかなと思ったりしますね: cancancanにあるcheck_authorization
なんかそうですけど、これをApplicationRecordに書いておくと、継承先でauthorize
を呼んでないときにエラーになる」「おー!」
「つかアソシエーションがあるかどうかをrespond_to?
でテストするのが一番楽じゃないっすか?」「確かにー」「Railsチュートリアルにも確かそんな感じで書いてありましたよ: respond_to? children
みたいに」「そうじゃなくてもモデル名使えばいいのに」
⚓コールバックとインスタンス変数
強く言いたいんだけど、 rails で `before_action` で `set_instance` みたいにインスタンス変数を暗黙的にセットしたりするの、ほんと嫌いなのでほんとやめてほしい。いや、一つや2つで、特に難しいロジックがないならいいけど、分岐したり3つとか4つとか暗黙的にセットされるとほんと
— HaiTo (@HaiTo_Linux) March 28, 2018
# 『3年以上かけて培ったRails開発のコツ集大成(翻訳)』2.より
class UsersController
before_action :load_resource
def index
# @usersで何かする
end
def show
# @userで何かする
end
def create
# @userで何かする
end
def update
# @userで何かする
end
def destroy
# @userで何かする
end
private
def load_resource
case params[:action].to_sym
when :index
@users = paginate(apply_filters(User.all, params))
when :create
@user = User.new(create_params)
when :show, :update, :destroy
@user = User.find(params[:id])
end
end
end
つっつきボイス: 「以前のTechRacho記事『3年以上かけて培ったRails開発のコツ集大成(翻訳)』でダントツで疑問が多く寄せられた『2. コントローラにload_resourceを書く』です」「うん、これキライ: indexしかないとかならまあわからんでもないけど、case
とかまで書いちゃうのはなぜ?みたいな」「厳密にスコープを分けたいとか常に何らかのスコープを通したいときとかなんですかね:気持ちはワカルけど」「全アクションに業務ロジックを書きたくないとか」「でもたとえばindexがいなくなったら台無し」「DRYに書こうとしすぎた感じですかね」
「怖いのは、新人くんとかにこれを盲目的にやられてしまうことかな」「あーたしかに」「何だかこう、コピペの匂いがするんですよね: これコピペしてやっとけって指導するみたいな」「これならコピペで動いちゃいますからね」
「このコードだとindexをpagenate
してるけど、後で特定のindexでpagenate
を使わないように変えようとすると詰む」「CSV出力みたいに、indexをページネーションしないとかざらにありますしね」
⚓(社内雑談より)Railsの設計で崩れやすいのは例外処理とロギング
つっつきボイス: 「この間タバコ吸いながらそういう話題になったので」「経験上、例外処理もロギングもまったく念頭にないまま書かれた素人さんコードに、後からそれを足そうとして詰む、みたいなのがよくあるかな」「ロギングはともかく、例外の方はそもそも正常系がぜんぜんちゃんとしていなかったりすると例外の拾いようがなくなって作り直す方が早かったり」「エラーの扱いが全然一貫してなかったりとか」「true
/false
で返すなよ、とか」
「ボクが例外処理が好きなのは、異常時にガード的にどんどん終わってくれるからコードがシンプルになるところ: if
書かなくていいし」
「Rubyスタイルガイドに『例外処理を制御フローに使わないこと』ってあったのを思い出しました」「そりゃやっちゃダメですよねw」「いわゆるgoto
的に使うもんじゃない」
参考: Avdi Grimm氏の有名な「Exceptional Ruby」のスライドです。
参考: Exceptional Ruby -- 同氏の著作です。
⚓その他記事など
- 元記事: Check Your Database Indexes For ActiveRecord Scopes - Andy Croll(Ruby Weeklyより)
- (動画)DHH流巨大Railsアプリのリファクタリング↓(Ruby Weeklyより)
⚓Ruby trunkより
⚓桁数が多いときにFloat#round(n)
の結果がずれる(継続)
# 同issueより
3.0e-31 #=> 3.0e-31
3.0e-31.round(31) #=> 3.0000000000000003e-31
つっつきボイス: 「Rational#to_f
で回避する、と」「Float
って忘れた頃につまずきますよね」
Rational
がデフォルトだったらいいのになんて思ってしまいました。
⚓コロンを変なところに置くと落ちる->(#14261と重複)
def a(x)
case x
when A
: # これ
when B, C
end
end
つっつきボイス: 「おー、これで落ちるのか」「『よくぞ見つけた』みたいなこと書いてる」「と思ったら#14261で修正されてた」「nobuさん、凄っ」
⚓(提案)ハッシュで特定のキーへの最短パスを取るメソッドが欲しい(継続)
# 同issueより
{
:a => {
:name => "abc"
},
:b => {
:name => "xyz"
},
}
deep_key(:name) => [:a]
つっつきボイス: 「これは欲しいときあるかも」「Rubyのハッシュキーの順序が保証されていなかったら大変そうですね」「『他の言語にあるからRubyでもやろうよ』というアピールは効きそう」「たしかPythonも最近順序が保証されるようになってた」
参考: Rubyリファレンスマニュアル Hash
⚓Ruby
⚓k0kubunさんのbenchmark/driver
I just published “Benchmark Driver Designed for Ruby 3x3” https://t.co/aybm3JgqGI
— k0kubun (@k0kubun) March 27, 2018
- リポジトリ: k0kubun/benchmark_driver
ベンチマークの別記事も見つけました。
- 元記事: Ruby Benchmarking
つっつきボイス: 「k0kubunさん今回は英語ブログだけ書いてるみたいですね: 両方書くのは大変だからかな」「そういう境地になりたいw」「ちょうど昨日derailed_benchmarksのREADME翻訳を出したところでした↓」
⚓あまり知られてないっぽいRubyのフック系メソッドたち
つっつきボイス: 「include
じゃなくてincluded
みたいに過去分詞というか受動態というか」「たとえばincluded
は、include
したときに発動するコールバックみたいな感じですね」「この名前、コールバックっぽく見えないなぁ: on_include
とかなら...」「でも何度も見かけるうちにわかるようになっちゃいましたねw」「method_removed
とかmethod_undefined
とか他にもまだまだあるんですね」
「そういえばinclude
される前に呼ばれるフックとかもあった気がする: んーと、append_features
だ↓」「こりゃすげえ」「こんなことまでできちゃうの?って正直びっくりでしたね」「呼び出しコスト大丈夫なのかしらん?」
参考: append_features
「フレームワーク的なものを作るときに欲しいやつで、業務で使ったらヤバイ」「included
は、言ってみればRailsのconcernsみたいなものだし、ありかな」「おー、concernsをそうやって説明してもらったら何だか腑に落ちた(気がする)」
⚓Browser: Rubyでブラウザ情報を検出するライブラリ(Ruby Weeklyより)
- リポジトリ: fnando/browser
# 同リポジトリより
...
browser.device
browser.device.id
browser.device.name
browser.device.blackberry_playbook?
browser.device.console?
browser.device.ipad?
browser.device.iphone?
browser.device.ipod_touch?
browser.device.kindle?
browser.device.kindle_fire?
browser.device.mobile?
browser.device.nintendo?
browser.device.playstation?
browser.device.ps3?
browser.device.ps4?
browser.device.psp?
browser.device.silk?
browser.device.surface?
browser.device.tablet?
browser.device.tv?
browser.device.vita?
browser.device.wii?
browser.device.wiiu?
browser.device.xbox?
browser.device.xbox_360?
browser.device.xbox_one?
...
つっつきボイス: 「Wii UとかXboxまであるじゃないですか」「何だかスゴイ」
「遠い昔に、当時の同僚であらゆるブラウザのUAヘッダをコレクションしてた人がいて、新しい携帯を買うたびにヘッダ取らせろってせがまれたのを思い出した」「今だともうコンプリート不可能ですね」
⚓Module.class_exec
でLiquid
を動かす(RubyFlowより)
- 元記事: Exotic Ruby: Module.class_exec, custom JSON And Liquid Drops In Action - Karol Galanciak - Ruby on Rails and Ember.js consultant
- リポジトリ: Shopify/liquid
Object.instance_exec
とModule.class_exec
は似ているけどちょっと違うみたいです。翻訳リクエストしてみます。
⚓GnuPGをRubyで実装した話(RubyFlowより)
⚓multi.rbって使われてる?
- 元記事: multi.rb - Multiple Dispatch and Pattern Matching for Ruby - てきとうなメモ
- 関連記事: If It's Not Nailed Down, Steal It
# 元記事より
require 'rubygems'
require 'multi'
multi(:fact, 0) { 1 }
multi(:fact, Integer) { |n| n * fact(n-1) }
for i in (0..5)
puts "fact(#{i}) ==> #{fact(i)}"
end
Matzのプログラミングのおきてをネットでけちけち読んでいて「マルチメソッド」という見慣れない言葉を見つけたので探してみました。
つっつきボイス: 「マルチメソッドって有名なんですか?」「知らないー」「(コードを見て)ほほう、なるほどー❤️」「おーなるほどー❤️」「すみません、面白みのところ教えてください🙇」
「普通だったらfact
メソッド作ってif
で分岐するところだけど、Haskell的にif
なしで書ける: 0が来たときは1つめのmulti
、それ以外が来たときは2つ目のmulti
が動くみたいな」「あー!言われてみればすごく数式っぽい: 数学的帰納法みたいな形」「関数型っぽいすね」
「まあでもこの書き方だと、パラメータの違う同じメソッドを複数定義するから、定義があちこちで増えたときにどれに解決するのかとかいろいろ面倒そう」「業務では使わないだろうなー」「処理として2つのmulti
があるところが自分的には残念: その間に何を実行されるかわからないでしょ?」「おー確かに」「処理とは別に定義としてこういうのを書けるんだったらきっと好き」
そういえば日本語記事にも「おもしろいんだがあまり使い勝手は良くなかった」って書いてありました。
プログラミングと直接関係ありませんが、引用したWikipediaにこんなことが書いてあります。
なお、数学的「帰納」法という名前がつけられているが、数学的帰納法を用いた証明は帰納ではなく、純粋に自然数の構造に依存した演繹論理の一種である。2 により次々と命題の正しさが"伝播"されていき、任意の自然数に対して命題が証明されていく様子が帰納のように見えるためこのような名前がつけられたにすぎない。
同Wikipediaより強調
100年遅いですが、個人的には数学的帰納法(mathematical induction)は「数学的誘導法」と訳して欲しかった...
⚓その他記事など
- 元記事: Behind the Scenes: Building a Dynamic Instrumentation Agent for Ruby - Sqreen Blog | Modern Application Security -- Ruby向けの動的なinstrumentation
- 元記事: Qyu: A distributed task execution system for complex workflows -- 分散タスク実行gem「Qyu(九)」(Ruby Weeklyより)
- 元記事: A New Ruby Application Server: NGINX Unit -- 新しいRuby製Webアプリサーバー Nginx Unit
- リポジトリ: diaspora/diaspora Ruby製オープンソースSNS(★めちゃ多い)
- リポジトリ: thoughtbot/appraisal Rubyコードの依存関係を切り替えて試せるgem(★850)
pycall.rb のロゴを作った - 恒温動物の生活ログhttps://t.co/0TUa4VcI2y
— みょうが 🇺🇦 (@mrkn) March 27, 2018
⚓SQL
⚓データベースの「トップN」問題を解決する(Postgres Weeklyより)
CitusData社のpostgresql-topnツールを紹介しています。
つっつきボイス: 「トップN問題って、N+1クエリみたいなアンチパターンとは違いますよね」「たぶんだけど、『トップ5の項目をすべてのカテゴリについて取る』みたいなやつなのかな: それなら確かに面倒かも」「Ruby側で処理すると効率悪いっすね」「DB側でできるんだとしたら便利かもー」
⚓pg_repack: PostgreSQLデータベースのテーブル再編成を最小のロックで
- リポジトリ: reorg/pg_repack
公開しそびれた翻訳記事で紹介されていたので。CLUSTERやVACUUM FULLと違って処理中のテーブルの排他ロックを維持せずにできるそうです。
⚓Awesome PostgreSQL: 精選ソフトウェア/ライブラリ/ツール/リソースリスト(Postgres Weeklyより)
Awesome MySQLを見て作ったそうです。どちらも参考になりそうです。
⚓JavaScript
⚓Vue.jsをRailsのフロントエンドとして使う(Ruby Weeklyより)
// 同記事より
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm'
import App from '../app.vue'
Vue.use(TurbolinksAdapter)
document.addEventListener('turbolinks:load', () => {
const app = new Vue({
el: '#hello',
data: {
message: "Can you say hello?"
},
components: { App }
})
})
⚓Conditioner.js: プログレッシブエンハンスメントをストレートに実現するJSライブラリ(JavaScript Weeklyより)
- 元記事: Lazy Loading JavaScript Modules With ConditionerJS — Smashing Magazine
- リポジトリ: rikschennink/conditioner
- デモ: https://rikschennink.github.io/smashing-magazine-lazy-loading-javascript-with-conditioner/killer-for-loop/?
プログレッシブエンハンスメントは、核となるコンテンツを最重要視するウェブデザイン戦略である。この戦略では、エンドユーザーのブラウザーやインターネット接続に合わせて、プレゼンテーション面や機能面で微妙に異なる内容や技術的に困難な内容をコンテンツに漸次追加していく。この戦略の利点として挙げられるのは、すべてのユーザーが任意のブラウザーまたはインターネット接続を用いてウェブページの基本的なコンテンツと機能性にアクセスできることと、より高度なブラウザーソフトウェアまたはより広帯域の接続を有するユーザーには同じページの拡張バージョンを提供できることである。
Wikipedia-jaより
参考: Wikipedia-ja プログレッシブエンハンスメント
⚓(動画)Vue.jsコンサルタントが本当は教えたくない7つの秘密パターン(JavaScript Weeklyより)
⚓その他記事など
- 元記事: React v16.3.0: New lifecycles and context API - React Blog
- 元記事: Announcing TypeScript 2.8 | TypeScript TypeScriptが正式に2.8に
⚓CSS/HTML/フロントエンド
⚓VisualInspector: 開発とデザインの齟齬をなくすCanvasFlip社のサービス(Hacklinesより)
- 元記事: Build Pixel Perfect Websites Without Dev-Design Conflict In Your Team — SitePoint
- サイト: https://www.canvasflip.com/visual-inspector/
- Chrome拡張: Visual Inspector by CanvasFlip
チーム開発でレイアウトをピクセル単位でびしっと決められるそうです。この種のサービスが最近増えてきているように思えるので。
⚓display: contents
のしくみ(Frontend Weeklyより)
CSSのdisplay: contents
の解説記事です。
参考: MDN display
⚓CSSの「Typed Object Model」について(Frontend Weeklyより)
Typed OMに関するGoogleの技術ブログです。文字列の代わりにオブジェクトベースのAPIを使ってJavaScriptからCSSを制御できるようです。
// 同記事より
el.attributeStyleMap.set('padding', CSS.px(42));
const padding = el.attributeStyleMap.get('padding');
console.log(padding.value, padding.unit); // 42, 'px'
記事の真ん中あたりにデモがあります(マウスオーバーすると四角形が回転する)が、私のChrome 65.0.3325.181では動かず、Chrome Canary 67.0.3383.0だと動きました。なお、今BPS社内ではbabaさんのおすすめでCanary版もインストールするのが流行中です。
最初わかってませんでしたが、CSS Object Model(CSSOM)を拡張したのがTyped OMという位置づけだと教えてもらいました。
CSSOM値の文字列を意味のある型付きJavaScript表現に変換(および逆変換)するとパフォーマンス上のオーバーヘッドが大きい。本仕様では、CSSの値を型付きJavaScriptオブジェクトとして公開することで効率よく操作できるようにする。
www.w3.org/TR/css-typed-om-1のAbstractより大意
参考: W3C CSS Typed OM Level 1
デモでついこのジャケットを思い出してしまいました↓。
坂本龍一『B-2UNIT』がリシツキーの「二つの正方形の物語」が元ネタなのは知られいるが、タイトルが米国軍野戦食から取られていたのは知らんかった。音と絵、語感で選んだ表題が互いに作用しあって名盤となった。そうゆうもんなんだな pic.twitter.com/XFdwhhMV9t
— Bellissima (@BellissM) July 23, 2015
⚓その他
⚓OracleとGoogleのJavaライセンス裁判
日本語記事です。とてもよくまとまってて助かります。ちょっと前に「GoogleがC#に乗り換えるかも?」みたいな記事を見かけたのですがうまく見つけられませんでした。
⚓ワイのLinux環境で使ってるツールを晒す(2018年度版)
知らないツールもいろいろあって楽しめます。「後はMacのAlfredみたいなランチャーやFenêtreみたいなピクチャ・イン・ピクチャ的ツールがLinuxにもあれば...」だそうです。
Almost there! pic.twitter.com/sdTn0HTlmA
— Yoann Moinet (@YoannM) October 4, 2017
⚓ReactiveX -- Observableパターンのライブラリ
- 元記事: ReactiveX - Intro
社内アプリチームがRxSwiftなどで盛り上がっているので。
つっつきボイス: 「ReactiveXって、何だかActiveXみたいな名前」「Rxなんちゃらのすべての元祖みたいなやつですね」「Observablesパターンが多用されるらしいんですけど」「Operatorsのページ見るとわかるけど、膨大なオペレーターがあるんですよね↓」「ほんとだー」
参考: Rubyリファレンスマニュアル Observable
「ところでRubyでObservableパターンってよく使います?」「そういえば、確かそのものズバリのObservable
ってモジュール↓がありますね: #changed
でフラグを立てて、notify_observers
を呼ぶと、フラグの立っているクラスでupdate
メソッドを呼ぶ形で通知する、みたいな」「おー」「かっけー」
# docs.ruby-lang.org: Observableより
require "observer"
class Ticker ### 定期的に株価をフェッチ
include Observable
def initialize(symbol)
@symbol = symbol
end
def run
last_price = nil
loop do
price = Price.fetch(@symbol)
print "Current price: #{price}\n"
if price != last_price
changed # オブザーバーに通知
last_price = price
notify_observers(Time.now, price)
end
sleep 1
end
end
end
「factory_botとかのコールバックでこのライブラリが使われてたような覚えがあります: after(:create)
あたりとか」
# https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md より
factory :user do
after(:create) { this_runs_first }
after(:create) { then_this }
end
⚓C言語のfor
文が変わる?
次のCで20年ぶりくらいにCのfor文の挙動が変わるぽい。https://t.co/CIY58JZBIt
— 7594591200220899443 (@shyouhei) March 27, 2018
// リンク先より
static inline int f (void) {
for (int i = 0; ; ) {
long i = 1; // CではできるがC++では無効
// ...
return i; // (おそらく期待に反して) Cでは1が返る
}
}
つっつきボイス: 「次のC?」「どういうこったろ?」「うお、for
文の中でlong i = 1
なんて書いてる: Cって今までこんな書き方できてたの!」「あれ、そもそもCでfor (int i = 0; ; )
みたいな書き方許されてたんだっけか?int i = 0
の部分をfor
より前に書かないとダメだった気がするけど: C言語ワカラン」「時間ないので次へー」
「関係ないんですけど、どの回だったかな、例のTuring Complete FM聞いてたら、『Cの関数宣言の何がイヤって、最初に型書くから途中まで読み進めないとそれが関数定義なのかどうかがわからないところ』って話があったんですよ」「ワカルー」「最近多くの言語が型を後ろに書くようになったのって、きっとそれなんでしょうね」
どこにでもいる平凡な東大生が自作CPUにUnixを移植していたら奇妙な事件に巻き込まれて世界を救うラノベが読みたい #tcfm / “10. Cコンパイラをスクラッチから作成、東大CPU実験、型とプログラミング (うどん)” https://t.co/B216rsCviR
— ISHIDA Akio (@iakio) March 28, 2018
⚓その他記事など
golang ここにきてさらにスケジューラ弄ろうとしてるのか。活発だなぁ。
— mattn (@mattn_jp) March 29, 2018
昨日言ってた #golang のスケジューラ変更案。現状、デバッガが停止中に任意の関数を注入出来ない問題があるので非同期で回すループの為にスケジューラに手を入れようって話。https://t.co/KbYKONjqI2
— mattn (@mattn_jp) March 30, 2018
⚓番外
⚓自分の声で
自分の声の合成音を作れるサービス https://t.co/kGtRsnLV68
— Koichiro Mori (@sylvan5) March 28, 2018
つっつきボイス: 「自分の声ってたいてい聞きたくないやつですけど」「これちゃんとした日本のメーカーじゃないですか」「自分の声をそっくりに出せるのって、アリバイ工作とかに使えたりして?」「他にもアレやらコレやら(略」
⚓宇宙を閉じ込めたような球体
ちょっと欲しい。
RT
The Universe Sphere - The Milky Way in a Spherehttps://t.co/ILOM4YM7XN— 森山和道/ライター、書評屋 (@kmoriyama) March 27, 2018
⚓地味に思われがちな固体物理
宇宙で最も冷たいキューブhttps://t.co/A02GVxhQ5c
「ニュートリノを放出しない二重ベータ崩壊」検出実験。 6ミリケルビンに保った二酸化テルル742kgが崩壊して温度上がるのを待っている。2ヶ月進めてまだ未検出(今後5年で5つを予測)。やはりこの手の実験、たいへんすぎる
— ゆきまさかずよし (@Kyukimasa) March 27, 2018
⚓請負の翻訳でやらせてもらえないやつ
Slack、日本語化頑張ってるね。 pic.twitter.com/5OxOzVkniB
— masa寿司 (@masa_iwasaki) March 26, 2018
⚓どこかで見たような...
Agility Robotics Raises $8 Million for Commercial Bipedal Robots https://t.co/597Cvc6Qsy
— Martin Ford (@MFordFuture) March 24, 2018
たぶんこれかな。
待望のカオカオ様の版画とどいた。原画展で見くらべましたが、限りなく原画に近い仕上がりです。諸星先生からサインまでいただいて感無量です! pic.twitter.com/cw0nffERvE
— 清水肇 (@shimipri) July 10, 2015
今週は以上です。
バックナンバー(2018年度)
週刊Railsウォッチ(20180323)Rails 5.2.0 RC2リリース、「サーバーレスなRubyが欲しい」、capybara風JSテストフレームワークCypressほか
- 20180316 Rails 5.2のドキュメント更新中、Value Objectの使い方、RubyがTIOBEトップテン復活、Rails「雪だるま」エンコーディングほか
- 20180309 RubyGems.orgのTLS 1.0/1.1接続非推奨、2年に1度のRailsアンケート、DockerのMoby Project、Ruby拡張をRustで書けるruruほか
- 20180302 Ruby 2.6.0-preview1とWebpack 4.0リリース、爆速検索APIサービスAlgolia、Clowneでモデルをクローンほか
- 20180223 Ruby25開催、Rails6のパラレルテスト、書籍「RSpecによるRailsテスト入門」更新ほか
- 20180216 Rails 5.1.5リリース、DHHのYouTubeチャンネルは必見、Ruby Toolboxが運営再開ほか
- 20180209 RubyにMJIT初マージ、高速JSON API gem、Railsにparallel-testingブランチほか
- 20180202 Rails 5.2.0 RC1と5.1.5.rc1リリース、Rails 6開発開始、メソッド絵文字化gemほか
- 20180126 Bootstrap 4登場でbootstrap_form gemが対応、PostgreSQLやnginxの設定ファイル生成サービスほか
- 20180119 derailed_benchmarks gem、PostgreSQLをGraphQL API化するPostGraphile、機械学習でモック画像をHTML化ほか
- 20180112 update_attributeが修正、ぼっち演算子
&.
はObject#try
より高速、今年のRubyカンファレンス情報ほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。