2016-01-06

詰まったことリスト

最近、業務でRailsアプリケーション開発をしている。 が!Railsに限らずだが何かと行き詰まってばかりなので忘れないうちにこの怒りと苦しみの元となったネタどもをリストアップしておきたいと思う。

※ ほとんど単なる調査不足・知識不足が原因だと思います

ActiveRecord関連

① パフォーマンス改善のため、User.where(type:1)のようにして取得したUserオブジェクトを1SQLでまとめて削除したかった。eachで回してそれぞれdestroyとかするとオブジェクトの数だけSQLが実行されてしまう。そこで、delete_allメソッドを使おうとしたけど、delete_allだとUserモデルの関連先オブジェクトまで削除できず要件を満たせなかったので断念した。次なる策は特にない。

# controller
users = User.where(type: 1)
User.bulk_destroy(users)

# model
def self.bulk_destroy(users)
  transaction do
    users.each(&:destroy!) # これだとusersの数だけSQLが実行される
  end
end

#
# ↓ delete_allを使おう!
#

# controller
User.where(type: 1).delete_all # これだとUserと関連しているモデルまで同時に削除できなかった

② 上記と同じように、Userの登録処理も一括で行いたかった。そこで、activerecord-importというGemを使えばできるよ!という情報を得たが、同じく関連先のテーブルまで同時に更新することはできなかった

③ 更新処理も同じく、update_allを使う方法にたどり着くものの同様の理由で断念

一括操作系REST APIの設計

RESTな一括操作系APIを作ろうとしたところ、設計で色々行き詰まった。一括操作とは、1リクエストで複数のレコードが操作されることを指す。

① 複数のリソースをRESTで指し示す良い方法がわからなかった。そもそも複数のリソースを示そうとしている時点で間違い?
どうしたか:検索系APIのように、クエリパラメータを使って対象のリソースを指定することにした

# typeが1のUserのstatusを1に更新する
PUT /users?type=1

{
  "users": {
    "status": 1
  }
}

② PUTやDELETEでクエリパラメータを使うことになったけど、これって良いんだっけ?
どうしたか:気にしつつも使った

③ DELETEでリクエストボディ使ってるけど、これも良いんだっけ?
どうしたか:調べた感じ、推奨されないけどRFC上禁止されてるわけでもないようだったので使った。

④ StrongParameterで配列型受け取りたいときってどうすれば良いの?
どうしたか:ググったら出てきたのでそれを真似した。しかしだいぶレール踏み外した感じ。

SQL系

① INSERTをしてAUTO INCREMENTで自動採番されたIDを使って、特定のカラムを更新する処理が書かれていた。こいつはパフォーマンス劣化の原因になるし、少々不吉な匂いがしたので取り除きたかった
どうしたか:がっつり改修する以外に策はない!!!!1

user = User.new(name: 'xxx', type: 1, stauts: 0)
user.save && user.update(original_id: "hoge-#{user.id}")

microservices

① 今流行のマイクロサービス的な何か。綺麗に分離できていないせいか、コンポーネント間で複雑なトランザクション処理を実装しなければならなかった。
どうしたか:WebAPIに柔軟性を持たせた。1リクエストで多くのリソースを処理できるインターフェースを持たせた。これによってトランザクション処理がいくらかやりやすくなった。

Rubocop

① メソッド10行制限キツすぎワロタ
どうしたか:がんばった

② ABC size制限厳しすぎワロタ
どうしたか:がんばった

RSpec

① 文法複雑すぎでは(sharedうんたらとかletとか星の数ほどありそうなマッチャーとか)
どうしたか:書きまくってたら慣れた。

まとめ

引き続きがんばります。