belongs_toとhas_oneの違い (Rails)

August 25, 2022

確認環境

$ bundle exec ruby --version
ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-darwin19]
$ bundle exec rails --version
Rails 6.0.4.6

事前準備

モデル作成

$ rails g model SampleUser name:string
$ rails g model SampleUserAddress sample_user_id:integer city:string

migrate

$ rake db:migrate

リレーションを作成

app/models/sample_user.rb

class SampleUser < ApplicationRecord
  has_one :sample_user_address
end

app/models/sample_user_address.rb

class SampleUserAddress < ApplicationRecord
  belongs_to :sample_user
end

データ準備

$ rails c
...
irb(main):007:0> SampleUser.create!(id: 1, name: 'hoge')
irb(main):008:0> SampleUserAddress.create!(sample_user_id: s.id, city: 'Tokyo')

参照してみる

has_one

SampleUser -> SampleUserAddress

$ rails c
...
irb(main):024:0> s = SampleUser.last
  SampleUser Load (0.1ms)  SELECT "sample_users".* FROM "sample_users" ORDER BY "sample_users"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> #<SampleUser id: 1, name: "hoge", created_at: "2022-08-24 15:34:58", updated_at: "2022-08-24 15:34:58">
irb(main):025:0> s.sample_user_address
  SampleUserAddress Load (0.2ms)  SELECT "sample_user_addresses".* FROM "sample_user_addresses" WHERE "sample_user_addresses"."sample_user_id" = ? LIMIT ?  [["sample_user_id", 1], ["LIMIT", 1]]
=> #<SampleUserAddress id: 1, sample_user_id: 1, city: "Tokyo", created_at: "2022-08-24 15:41:10", updated_at: "2022-08-24 15:41:10">

belongs_to

SampleUserAddress -> SampleUser

SampleUserAddress は sample_user_id を持っています。

$ rails c
...
irb(main):005:0> sua = SampleUserAddress.last
   (0.1ms)  SELECT sqlite_version(*)
  SampleUserAddress Load (0.1ms)  SELECT "sample_user_addresses".* FROM "sample_user_addresses" ORDER BY "sample_user_addresses"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> #<SampleUserAddress id: 1, sample_user_id: 1, city: "Tokyo", created_at: "2022-08-24 15:41:10", updated_at: "2022-08-24 15:41:10">
irb(main):006:0> sua.sample_user
  SampleUser Load (0.1ms)  SELECT "sample_users".* FROM "sample_users" WHERE "sample_users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<SampleUser id: 1, name: "hoge", created_at: "2022-08-24 15:34:58", updated_at: "2022-08-24 15:34:58">

おわりに

今回はデータの参照だけでしたが、データ登録時に妥当なデータを入れたい場合、

データベースでの外部キーの指定などする必要があると思われます。


SHARE

Profile picture

Written by tamesuu