CarrierWaveを利用したModelの挙動について
幅を広げるのにRoRを勉強し直すのに簡単なアプリを作ってみたらはまったので、メモ。
・とりあえず
プロフィール的なページを構成するのに、メインとなるプロフィールテーブルとhas_oneで2つ別テーブルを関連づけしてました。画像は特定のディレクトリに保存する形をとって、ファイル名をプロフィールテーブルに保存をしようとした。
・そのまえに
RoRのhas_oneで更新をかけると、子テーブルのほうに続々と不要レコードがたまってきたので更新のタイミングで直前のレコードを削除するように、プロフィールモデルをいじってました。
ざっくり)after_initialize時に子テーブルのidを取得→after_commit時に削除
ネットで調べるとhas_manyであれば別の方法があるっぽいけど、うまく動作しなかったのでこうしました。
参考:
has_many側の不要なやつはdeleteして更新したい - Oh! My! Enter! 〜バッチを起動しようと勢いよくキーを叩いたら、それはシフトキーだった〜
・本題
プロフィール編集フォームにて、画像以外の項目で編集しても問題なかったのに画像をアップロードしようとするとエラーが出た。原因は上記のinitialize時のid取得でエラーが出ていたが、画像の有無で挙動が変わっていた。
・結果?
とりあえず「mount_uploader :image, ImageUploader」としたカラムを更新する時は再度initializeが発生する。(おそらく新しくインスタンスを生成しているのではと思う
なお、SQLの実行内容をみていると次のようになっていた。
# 画像無し Started PATCH "/my_page" for 127.0.0.1 at 2016-08-22 02:48:31 +0000 Processing by UserProfilesController#update as HTML Parameters: {"utf8"=>"✓", -略- "commit"=>"Update User profile"} UserProfile Load (0.2ms) SELECT -略- LIMIT 1 # ここらへんでafter_initialize動作しているっぽい UseService Load (0.2ms) SELECT -略- LIMIT 1 # has_oneその1 UseLang Load (0.3ms) SELECT -略- LIMIT 1 # has_oneその2 # ここらへんでafter_initializeが終わっているぽい BEGIN SQL (0.3ms) has_oneその1をアップデート(ここで古い情報がゴミレコードになる SQL (0.2ms) has_oneその2をアップデート(ここで古い情報がゴミレコードになる UserProfile Exists (0.2ms) 親テーブルの重複チェック? UserProfile Exists (0.2ms) 親テーブルの重複チェック? SQL (0.2ms) UPDATE 親テーブルのUserProfileで画像以外のカラムを編集 SQL (0.2ms) INSERT has_oneその1に更新情報を格納 SQL (0.2ms) INSERT has_oneその2に更新情報を格納 COMMIT # after_commitが動作 UseService Load (0.2ms) SELECT has_oneその1の古い情報を取得 BEGIN SQL (0.3ms) DELETE has_oneその1の古い情報を削除 COMMIT UseLang Load (0.2ms) SELECT has_oneその2の古い情報を取得 BEGIN SQL (0.3ms) DELETE has_oneその2の古い情報を削除 COMMIT # after_commitが終了 Redirected to http://++++ Completed 302 Found in 29ms (ActiveRecord: 9.8ms)
# 画像有り Started PATCH "/profile" for 127.0.0.1 at 2016-08-22 02:49:29 +0000 Processing by UserProfilesController#update as HTML Parameters: {"utf8"=>"✓", -略- "commit"=>"Update User profile"} UserProfile Load (0.2ms) SELECT -略- LIMIT 1 # ここらへんでafter_initialize動作しているっぽい UseService Load (0.2ms) SELECT -略- LIMIT 1 # has_oneその1 UseLang Load (0.3ms) SELECT -略- LIMIT 1 # has_oneその2 # ここらへんでafter_initializeが終わっているぽい BEGIN SQL (0.3ms) has_oneその1をアップデート(ここで古い情報がゴミレコードになる SQL (0.2ms) has_oneその2をアップデート(ここで古い情報がゴミレコードになる UserProfile Exists (0.2ms) 親テーブルの重複チェック? UserProfile Exists (0.2ms) 親テーブルの重複チェック? UserProfile Load (0.2ms) SELECT -略- LIMIT 1 # ここで再びafter_initializeが動作している? UseService Load (0.2ms) SELECT -略- LIMIT 1 # この時点ではuse_serviceはnil UseLang Load (0.2ms) SELECT -略- LIMIT 1 # この時点ではuse_langはnil # ここで再び動作していたafter_initializeが終わっている? SQL (0.2ms) UPDATE 親テーブルのUserProfileに画像ファイルのファイル名を格納 SQL (0.2ms) INSERT has_oneその1に更新情報を格納 SQL (0.2ms) INSERT has_oneその2に更新情報を格納 COMMIT # after_commitが動作 UseService Load (0.2ms) SELECT has_oneその1の古い情報を取得 BEGIN SQL (0.3ms) DELETE has_oneその1の古い情報を削除 COMMIT UseLang Load (0.2ms) SELECT has_oneその2の古い情報を取得 BEGIN SQL (0.3ms) DELETE has_oneその2の古い情報を削除 COMMIT # after_commitが終了 Redirected to http://++++ Completed 302 Found in 40ms (ActiveRecord: 10.5ms)
パーフェクトRoR買おうかな。。。