- 開発
週刊Railsウォッチ(20170616)railsdiff.orgはアップグレードに便利、RubyのDSLとかっこの省略、TerraformをRubyで制御ほか
こんにちは、hachi8833です。先週から歯痛で転げ回ってましたが、レントゲンにもCTにもそれっぽいものが映りませんでした。謎です。
6月第2週のRailsウォッチ、いってみましょう。
Rails 5.0.4.rc1リリース
バグ修正用です。リグレッションが見つからなければ早くも来週月曜にリリースされるそうです。
変更点はきわめてわずかで、ActiveRecordとActiveModelの修正だけでした。Rails 5.0.x系をお使いの方はアップデートをおすすめします。
Rails: 今週の改修(Rails公式ニュースより)
新機能: mattr_accessor
でもデフォルト指定オプションを追加
DHHが先週class_attribute
にデフォルト値を指定できるオプションを追加したからmattr_accessor
でも追加しようよ、という流れです。今回も以下のような感じでガシガシ追加されています。
# actionmailer/lib/action_mailer/preview.rb
- mattr_accessor :preview_interceptors, instance_writer: false
- self.preview_interceptors = [ActionMailer::InlinePreviewInterceptor]
+ mattr_accessor :preview_interceptors, instance_writer: false, default: [ActionMailer::InlinePreviewInterceptor]
ついでにcattr_accessor
でもガシガシやっています。
# actioncable/lib/action_cable/server/base.rb
- cattr_accessor(:config, instance_accessor: true) { ActionCable::Server::Configuration.new }
+ cattr_accessor :config, instance_accessor: true, default: ActionCable::Server::Configuration.new
つっつきボイス: 「ところでcattr_accessor
とmattr_accessor
って何が違うんでしょうか」「なんだか動作同じなんですけど」
morimorihogeさんがRubyMineで追っかけてみたところ、以下のオチでした。一同「何じゃそりゃーw」
# activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
alias :cattr_accessor :mattr_accessor
新機能: 多数のキャッシュエントリを一括で書き込めるwrite_multi
💪
Rails.cache.write_multi foo: 'bar', baz: 'qux'
#write_multi_entries
を実装するストアに、より高速な#fetch_multi
を追加。
見つからないキーは(個別ではなく)一括でキャッシュストアに書き込まれるデフォルトの実装では単にエントリーごとに
#write_entry
を呼んでいる。
RedisMSET
のように一括書き込み可能なストアはオーバーライドを行える。
# activesupport/lib/active_support/cache.rb
options = names.extract_options!
options = merged_options(options)
- results = read_multi(*names, options)
- names.each_with_object({}) do |name, memo|
- memo[name] = results.fetch(name) do
- value = yield name
- write(name, value, options)
- value
+ read_multi(*names, options).tap do |results|
+ writes = {}
+
+ (names - results.keys).each do |name|
+ results[name] = writes[name] = yield(name)
end
+
+ write_multi writes, options
end
end
つっつきボイス: 「CacheバックエンドにRedisを使ってればRedisのMSET
命令で一括書き込みできるということかな」
修正: チェックボックスやラジオボタンのラベルをクリックしても選択できるようになった
「チェックボックスやラジオボタンのラベルもクリッカブルにする」は最近のWeb UIエクスペリエンス周りではよく行われていますが、今回から対応しました。
# actionview/lib/action_view/helpers/tags/collection_check_boxes.rbの場合
def check_box(extra_html_options = {})
html_options = extra_html_options.merge(@input_html_options)
html_options[:multiple] = true
+ html_options[:skip_default_ids] = false
@template_object.check_box(@object_name, @method_name, html_options, @value, nil)
end
end
つっつきボイス: 「これ仕様だと思ってたけどついに直るのか」「自分でラベルを処理しようとするとすごく面倒くさい」
そういえばラベルをクリッカブルにするChrome拡張機能を以前使ったことがあるのですが、今探したところうまく見つけられませんでした。
修正: パーシャルのキャッシュログで誤ったパーシャルから属性を取得していた問題
- Commit: 824063
- PR: #28637 Fix partial cache logging
# actionview/lib/action_view/helpers/cache_helper.rb
def fragment_for(name = {}, options = nil, &block)
+ # Some tests might using this helper without initialize actionview object
+ @cache_hit ||= {}
if content = read_fragment_for(name, options)
- @cache_hit = true
+ @cache_hit[@virtual_path] = true
content
else
- @cache_hit = false
+ @cache_hit[@virtual_path] = false
write_fragment_for(name, options, &block)
end
end
# actionview/lib/action_view/renderer/partial_renderer.rb
content = layout.render(view, locals) { content } if layout
- payload[:cache_hit] = view.cache_hit
+ payload[:cache_hit] = !!view.cache_hit[@template.virtual_path]
content
end
end
つっつきボイス: 「あー、パーシャルがネストしたときとかが問題だったのか」
余談: たった今気づいたのですが、これをコミットしたStan Lo氏は、この間Railsウォッチで紹介したGobyのメインメンテナでもあります。
RailsでAPMサービスをスクラッチ開発(RubyFlowより)
私が最初元記事を「AMP」と空目してしまい、ひととおりスマホのAMP談義があったあとで「あれ、これAPMじゃね?」と気づきました。失礼しました。
つっつきボイス: 「なーんだ、Application Performance Monitoringのことか」「Advanced Power Managementではない(キリッ」「NewRelicみたいなことを自分たちでやろうとしてるのかー」「またしても車輪の再発明w?」
そこから、NewRelicはやっぱり凄いという話題になりました。morimorihogeさんがその場でNewRelicにログインしてみると、大昔に作ったトライアルのエントリでもしっかりチャートが生成されました。
つっつきボイス: 「NewRelic、やっぱりいろいろよくできてる」「ライブラリやメソッドの呼び出しレベルまでチェックしてくれるし」「高いけどねw」「トライアルだとどこまでできるんだったかな?」「NewRelicってアプリの相当深いところまで食い込むのか」「たしかそのためのエージェントをgemでインストールしたはず」
静的型付け言語だからバグが減るわけではない?
某所で見かけました。これは2016年に書かれた元記事が別サイトに再掲載されたものですが、忘れた頃にバズったようです。
原文でも断言は避けていますが「静的型付け言語ならバグが減る、とは言い切れないのでは」「むしろ言語仕様のシンプルさの方がバグ減らしに貢献しているのでは」という見解です。
グラフのx軸はバグの密度です。グラフ上ではRubyが健闘しています。
つっつきボイス: 「GitHubのbug
タグでかき集めたのか」「うーん、これは信頼に足る情報なんだろうか」「とりあえず集計方法は疑問だなー」「すごく巨大なC++プロジェクトとかあったらbug
多いに決まってるんだから不利じゃん」「極端なデータは捨てないといけないのかな」「それもデータの種類や目的とかによりますね: 極端なデータに意味があることもあるし」
DockerとクラウドでHeroku的なデプロイソリューションを構築(Ruby Weeklyより)
タイトル通りです。長いです。
つっつきボイス: 「Google Container Engineとか使えばいいのに」「意識高めの車輪の再発明という感じ」
stdgems.org: Rubyバージョンごとのデフォルトgemとバンドルgemのリスト
サイト: stdgems.org
Rubyのバージョンごとにどんな標準のgemがあるかを一覧できます。標準のgemはデフォルトgem(取り外せない)またはバンドルgem(外部メンテ、取り外し可)に区別されており、Ruby 2.2以降が対象です。
Rubyの標準ライブラリはgem化が進められており、Ruby 2.5の「たぶんこうなる」も見ることができます。
つっつきボイス: 「これ悪くないかも」「知ってれば見るかなー」「普通にrbenvでインストールして確認しちゃうかも」
同時実行制御を深掘り: イベントループの巻(Ruby Weeklyより)
シリーズものです。
つっつきボイス: 「このあたりを掘っていくとOSの話は避けられないね」「OSは一度みっちりやっておくのが大事」
そこから、concurrentとparallelの違いなどについて話題になりました。なお、上の記事にはparallelという言葉は一度も使われていません。
つっつきボイス: 「concurrentとparallelはITの世界でははっきり違う」「concurrentは「異なるタスクの手分け」、parallelは「同じ種類のタスクの手分け」」「concurrentをsimultaneousという言葉で形容することはない: simultaneousは「開始が同時」というだけ」
- 参考: ASCII.jp データ処理に関するIT英語「concurrent」「parallel」「distributed」
Rubyの#each_cons
は他の言語でどう書くの?(Ruby Weeklyより)
Rubyだと以下のように書けるコードを他の言語で書くとどうなるか、という記事です。F#、C#、Kotlin、Idrisのコード例などが集められています。
([0] + arr).each_cons(2).count {|x,y| x == 0 && y == 1 }
Rubyリファレンスマニュアル: each_consでは以下のようになっています。
要素を重複ありで n 要素ずつに区切り、 ブロックに渡して繰り返します。
ブロックを省略した場合は重複ありで n 要素ずつ繰り返す Enumerator を返します。
C#ではそれ用のコードをこしらえています↓。
つっつきボイス: 「ちょC#スクショだしww」「しかも斜めってる」「#each_cons
って要素が重なるのか」「重ならないのが#each_slice
、その名のとおり」
インタビュー: Aaron Patterson(Ruby Weeklyより)
tenderloveの名前でおなじみのAaron Patterson氏インタビューで、Railsconf 2017でのインタビュー音声つきです。HTTP/2と「Rack 2」計画との関連など、技術面でも非常に読み応えのある良記事です。
ベーコン作りが趣味で、Rubyのハックに必要な日本語記事を読むために11年前から日本語を勉強し、今では日本語ブログも問題なく読めるようになったそうです。凄い!
インタビュー中で、kazuho氏の作ったH2OというWebサーバーを「HTTP/2サーバーとしては最高峰だ」と激賞しています。
つっつきボイス: 「これは日本語になってたら読みたい」「長いから英語で読むのはだるい」「H2O、数年前に話題になってました」「当時HTTP/2をまともに使えるWebサーバーがこれしかなかったんだったかな」「H2Oのh2o.examp1e.netってドメイン名、クラックサイトっぽいwww」「お、lが1になってるw」
参考: 東京 Ruby 会議 11 直前特集号 Aaron Patterson さんインタビュー
開発用ローカルWebサーバーをNginxからTræfikに置き換える(Ruby Weeklyより)
Træfikは文字化けではありません。Goで書かれたリバースプロキシ兼用Webサーバーで、GUIで設定できるのがウリのようです。
つっつきボイス: 「GUI(゚⊿゚)イラネww」「CLIでちゃんと設定できない人がGUIでできると思えない」「両方で設定を繰り返すと泣くことになりそうってkazzさんも言ってた、そういえば」
Railsでcookieをテストする(Ruby Weeklyより)
capybaraでfeature specを書くのは避けたかったらしく、rack-test gemの#get-cookie
を使っています。
# http://blog.arkency.com/2017/06/testing-cookies-in-rails/ より
describe do
specify do
get "/"
Timecop.travel(35.minutes.from_now) do
get "/"
cookie = get_cookie(cookies, "foo")
expect(cookie.value).to eq("some value!")
expect(cookie.expires).to be_present
end
end
# rack-test > 0.6.3 に組み込まれる予定
def get_cookie(cookies, name)
cookies.send(:hash_for, nil).fetch(name, nil)
end
end
つっつきボイス: 「cookieでここまでテストしないといけないのか、大変だなー」
たった2分でRubyプリミティブをカスタムドメインオブジェクトに書き換える方法(Ruby Weeklyより)
ここではNet::HTTP
が返すStringのステータスコード'200'
を、#success?
でチェックするようリファクタリングしています。テストコードも一緒に書いてあるので助かります。
つっつきボイス: 「こういうの、たまにやるかなー」
GeoEngineering: TerraformのDSLをRubyで書けるgem(Ruby Weeklyより)
- リポジトリ: coinbase/geoengineer
インフラをコードで管理するソフトウェアであるTerraformをRubyで制御するラッパーのようです。なおTerraformはGo言語で書かれています。
つっつきボイス: 「Terraformは超有名で実績も多数」「Terraformのリポジトリ、★8,600超えだ」「TerraformのDSLは割りと独特なので、それをRubyで書きたいってことか」「GeoEngineeringの方は★200個程度というのがちと不安」
# https://www.terraform.io/ のサンプルDSL
resource "aws_elb" "frontend" {
name = "frontend-load-balancer"
listener {
instance_port = 8000
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
instances = ["${aws_instance.app.*.id}"]
}
resource "aws_instance" "app" {
count = 5
ami = "ami-408c7f28"
instance_type = "t1.micro"
}
# https://github.com/coinbase/geoengineer のサンプルコードより
class GeoEngineer::Resources::AwsSecurityGroup < GeoEngineer::Resource
# ...
def all_egress_everywhere
egress {
from_port 0
to_port 0
protocol "-1"
cidr_blocks ["0.0.0.0/0"]
}
end
# ...
end
project.resource('aws_security_group', 'all_egress') {
all_egress_everywhere # use the method to add egress
}
ところで、GeoEngineeringという名前は明らかにTerraformを意識してますね。暁星記という未完のマンガを思い出しました。
n_plus_one_control: RSpec/miniTestの両方で使えるN+1問題検出マッチャー(Ruby Weeklyより)
- リポジトリ: palkan/n_plus_one_control
expect { subject }.to query(2).times
のように具体的な回数を書かずにN+1問題をテストできるそうです。クエリの数がO(N)ではなくO(1)として振る舞うかどうかをテストします。
「bulletでもテスト書けるんだけど?」については、「bulletは銀の弾丸(silver bullet)じゃないので、偽陽性や偽陰性の可能性が残る」だそうです。誰がうまいこと言えと。
つっつきボイス: 「N+1が起きてないことをテストする?」「N+1警察はN+1でないことを確認するテストを書くんだろうなーw」「★まだ80個台...」
Rubyのコードを読む: DSL(RubyFlowより)
連載記事の4回目です。RubyのROMのDSLをとことん追求している濃厚な記事です。
# https://blog.mikecordell.com より
def schema(dataset = nil, infer: false, &block)
if defined?(@schema)
@schema
elsif block || infer
self.dataset(dataset) if dataset
self.register_as(self.dataset) unless register_as
name = Name[register_as, self.dataset]
inferrer = infer ? schema_inferrer : nil
dsl = schema_dsl.new(name, inferrer, &block)
@schema = dsl.call
end
end
つっつきボイス: 「ROMはRuby Object Mapperのことか」「RubyでDSL書きたい人にはよさそう」
morimorihoge「RubyのDSL入門ならCodeSchoolのRuby Bits part 2がシンプルでおすすめですよー」
その後、Rubyの引数のかっこを省略できる仕様の理由を私は今頃になって初めて知りました。
つっつきボイス: 「Rubyでかっこを省略できるのは、RubyでDSLを書きやすくするためという明確な目的がある」「そうだったのか!」「たしかmatzはRubyの初期からそのつもりでやっているはず」
ネットの記事で「Rubyではかっこを省略できるので、DSLを簡単に書けます」という記述をときどき見かけていました。そこから「たまたまかっこを省略できるのでそれを利用して...」かなと思っていましたが、違いました。Rubyは「言語を書くための言語」を最初から志向していたんですね。
RailsでUIコントローラ(RubyFlowより)
ネストしたフォームを使う場合など、ビューが複雑になった場合にコントローラをどう扱うかを検討し、ここでは以下の3番目の方法を使っています。
- 同じコントローラに新しいメソッド(アクション)を追加
- 別のコントローラを書く
- UIコントローラをネストする(Railsの密かな第3のオプション)
ここではコントローラでささやかなDSLを書く方法を使っています。さらに、ネストを重ねたり、ネストしたコントローラでもパーシャルを参照できるようにするなどし、ルーティング用のモジュールも書いています。
つっつきボイス: 「この方法、悪くないかも」「『RESTfulを崩さないかぎりコントローラは増やしてもいい』がDHH流ですよね」「ネストするフォームってつらくなりがち」「この落書きwww↓」「1分間に何回WTF(何やこれは!)って言われるかでコードの良し悪しがわかるw」
Railsアプリのアップグレードに役立つリソース集(RubyFlowより)
「アップグレードのときはこれ見ましょう」リンク集です。
つっつきボイス: 「Rails 4どまりかー」「世の中にはRails3っていうものもあるんだじぇー」
⭐ railsdiff.org ⭐
むしろ、その中で紹介されていたrailsdiff.orgの方が一同の目を引きました。
RailsのバージョンアップでRailsアプリのどこを変更しなければいけないかをざっと表示するもので、内部コードのdiffではありません。当然ながらバージョンが離れるほどどんどん量が増えます。こちらは何とRails 2.3.6以降に対応しており、Rails 4.xとRails 3.xといった設定の差も表示できます。
つっつきボイス: 「これ、いいんじゃん!?」
⭐ を進呈いたします。おめでとうございます。
Rubyで機械学習: 線形回帰を実装(RubyFlowより)
x_data = []
y_data = []
# CSVから配列に読み込む - 自由変数 X と従属変数 Y
# 各行には以下のようにプロパティと生活圏の広さ(平方フィート)を含む
# [ SQ FEET PROPERTY, SQ FEET HOUSE ]
CSV.foreach("./data/staten-island-single-family-home-sales-2015.csv", :headers => true) do |row|
x_data.push( [row[0].to_i, row[1].to_i] )
y_data.push( row[2].to_i )
end
つっつきボイス: 「Pythonでやってくれーw」
Quora: 有名サイトでRubyが使われてないのはどして?
最近のQuoraから届く更新メールはこれ系の記事が多く、こちらのクリックがトラック・分析されていることをひしひしと実感します。
回答は「そりゃRailsが登場する前からあるサイトばかりだからなんじゃ?」「Rails登場以前はRubyで大規模Webサイトを作るとかありえなかったし」などなど。
つっつきボイス: 「(トラック・分析は)記事表示の最適化がQuoraの売りだから」「煽ってくるなー、このタイトル」「その割にスレが伸びてないなw」「みんな不感症になっちゃった?」「初期のTwitterとかもRailsで構築されていたんだけどな」「表にもTwitterあるし」
今週は以上です。
関連記事
- 週刊Railsウォッチ(20170609)ついにtherubyracerからmini_racerへ、注意しないとハマるgem、5.1でのVue.jsとTurbolinksの共存ほか
- 週刊Railsウォッチ(20170602)チームが喜ぶ19のgem、Bundler 1.15が高速化&機能追加、Deviseに挑戦する新認証gem「Rodauth」ほか
- 週刊Railsウォッチ(20170512)Rubyの不思議な挙動「シャドウイング」、コードレビュー作法を定めるDanger gemほか
- 週刊Railsウォッチ(20170428)Rails 6.xでの’#form_for’と
#form_tag
廃止決定のその後、deviseの5.1対応はこれから、ほか - 週刊Railsウォッチ(20170421)RailsConfが来週アリゾナで開催、コントローラを宣言的に書けるdecent_exposure gemほか
- 週刊Railsウォッチ(20170414)サーバーを危うくする1行のコード、PostgreSQL 10の新機能ほか
- 週刊Railsウォッチ(20170407)N+1問題解決のトレードオフ、Capybaraのテスト効率を上げる5つのコツほか
- 週刊Railsウォッチ(20170331)PostgreSQLの制約機能を使えるRein gemはビューも使えるほか
- 週刊Railsウォッチ(20170324)Ruby 2.4.1リリース、GAEがついにRubyに対応、このgemがないと生きていけない27選ほか
- 週刊Railsウォッチ(20170317)Railsパフォーマンスチューニング本、DBレコード存在チェックの最速メソッド、RubyのUnicode正規化ほか
- 週刊Railsウォッチ(20170310)クールなDocker監視ツールCtop、RailsがGoogle Summer of Code 2017に正式参加、Unicode 10.0.0ドラフト発表ほか
- 週刊Railsウォッチ(20170303)5.0.2正式リリース、メタプログラミングに懲りた話、bundler 1.12のバグ、すぐ試せるWebアノテーションほか
- 週刊Railsウォッチ(20170227)Rails 4.2.8リリース、SHA-1コリジョンアタック、便利なハッシュ変換ツールほか
- 週刊Railsウォッチ(20170217)Rails 4.2.8.rc2リリース、Ruby 2.4正規表現とActiveSupportのnormalizeほか
- 週刊Railsウォッチ(20170210)JRubyやRubiniusの配列への追加はスレッドセーフではないほか
- 週刊Railsウォッチ(20170203)AnyLogin gemで開発中に楽々再ログイン、イベント数ベース課金の監視サービスRollbarほか
- 週刊Railsウォッチ(20170127)わかりやすいAWSサービス名、Rails DBは便利、TruffleRubyの驚異的速度ほか
- 週刊Railsウォッチ(20170120)Ruby 2.5.0 devリリース、古いMySQLのサポート終了、uniqメソッドが削除ほか
- 週刊Railsウォッチ(20170116)Ruby 2.4の詳細、範囲指定したsumメソッドは速い、rescueの挙動を動的に変更ほか
- 週刊Railsウォッチ(20170110)ReactをRailsに置き換える、Ruby 2.4の新機能ほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。