RailsでネストされたリレーションのN+1の解決方法
ranking.article.authorみたいなときの話。
N+1はincludesつけて回避するのがふつう。
http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
で、タイトルのケースも↑のリンクに書いてあるんだけど、こんな感じに書く。
続きを読むCircleCIでMySQL5.6を使う方法
追記)コメントで教えてもらったけど、今は設定でubuntuのバージョンが変更でき、そこではMySQL5.6などがプリインストールされるので、もうこの記事読まなくていいです。
Ubuntu 14.04 (Trusty) - CircleCI
ただ、1つ言いたいのは、「使えるようになったら連絡するよ!」ってサポートは言ってたけど、それはウソだったということである。CircleCIまだ安いとは思えないし、もっと競合にはがんばってもらいたい。追記終わり
前回、CircleCIでMySQL5.6が使えなくて困った、というエントリを書いた。
http://d.hatena.ne.jp/ria10/20150215/1424006550
で、CircleCIに問い合わせてたんだけど、返事がきて一応は解決したのでその内容のメモ。
続きを読むRailsでCircleCIがMySQL5.6をサポートしていないので苦労した話
かつて日記に書いたんだけど、MySQL5.6から導入されたinnodbのfull text indexは割と便利。
http://d.hatena.ne.jp/ria10/20140107/1389071672
が、innodbのfull-text indexを利用した機能があるRailsアプリをCircleCIでテストしようとすると絶対にコケる。
なぜなら、CircleCIでサポートされているMySQLは5.5だから。
https://circleci.com/docs/environment#databases
こんなときにどうしたか、という話。
続きを読むrubyでループを1から始める
10.times do |i| p i + 1 end
のi + 1が可読性悪いというときの話。
で、
(1..10).each do |i| p i end
こんな感じで書ける。
さらに・・・
1.upto 10 do |i| p i end
こっちはrubyっぽいけど、実際コードの中にふっとでてくると、以外に頭に入ってこない(個人差かも)。
ちなみにuptoがあるんだから、downtoもあるでよ。
※(10..1).each はできない。
追記)
each_with_indexはどうするか。
each_with_indexはoffsetを取れる。
each_with_index(1)とすれば、i + 1を撲滅できる。
each.with_indexとすればoffsetが取れる。
each.with_index(1)で、i+1を撲滅できる。
RailsのValidationで必要なエラーがだけを出すチョイワザ
こんなバリデーションを入れているとする。
validates :login_id, presence: true, uniqueness: { case_sensitive: false }, length: { in: MIN_LENGTH_LOGIN_ID..MAX_LENGTH_LOGIN_ID }, format: { with: /\A\w+\z/i }
これだと、未入力でバリデーションにかかると、
- ログインIDを入力してください!
- ログインIDは4文字以上です!
- ログインIDは不正な値です!
とか畳み込まれる。
せめて、入力してから出そうと思ったものは2行に分けて、入力があったときだけバリデーションするとよい。
validates :login_id, presence: true, uniqueness: { case_sensitive: false }, length: { in: MIN_LENGTH_LOGIN_ID..MAX_LENGTH_LOGIN_ID } validates :login_id, format: { with: /\A\w+\z/i }, if: ->(u) { u.login_id.present? }
が、あまりこの書き方は好きではない。
どうしたらいいのや。
Railsでstructure.sqlがやたらコンフリクトするとき
config.active_record.schema_format = :sqlにしたとき、DBがMySQLだと(そうでない場合もなるかもだけど)db:migrate:resetしたりすると、dumpのタイミングでタイムスタンプがずれるのでこんな感じの残念な差分が生まれる。
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2015-01-05 12:17:15
+-- Dump completed on 2015-01-06 10:47:36
INSERT INTO schema_migrations (version) VALUES ('20140902084054');
INSERT INTO schema_migrations (version) VALUES ('20140903074012');
これをイチイチ手作業で対応するのはやってらんないし、この情報が重要だともあまり思えなかった(gitの履歴を追えばだいたいわかるし)ので、dumpのタイミングで消してしまうことにした。
具体的には以下の処理を書いた。
lib/tasks/dump.rake
namespace :db do namespace :structure do task :dump do path = Rails.root.join('db', 'structure.sql') sql = File.open(path).read.gsub(/^-- Dump completed on.*\n/, '').gsub(/-- Server version.*\n/, '') File.open(path, 'wb') {|f| f.puts sql } end end end
この例ではServer versionも消している。マイナーバージョンとか開発者によって微妙に違ったりするのでこれも消した(バージョンを合わせたほうがいいとは思うけど)