Associationを試す...!(多:多)
58895 ワード
多対多
よくわからないので一個づつ migrate を試していく
MySQLだけまっさらな状態に戻して、migrateは流用するので、 rails db:migrate VERSION=... で一個づつ指定して確認していきます。
1対多 を改めて 1Step づつ ERD していく
最初の user table だけの時。
class CreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
- 上記を rails db:migrate した後の erd
post を追加してみる
class CreatePosts < ActiveRecord::Migration[7.0]
def change
create_table :posts do |t|
t.text :content
t.references :user, null: false, foreign_key: true
t.timestamps
end
add_index :posts, [:user_id, :created_at]
end
end
-
上記を rails db:migrate した後の erd
- か、変わらんっ...!
- か、変わらんっ...!
-
ので、 model にそれぞれ追加
class User < ApplicationRecord
has_many :posts
end
class Post < ApplicationRecord
belongs_to :user
end
- あらたえめて erd
- model に入れないとだめぽそ
- migrate の時の references でよろしくやってくれるんだと思ってたよ...。
- migrate した時には model ファイルがなかったので、その為かもしれないけど()
多対多 に続く...。
現状 user table と post table でリレーションを作ってる状態。
これに group table を追加して、下記を実現できるようにしてみる。
- 1つのグループに複数のユーザが所属できる
- 1人のユーザは複数のグループに所属できる
group table の migrate
class CreateGroups < ActiveRecord::Migration[7.0]
def change
create_table :groups do |t|
t.string :name
t.timestamps
end
end
end
class Group < ApplicationRecord
end
- 上記を rails db:migrate した後の erd
- group table が生えた
- group table が生えた
中間テーブルを作る
- なんだか昔は user と group の中間であれば user_group table 的な感じだったようだ
- そもそも中間テーブルの命名考えるの苦手ですし... って、思いたい気持ちはある
class CreateGroupMembers < ActiveRecord::Migration[7.0]
def change
create_table :group_members do |t|
t.references :user, null: false, foreign_key: true
t.references :group,null: false, foreign_key: true
t.timestamps
end
add_index :group_members, [:user_id, :group_id], unique: true
end
end
-
上記を rails db:migrate した後の erd
- groupMember table が生えた
- groupMember table が生えた
-
Model user , group に手を入れる
class User < ApplicationRecord
has_many :posts
has_many :group_members, class_name: "GroupMember",
foreign_key: "user_id"
end
class Group < ApplicationRecord
has_many :group_members, class_name: "GroupMember",
foreign_key: "group_id"
end
- 改めて erd した。
- 画像が N:N に見えない不思議
- 画像が N:N に見えない不思議
ここまでに作った table に rails c でアレコレしてみる。
一旦 データを作成
- User 作成
- 気持ちは Web で新規ユーザ作成した気持ちで
pry(main)> User.create(name: "nyasu", email: "[email protected]")
pry(main)> User.create(name: "nya", email: "[email protected]")
pry(main)> User.all
User Load (4.7ms) SELECT `users`.* FROM `users`
=> [#<User:0x000000010990f240 id: 1, name: "nyasu", email: "[email protected]", created_at: Wed, 13 Apr 2022 13:37:03.816365000 UTC +00:00, updated_at: Wed, 13 Apr 2022 13:37:03.816365000 UTC +00:00>,
#<User:0x000000010990f178 id: 2, name: "nya", email: "[email protected]", created_at: Wed, 13 Apr 2022 13:37:12.864565000 UTC +00:00, updated_at: Wed, 13 Apr 2022 13:37:12.864565000 UTC +00:00>]
- Group 作成
- 気持ちは Web で新規に作成したユーザがグループも作成した気持ちで
- こういう時に適当に入力する内容でセンスって分かりますよね()
pry(main)> Group.create(name: "nyanyanya")
pry(main)> Group.all
Group Load (4.1ms) SELECT `groups`.* FROM `groups`
=> [#<Group:0x0000000109a3dc48 id: 1, name: "nyanyanya", created_at: Wed, 13 Apr 2022 13:40:02.670938000 UTC +00:00, updated_at: Wed, 13 Apr 2022 13:40:02.670938000 UTC +00:00>]
-
と、別々に関連なくそれぞれができてしまう...。
-
model 改変
class User < ApplicationRecord
has_many :posts
has_many :group_members, foreign_key: "user_id"
has_many :groups, through: :group_members, source: :group
end
class Group < ApplicationRecord
has_many :group_members, foreign_key: "group_id"
has_many :users, through: :group_members, source: :user
end
class GroupMember < ApplicationRecord
belongs_to :user
belongs_to :group
end
- rails c で改めて。
pry(main)> user = User.find(1)
User Load (1.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User:0x000000010f191558 id: 1, name: "nyasu", email: "[email protected]", created_at: Wed, 13 Apr 2022 13:37:03.816365000 UTC +00:00, updated_at: Wed, 13 Apr 2022 13:37:03.816365000 UTC +00:00>
user 経由で group を作成する
pry(main)> user.groups.create(name: "nya-n")
TRANSACTION (2.8ms) BEGIN
Group Create (2.8ms) INSERT INTO `groups` (`name`, `created_at`, `updated_at`) VALUES ('nya-n', '2022-04-13 14:18:09.867220', '2022-04-13 14:18:09.867220')
User Load (3.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
GroupMember Create (2.7ms) INSERT INTO `group_members` (`user_id`, `group_id`, `created_at`, `updated_at`) VALUES (1, 2, '2022-04-13 14:18:09.894603', '2022-04-13 14:18:09.894603')
TRANSACTION (4.2ms) COMMIT
=> #<Group:0x000000010fb1eeb8 id: 2, name: "nya-n", created_at: Wed, 13 Apr 2022 14:18:09.867220000 UTC +00:00, updated_at: Wed, 13 Apr 2022 14:18:09.867220000 UTC +00:00>
MySQL を確認
- 中感テーブルにもデータが入ってる
mysql> select * from users;
+----+-------+-------------------+----------------------------+----------------------------+
| id | name | email | created_at | updated_at |
+----+-------+-------------------+----------------------------+----------------------------+
| 1 | nyasu | nyasu@example.com | 2022-04-13 13:37:03.816365 | 2022-04-13 13:37:03.816365 |
| 2 | nya | nya@example.com | 2022-04-13 13:37:12.864565 | 2022-04-13 13:37:12.864565 |
+----+-------+-------------------+----------------------------+----------------------------+
2 rows in set (0.01 sec)
mysql> select * from groups;
+----+-----------+----------------------------+----------------------------+
| id | name | created_at | updated_at |
+----+-----------+----------------------------+----------------------------+
| 1 | nyanyanya | 2022-04-13 13:40:02.670938 | 2022-04-13 13:40:02.670938 |
| 2 | nya-n | 2022-04-13 14:18:09.867220 | 2022-04-13 14:18:09.867220 |
+----+-----------+----------------------------+----------------------------+
2 rows in set (0.01 sec)
mysql> select * from group_members;
+----+---------+----------+----------------------------+----------------------------+
| id | user_id | group_id | created_at | updated_at |
+----+---------+----------+----------------------------+----------------------------+
| 1 | 1 | 2 | 2022-04-13 14:18:09.894603 | 2022-04-13 14:18:09.894603 |
+----+---------+----------+----------------------------+----------------------------+
1 row in set (0.00 sec)
mysql>
rails c で確認( group 視点 )
pry(main)> group = Group.find(2)
Group Load (4.4ms) SELECT `groups`.* FROM `groups` WHERE `groups`.`id` = 2 LIMIT 1
=> #<Group:0x000000010fa178a8 id: 2, name: "nya-n", created_at: Wed, 13 Apr 2022 14:18:09.867220000 UTC +00:00, updated_at: Wed, 13 Apr 2022 14:18:09.867220000 UTC +00:00>
- nya-n group に所属している users を問い合わせると、現在所属している nyasu を取得できる
pry(main)> group.users
User Load (3.6ms) SELECT `users`.* FROM `users` INNER JOIN `group_members` ON `users`.`id` = `group_members`.`user_id` WHERE `group_members`.`group_id` = 2
=> [#<User:0x000000010f7bebd8 id: 1, name: "nyasu", email: "[email protected]", created_at: Wed, 13 Apr 2022 13:37:03.816365000 UTC +00:00, updated_at: Wed, 13 Apr 2022 13:37:03.816365000 UTC +00:00>]
nyasu があらたに groupB を立ち上げた...!
pry(main)> user.groups.create(name: "groupB")
TRANSACTION (3.9ms) BEGIN
Group Create (3.0ms) INSERT INTO `groups` (`name`, `created_at`, `updated_at`) VALUES ('groupB', '2022-04-13 14:27:04.309306', '2022-04-13 14:27:04.309306')
User Load (3.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
GroupMember Create (3.2ms) INSERT INTO `group_members` (`user_id`, `group_id`, `created_at`, `updated_at`) VALUES (1, 3, '2022-04-13 14:27:04.325420', '2022-04-13 14:27:04.325420')
TRANSACTION (6.8ms) COMMIT
=> #<Group:0x000000010f766078 id: 3, name: "groupB", created_at: Wed, 13 Apr 2022 14:27:04.309306000 UTC +00:00, updated_at: Wed, 13 Apr 2022 14:27:04.309306000 UTC +00:00>
nyasu が自分が所属する group 一覧を問い合わせた...!
pry(main)> user.groups
Group Load (5.0ms) SELECT `groups`.* FROM `groups` INNER JOIN `group_members` ON `groups`.`id` = `group_members`.`group_id` WHERE `group_members`.`user_id` = 1
=> [#<Group:0x000000010fb1eeb8 id: 2, name: "nya-n", created_at: Wed, 13 Apr 2022 14:18:09.867220000 UTC +00:00, updated_at: Wed, 13 Apr 2022 14:18:09.867220000 UTC +00:00>,
#<Group:0x000000010f766078 id: 3, name: "groupB", created_at: Wed, 13 Apr 2022 14:27:04.309306000 UTC +00:00, updated_at: Wed, 13 Apr 2022 14:27:04.309306000 UTC +00:00>]
groupB に新たなメンバ nya が増えた...!
pry(main)> user = User.find_by(name: "nya")
pry(main)> group = Group.find_by(name: "groupB")
pry(main)> GroupMember.create(user_id: user.id, group_id: group.id)
TRANSACTION (4.9ms) BEGIN
User Load (4.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
Group Load (3.3ms) SELECT `groups`.* FROM `groups` WHERE `groups`.`id` = 3 LIMIT 1
GroupMember Create (3.2ms) INSERT INTO `group_members` (`user_id`, `group_id`, `created_at`, `updated_at`) VALUES (2, 3, '2022-04-14 12:39:22.344590', '2022-04-14 12:39:22.344590')
TRANSACTION (6.0ms) COMMIT
=> #<GroupMember:0x0000000110518810 id: 5, user_id: 2, group_id: 3, created_at: Thu, 14 Apr 2022 12:39:22.344590000 UTC +00:00, updated_at: Thu, 14 Apr 2022 12:39:22.344590000 UTC +00:00>
pry(main)>
- 所属しているっ...!
pry(main)> user.groups
Group Load (4.0ms) SELECT `groups`.* FROM `groups` INNER JOIN `group_members` ON `groups`.`id` = `group_members`.`group_id` WHERE `group_members`.`user_id` = 2
=> [#<Group:0x000000010ec856b8 id: 3, name: "groupB", created_at: Wed, 13 Apr 2022 14:27:04.309306000 UTC +00:00, updated_at: Wed, 13 Apr 2022 14:27:04.309306000 UTC +00:00>]
pry(main)>
しかし、即辞めた...
pry(main)> GroupMember.find_by(user_id: user.id, group_id: group.id).destroy
GroupMember Load (4.5ms) SELECT `group_members`.* FROM `group_members` WHERE `group_members`.`user_id` = 2 AND `group_members`.`group_id` = 3 LIMIT 1
TRANSACTION (2.9ms) BEGIN
GroupMember Destroy (4.7ms) DELETE FROM `group_members` WHERE `group_members`.`id` = 5
TRANSACTION (6.8ms) COMMIT
=> #<GroupMember:0x000000010fda8bc0 id: 5, user_id: 2, group_id: 3, created_at: Thu, 14 Apr 2022 12:39:22.344590000 UTC +00:00, updated_at: Thu, 14 Apr 2022 12:39:22.344590000 UTC +00:00>
pry(main)>
- nya は1人になった
pry(main)> user = User.find_by(name: "nya")
User Load (4.6ms) SELECT `users`.* FROM `users` WHERE `users`.`name` = 'nya' LIMIT 1
=> #<User:0x000000010fb12460 id: 2, name: "nya", email: "[email protected]", created_at: Wed, 13 Apr 2022 13:37:12.864565000 UTC +00:00, updated_at: Wed, 13 Apr 2022 13:37:12.864565000 UTC +00:00>
pry(main)> user.groups
Group Load (4.1ms) SELECT `groups`.* FROM `groups` INNER JOIN `group_members` ON `groups`.`id` = `group_members`.`group_id` WHERE `group_members`.`user_id` = 2
=> []
pry(main)>
Author And Source
この問題について(Associationを試す...!(多:多)), 我々は、より多くの情報をここで見つけました https://zenn.dev/strsbn/articles/f9605da88893dd著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol