- Ruby / Rails関連
READ MORE
こんにちは、hachi8833です。
「HackerNewsのランキングアルゴリズムをリバース・エンジニアリングした記事がHackerNewsから削除されたという記事」が昨日までHackerNewsでトップでした。ややこしいですね。
IPAが自ら脆弱性を報告した無料ゲーム「安全なウェブサイト運営入門」は書籍の名前かと思ってしまいました。
それでは今週もいってみましょう。
(Amazon.co.jpにはエントリがないので同サイトの書影をリンク付きで引用しました)
元記事は「私はいかにしてRails本で7万ドル稼いだか」的な記事ですが、その書籍の方をピックアップしました。読んでみないと何とも言えませんが、よさそうです。
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をそれ以上いじるのは避けたい気がしました。
Improvementに分類されてましたが、バグ修正ですね。修正もごくわずかでした。
Migrator.schema_migrations_table_name
を非推奨化(Rails公式より)SchemaMigrationモデルが切り出されたことによる変更です。変更自体はアプリ開発者には直接関連しませんが、schema_migrationsという名前のテーブルが話題になりました。
今さらですが、Railsのデータベースにはschema_migrationsテーブルがあり、versionカラムにはそれまでマイグレーションに使ったファイル(db/migrate/以下)のバージョン番号がすべて保存されています。
マイグレーションが思うようにいかなくて、思い余ってマイグレーションファイルのバージョン番号を変更してしまう人がいるらしいのですが、「schema_migrationsテーブルの一貫性が損なわれるから絶対やめた方がいいよ」という話を聞きました。
マイグレーションには恥ずかしい履歴が残りがちなので、気持ちはわかります。
改修箇所はわずかでしたが、見終わってから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
を実行できるのですが、「何が起きるかわからないからコマンドはプロジェクトのルートディレクトリでしか実行しない」という意見がありました。私も同感です。
asset_url
が不完全だった(’https://’が含まれないことがあった)問題の修正です。
#28250ではやや緊張感のあるやりとりが繰り広げられていました。こんな写真が貼られてたり。もちろんお茶目でやっていると思います。
最終的にPRのrebaseに手違いが見つかり、それを修正して無事commitされました。
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探訪シリーズ「[Rails5] Active Support::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"
これもkamipoさんによる修正で、PostgreSQLのみが対象です。kamipoさんのコミットが膨大なので、昨年既に七福神入りしていたんですね。いつもありがとうございます?
Rails 5.0 七福神入りしてた? https://t.co/RGojsyxUrM
— Ryuta Kamizono (@kamipo) 2016年7月1日
#attr_reader
で初期化を簡潔に書く、ブロックをprocオブジェクトに置き換えるなどの方法などが紹介されています。追記に、Ruby 2.3ではprivate
での#attr_reader
警告が表示されなくなったということについても触れられています(#10967 Is “warning: private attribute?” wrong?)。それほど短い記事ではありませんが、込み入ってはいないので読んでおくとよさそうです。
ある程度複雑な初期化を楽に書くgemとして、morimorihogeさんが以下の2つを教えてくれました。
週刊Railsウォッチ(20170217)でマサカリが大量に飛んできた「Testing Ruby’s Unicode Support」記事のリベンジです。
Frankly, I was a bit fuzzy on Unicode normalization.
一転してUnicode正規化を熱心に調べています。短くもよくまとまった良記事です。後でじっくり読んでみます。
「RubyやRailsのコミュニティがUnicode正規化に思ったほど関心を寄せていないのに少しだけ驚いた」としめくくっています。ASCIIだけで事足りる英語圏ではある程度仕方がないかなとも思いますが、私としては、絵文字のおかげで近年こうした問題に以前よりも関心が高まっているような気はしています。
長いです。最適化の主題となっているsigprocmaskって何だろうと思って一同で検索したところ、プロセスが応答するシグナルを変更するシステムコールでした。
ただ、新しい記事にもかかわらず、使っているのがRuby 1.8なので現在のRuby 2.x VMには符合しなさそうです。
以下は、同記事の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であることを今さら知りました。
表計算を何とかするgemです。
OAuth認証と組み合わせることで、RubyからGoogleスプレッドシートにアクセスして読み取りや更新を行えます。記事やリポジトリには記載されていませんが、Railsでも使えると思います。スプレッドシートを正しく運用できるのであれば、案件によっては合うかもしれません。
この種のgemを導入するときは、頻繁に更新されている(=放置されていない)ものを選ぶのが重要ですね。機会があれば使ってみたいですが、データをシートから取ってくるだけにしておきたいと思いました。
Rubyはオープンクラスなのでモンキーパッチを簡単に当てられますが、よく切れるナイフと同様、自分の身を傷つけないように注意が必要と説いています。
require
するのを忘れると、パッチではなくクラスの再定義になってしまうmorimorihogeさんが、趣旨の近い記事としてクックパッド開発者ブログ「Ruby on Rails アプリケーションにおけるモンキーパッチの当て方」を挙げました。
RubyFlowのリンクが壊れていたので、直接元記事にリンクしました。
タイトルと本文の量がほぼ同じぐらいですね。リンクはしませんが、About Usを見るとインドのアフマダーバードの会社でした。
「〜する理由」記事が続きます。EuRuKoはヨーロッパで開催される大きなRubyセッションです。2016年度はブルガリアのソフィアでの開催、そして今年は9月にハンガリーの首都ブダペストでの開催となります。
Matzももちろんキーノートスピーチを担当しますし、昨年はLTやCoding Golfも大いに盛り上がったそうです。
morimorihogeさんによると「会場が空港や駅から遠い」「宿がスムーズに取れない」「会場の周辺に居酒屋などがまったくない」カンファレンスはやっぱりつらいそうです。
日本であれば多少不便でも旅情を味わえたりしますが、海外(特にヨーロッパ)だと都市部であってもコンビニが少なかったりレストランも土日閉まってたりすることが多いので、参加にあたってはそのあたりをチェックしたいですね。
今週は以上です。
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。