RailsのINSERT INTOがnewとかcreateでリレーションで躓いたこと
UPDATEとパスワードのハッシュ化についての問題が片付いたので、次は初期の登録をかっちりできるようにとRailsでSQLのINSERT文に相当するものに手を付けた。
・・・のだが、これもどうしてまたなかなかクセのあるシロモノだった。
UPDATEとかはまんまupdateなのだが、Ruby on RailsでのINSERT INTOってnewなのよね。(RailsというかActiveRecordのメソッド)
SQLだと一般的にUPDATE文だろうがINSERT文だろうが走らせたときにもCOMMIT入れなきゃいかん。
update_allはUPDATEと同時にCOMMITもやってくれるので、INSERT INTOを行うだけにCOMMITに相当するsaveを入れるのものなぁ~とか思って調べてたら、こんな書き方もできるようだった。
user = User.create(:user_id => 【ユーザーID】)
update_allに書き方を合わせてsaveを入れたくないので、INSERT文の発行と同時にCOMMITも行ってくれるcreateメソッド。
そうそう、これこれ。こういうのがいいんだよ。
で、これに関してはまぁどこにでも書いてあるので難はなかったんだけど問題はその次。
上記の例だとUserのモデルを持っているんだが、実はこのUserのモデルは、実際は「Profile」というモデルへ、テーブルをリレーションさせている。(もとい、子テーブル的にね)
モデルのリレーションについてはこれもまたこないだ書いたところだけど、以下のような感じで書いている。
UserのModel(usersテーブル):
class User < ApplicationRecord self.primary_key = 'user_id' has_many :profiles, :class_name => :Profile, :foreign_key => 'user_id' end
ProfileのModel(profilesテーブル):
class Profile < ApplicationRecord self.primary_key = 'user_id' belongs_to :users, :class_name => :User, :foreign_key => 'user_id' end
Model同士はこれできちんとつながっているわけだ。
で、普通にusersのレコード挿入に付随して、SQLと同じ感覚で以下のようにやったところ、
profile = Profile.create(:user_id => 【ユーザーID】, :lname => 【姓】, :fname => 【名】)
なーんということでしょう・・・レコードが挿入されません(´・ω・`)
リファレンスサイトはあまり信用できないのでGithubで調べてみたら、「Model同士にリレーションの設定を入れていると単独でレコードを挿入できないよ!」的な英語の一文を発見。
確かにリレーションがModelに明示化されている以上、これは合理的だ。
多分、親テーブルに不在のレコードを子テーブルへ挿入することを防いで、テーブル間の整合性を取るためなんだろうな、これ。
でも、こんなところで縛らないで欲しいわぁ、とリアルにぼやいた。
だって、SQLだったらテーブルそれぞれ単独でINSERT INTOできるじゃん!(こっちはリレーションシップ明示化されてないけど)
まぁそんなことを言ってもしょうがない。
なので、この外国人?さんに感謝して指定通りに以下のようにしてみた。
user = User.create(:user_id => 【ユーザーID】) profile = Profile.new(:user_id => 【ユーザーID】, :lname => 【姓】, :fname => 【名】) user.profile << profile
これで、無事に親子のテーブルへレコードがINSERTされた。
なるほどなー。モデルのオブジェクトを継承してるのな、これ。
そして、一番下でやってることがCOMMIT臭くてイヤだったので、下記のように変更。(上記は以下の書き方でも行けるみたい)
user = User.create(:user_id => 【ユーザーID】) profile = user.profile.create(:user_id => 【ユーザーID】, :lname => 【姓】, :fname => 【名】)
キックストライク!サイコー!!すっきりした感じで書けて好感触。
とりあえず、これで躓いたところについては解決できた。
RailsでSQLで言うところのINSERT INTOはnewかcreate、そして、リレーションさせているテーブルは単独ではINSERTできないこと。
それが今回の教訓だ。
・・・まぁ、これ以前にモデル関係でちょっと一悶着あったんだけど、それは続けさまに投稿することにする。