- Ruby / Rails関連
週刊Railsウォッチ(20170317)Railsパフォーマンスチューニング本、DBレコード存在チェックの最速メソッド、RubyのUnicode正規化ほか
こんにちは、hachi8833です。
「HackerNewsのランキングアルゴリズムをリバース・エンジニアリングした記事がHackerNewsから削除されたという記事」が昨日までHackerNewsでトップでした。ややこしいですね。
IPAが自ら脆弱性を報告した無料ゲーム「安全なウェブサイト運営入門」は書籍の名前かと思ってしまいました。
それでは今週もいってみましょう。
書籍「The Complete Guide to Rails Performance」(HackerNewsより)
- 元記事: How I Made $70,714.20 Self-Publishing a Book About Ruby on Rails
- 書籍サイト: The Complete Guide to Rails Performance
(Amazon.co.jpにはエントリがないので同サイトの書影をリンク付きで引用しました)
元記事は「私はいかにしてRails本で7万ドル稼いだか」的な記事ですが、その書籍の方をピックアップしました。読んでみないと何とも言えませんが、よさそうです。
ActionController::Parameters:にreverse_merge
とreverse_merge!
を追加(Rails公式より)
改修箇所は以下です。
# 現在のハッシュをother_hashにマージし、新しいActionController::Parametersインスタンスをすべてのキーとともに返す
def reverse_merge(other_hash)
new_instance_with_inherited_permitted_status(
other_hash.to_h.merge(@parameters)
)
end
# 現在のハッシュをother_hashにマージし、現在のActionController::Parametersインスタンスを返す
def reverse_merge!(other_hash)
@parameters.merge!(other_hash.to_h) { |key, left, right| left }
self
end
#merge
と#merge!
のパラメータ順序をRubyのHash#mergeで確認すると以下のようになっていました。
merge(other) {|key, self_val, other_val| ... }
-> Hashmerge!(other) {|key, self_val, other_val| ... }
-> self
「これ欲しかった!」「strong parametersにデフォルト値を設定したいときにいいかも」という声がありました。
strong parametersの#permit
は、paramsに入ってないkeyを#permit
した場合にParameterオブジェクトの当該keyがnil
になってしまいます。従来であればデフォルト値を与えたいときには自力でkeyに与える必要がありましたが、#reverse_merge!
を使ってparamsのkeyにデフォルト値を与えられます。
たとえばモデル側で余計なことをしたくない(ビューの都合だけでデフォルト値を設定したいなど)場合に、モデルではなくコントローラ側でデフォルト値を与えられるのがよいかもという意見もありました。
個人的にはコントローラでparamsをそれ以上いじるのは避けたい気がしました。
Capybaraでドライバがスクショ非対応の場合にはスクショを撮らないようになった(Rails公式より)
Improvementに分類されてましたが、バグ修正ですね。修正もごくわずかでした。
Migrator.schema_migrations_table_name
を非推奨化(Rails公式より)
SchemaMigrationモデルが切り出されたことによる変更です。変更自体はアプリ開発者には直接関連しませんが、schema_migrationsという名前のテーブルが話題になりました。
今さらですが、Railsのデータベースにはschema_migrationsテーブルがあり、versionカラムにはそれまでマイグレーションに使ったファイル(db/migrate/以下)のバージョン番号がすべて保存されています。
マイグレーションが思うようにいかなくて、思い余ってマイグレーションファイルのバージョン番号を変更してしまう人がいるらしいのですが、「schema_migrationsテーブルの一貫性が損なわれるから絶対やめた方がいいよ」という話を聞きました。
マイグレーションには恥ずかしい履歴が残りがちなので、気持ちはわかります。
例外時にローカルキャッシュがクリアされない問題を修正(Rails公式より)
改修箇所はわずかでしたが、見終わってからRackとWardenの役割の違いについて話題になりました。
手短にまとめると、Wardenは認証用フレームワークであり、RackとRailsアプリの間の層で認証やセッション管理をつかさどります。Rackはmorimorihogeさんいわく「薄いWebサーバー」であり、Rackの上でRailsやSinatraなどのアプリケーションが動作します。
Rackについては、Railsガイド: RailsとRackと技術評論社サイトの記事「Rackについて」、Wardenについては、「Devise を知るにはまず Warden を知るが良い」がそれぞれ参考になります。
サブディレクトリでのrake db:schema:load
の不具合を修正(Rails公式より)
実はRailsではサブディレクトリでもrails db:migrate
を実行できるのですが、「何が起きるかわからないからコマンドはプロジェクトのルートディレクトリでしか実行しない」という意見がありました。私も同感です。
ActionController::Rendererでのasset_urlの不具合を修正(Rails公式より)
asset_url
が不完全だった('https://'が含まれないことがあった)問題の修正です。
#28250ではやや緊張感のあるやりとりが繰り広げられていました。こんな写真が貼られてたり。もちろんお茶目でやっていると思います。
最終的にPRのrebaseに手違いが見つかり、それを修正して無事commitされました。
has_many関連付けでブロックにselect
したときに新レコードが作成されない問題を修正(Rails公式より)
#titlize
がアポストロフィに対応(Rails公式より)
改修箇所は、正規表現への\w
(語の区切りを表す)の追加で終わりました。
humanize(underscore(word)).gsub(/\b(?<!['’`])[a-z]/) { |match| match.capitalize } # 修正前
humanize(underscore(word)).gsub(/\b(?<!\w['’`])[a-z]/) { |match| match.capitalize } # 修正後
#titlelize
をどこかで見たと思ったらActiveSupport探訪シリーズ「ActiveSupport::Inflector
の便利な活用形メソッド群」でお見かけしていました。その後お変わりありましたね。
ちなみに私はtitlelizeという造語のスペルを一発で入力できたことがありません。いつも間違えます。
#titlelize
のサンプルに使われている映画のタイトルが趣味全開ですね。さりげに新旧取り混ぜているのはコミッターの層の厚さゆえかシニアコミッターに気を遣ったのかはわかりませんが。
# titleize('man from the boondocks') # => "Man From The Boondocks"
# titleize('x-men: the last stand') # => "X Men: The Last Stand"
# titleize('TheManWithoutAPast') # => "The Man Without A Past"
# titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
PostgreSQLのJSON型データのdeserializeが文字列を返す問題を修正(Rails公式より)
これもkamipoさんによる修正で、PostgreSQLのみが対象です。kamipoさんのコミットが膨大なので、昨年既に七福神入りしていたんですね。いつもありがとうございます?
Rails 5.0 七福神入りしてた? https://t.co/RGojsyxUrM
— Ryuta Kamizono (@kamipo) 2016年7月1日
簡潔・高効率かつRubyらしいコードを書く(RubyWeeklyより)
#attr_reader
で初期化を簡潔に書く、ブロックをprocオブジェクトに置き換えるなどの方法などが紹介されています。追記に、Ruby 2.3ではprivate
での#attr_reader
警告が表示されなくなったということについても触れられています(#10967 Is "warning: private attribute?" wrong?)。それほど短い記事ではありませんが、込み入ってはいないので読んでおくとよさそうです。
参考: 初期化を便利にするgem 2つ
ある程度複雑な初期化を楽に書くgemとして、morimorihogeさんが以下の2つを教えてくれました。
RubyのUnicode正規化とは
週刊Railsウォッチ(20170217)でマサカリが大量に飛んできた「Testing Ruby's Unicode Support」記事のリベンジです。
Frankly, I was a bit fuzzy on Unicode normalization.
一転してUnicode正規化を熱心に調べています。短くもよくまとまった良記事です。後でじっくり読んでみます。
- NF: "normalization form"の略
- D: "decomposition"の略
- C: "composition"の略
- K: "kompatibility"の略 ┐(´∀`)┌
「RubyやRailsのコミュニティがUnicode正規化に思ったほど関心を寄せていないのに少しだけ驚いた」としめくくっています。ASCIIだけで事足りる英語圏ではある程度仕方がないかなとも思いますが、私としては、絵文字のおかげで近年こうした問題に以前よりも関心が高まっているような気はしています。
微細な最適化が効く(RubyWeeklyより)
長いです。最適化の主題となっているsigprocmaskって何だろうと思って一同で検索したところ、プロセスが応答するシグナルを変更するシステムコールでした。
ただ、新しい記事にもかかわらず、使っているのがRuby 1.8なので現在のRuby 2.x VMには符合しなさそうです。
なぜRuby 1.8なのか
以下は、同記事のRubyバージョンがえらく古い点についての私の推測です。
全文がHTMLで公開されている「Rubyソースコード完全解説」は2004年に公開されましたが、英語化されたのはかなり最近です。そして同書がRuby 1.7.xをベースにしている(前書きには1.8でもほとんど同じだろうと書かれている)ので、2.xではこうしたローレベルの最適化を追求しづらかったのではないかと思いました。
リポジトリ: Ruby Hacking Guide Translation
データベースレコードの存在チェックはexists?
が最速
present? #=> 2892.7 ms
any? #=> 400.9 ms
empty? #=> 403.9 ms
exists? #=> 1.1 ms
だそうです。morimorihogeさんが「それぞれのメソッドがどんなSQLを吐いているかを知っておくことが重要」と指摘していました。記事中のサンプルコードでは#exist
だけにLIMIT 1
が含まれているのが効いているようです。
著者は「いつもexists?
でおk」と結論づけていますが、こうした速度はさまざまな条件によって影響される可能性があるので、参考として頭の隅に置いておこうと思います。
私はといえば、select 1 as one
はクエリの結果がいらない場合の定番のSQLであることを今さら知りました。
google-drive-ruby gem: RubyでGoogleスプレッドシートにアクセスできる(RubyFlowより)
- 元記事: Google Spreadsheets and Ruby
- リポジトリ: gimite/google-drive-ruby
表計算を何とかするgemです。
OAuth認証と組み合わせることで、RubyからGoogleスプレッドシートにアクセスして読み取りや更新を行えます。記事やリポジトリには記載されていませんが、Railsでも使えると思います。スプレッドシートを正しく運用できるのであれば、案件によっては合うかもしれません。
この種のgemを導入するときは、頻繁に更新されている(=放置されていない)ものを選ぶのが重要ですね。機会があれば使ってみたいですが、データをシートから取ってくるだけにしておきたいと思いました。
Rubyのモンキーパッチで怪我をしないためには(RubyFlowより)
Rubyはオープンクラスなのでモンキーパッチを簡単に当てられますが、よく切れるナイフと同様、自分の身を傷つけないように注意が必要と説いています。
- ひとつのメソッドにモンキーパッチが2つ当たると、最初のモンキーパッチは上書きされてまったく効かなくなる
- モンキーパッチで発生したエラーはクラス内で発生したように見えてしまう
- モンキーパッチをオフにする方が面倒
- モンキーパッチ実行前にクラスを
require
するのを忘れると、パッチではなくクラスの再定義になってしまう - モンキーパッチをモジュール化することもできるが、問題はさして変わらない: パッチはグローバルに効くので、別のライブラリでいつの間にか上書きされてしまう可能性がある
morimorihogeさんが、趣旨の近い記事としてクックパッド開発者ブログ「Ruby on Rails アプリケーションにおけるモンキーパッチの当て方」を挙げました。
Webアプリ・モバイルアプリ開発にRuby on Railsを選ぶ理由(RubyFlowより)
RubyFlowのリンクが壊れていたので、直接元記事にリンクしました。
- オープンソースであり、コミュニティによるサポートが絶大
- 改修が容易
- 短期間でのリリースが可能
- 開発ツールの再利用が利く
- 開発者に優しい
- 英語に近い感覚
タイトルと本文の量がほぼ同じぐらいですね。リンクはしませんが、About Usを見るとインドのアフマダーバードの会社でした。
EuRuKo 2017に参加すべき理由(RubyFlowより)
「〜する理由」記事が続きます。EuRuKoはヨーロッパで開催される大きなRubyセッションです。2016年度はブルガリアのソフィアでの開催、そして今年は9月にハンガリーの首都ブダペストでの開催となります。
- コミュニティが主役
- 交通の便がよい
- Geekすぎないのもありがたい
- 内容がよい
- 会社にもメリットがある
- 出張の名目として絶好
Matzももちろんキーノートスピーチを担当しますし、昨年はLTやCoding Golfも大いに盛り上がったそうです。
morimorihogeさんによると「会場が空港や駅から遠い」「宿がスムーズに取れない」「会場の周辺に居酒屋などがまったくない」カンファレンスはやっぱりつらいそうです。
日本であれば多少不便でも旅情を味わえたりしますが、海外(特にヨーロッパ)だと都市部であってもコンビニが少なかったりレストランも土日閉まってたりすることが多いので、参加にあたってはそのあたりをチェックしたいですね。
今週は以上です。
関連記事
- 週刊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の新機能ほか
- 週刊Railsウォッチ(20161224)Float#roundの動作変更を取り消し、Rails 5.0.1/Ruby 2.4.0-rc1リリースほか
- 週刊Railsウォッチ(20161218)Ruby 2.4ではFloat#roundの動作が変わる、デフォルトのプライマリキーをBIGINTに変更ほか
- 週刊Railsウォッチ(20161209)Active Supportの非推奨メソッド廃止、RailsのjQueryへの依存を廃止ほか
- 週刊Railsウォッチ(20161125)Railsのデータベース・ベストプラクティス、SQLインジェクション解説ほか
- 週刊Railsウォッチ(20161117)DockerホスティングのHyper.sh、accepts_nested_attributes_for殺すほか
- 週刊Railsウォッチ(20161109)bundler audit gemは超おすすめ、CIAのFactbook gemほか
- 週刊Railsウォッチ(20161102)HTML 5.1正式勧告、CSS中央揃えに便利なサイトほか
- 週刊Railsウォッチ(20161027)LinuxカーネルのDirty COW脆弱性、DeviseはWikiを読めほか
- 週刊Railsウォッチ(20161019)ObjectSpaceモジュール活用法、Capybara統合、コミッターを撮影するソフト
- 週刊Railsウォッチ(20161012)RubyのHashの詳細、RethinkDBの会社が終業ほか
- 週刊Railsウォッチ(20161005)Mac OS SierraとRubyの問題、Learning Gitほか
- 週刊Railsウォッチ(20160928)constantizeの注意点、GoのGUI “gallium”登場ほか
- 週刊Railsウォッチ(20160921)クールなHTMLエディタ「Mozilla Thimble」他
- 週刊Railsウォッチ(20160913)MySQLの脆弱性ほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。