N7. N:N관계
2020. 7. 5. 16:46ㆍRails 5 on aws c9
1:N 이 가장 많이 쓰이는 관계이다
N:N관계도 있다. 이는 게시물과 #해시태그의 관계가 있을 수 있다
하나의 게시물은 여러개의 해시태그를 가질 수 있고
해시태그는 여러 게시물을 가질 수 있다.
게시물의 좋아요도 그렇게 구현할 수 있다.
User ← 1:N → Like ← N:1 → Post
두개의 태이블을 Join하면 N:N을 얻을 수 있다. (join table)
하나의 유저가 여러개의 포스트를 좋아요 할 수 있고
하나의 포스트가 여러개의 좋아요를 받을 수 있다.
이럴 경우
User has many liked_posts through likes
Post has many liked_users through likes
ubuntu:~/environment/noar (master) $ rails g model Like
Running via Spring preloader in process 1583
invoke active_record
create db/migrate/20200621131036_create_likes.rb
create app/models/like.rb
invoke test_unit
create test/models/like_test.rb
create test/fixtures/likes.yml
class CreateLikes < ActiveRecord::Migration[5.0]
def change
create_table :likes do |t|
#like모델은 유저와 포스트 둘다 부모로 가진다.
t.belongs_to :user
t.belongs_to :post
t.timestamps
end
end
end
ubuntu:~/environment/noar (master) $ rake db:migrate
== 20200621131036 CreateLikes: migrating ======================================
-- create_table(:likes)
-> 0.0062s
== 20200621131036 CreateLikes: migrated (0.0073s) =============================
이제 모델의 관계설정을 해줘야한다.
User ← 1:N → Like ← N:1 → Post
에서
User ← 1:N → Like
라이크와 유저사이의 관계를 설정해주고
Like ← N:1 → Post
라이크와 포스트 간의 관계설정을 해 준 이후
유저입장에서 좋아하는 포스트의 리스트를 가져올 수 있는 관계설정을 할 것이다.
라이크모델부터 살펴보자
class Like < ApplicationRecord
#어떤 하나의 Like를 찾아오면
#어떤 사용자가 어떤 글을 좋아했는지 알 수 있다.
belongs_to :user
belongs_to :post
end
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :posts
has_many :liked
# 1:N 관계인 likes를 이용해서 Post와 N:N 관계를 구현
# 특정 유저가 좋아요를 누른 posts를 얻을 수 있음.
# ex) user.likes_posts
#유저입장에서 좋아하는 글을 가져오는데,
#가져올 때 Likes를 토대로 찾게되고,
#그 속에서 post만 묶어서 보여준다.(그 출처는 post다)
has_many :liked_posts, through: :likes, source: :post
end
class Post < ApplicationRecord
belongs_to :user
has_many :likes
# 1:N 관계인 likes를 이용해서 User와 N:N 관계를 구현
# 특정 글에 좋아요를 누른 users를 얻을 수 있음.
# ex) post.liked_users
has_many :liked_users, through: :likes, source: :user
end
콘솔에서 확인해보자.
**ubuntu:~/environment/noar (master) $ rails c**
Running via Spring preloader in process 2533
Loading development environment (Rails 5.0.7.2)
**2.6.3 :001 > User.all**
User Load (1.2ms) SELECT "users".* FROM "users"
=> #<ActiveRecord::Relation [#<User id: 1, email: "comp-er@daum.net", name: "정형찬", created_at: "2020-06-16 07:21:14", updated_at: "2020-06-16 07:55:00">, #<User id: 2, email: "asd@asd.com", name: "asd", created_at: "2020-06-21 13:30:36", updated_at: "2020-06-21 13:30:36">]>
**2.6.3 :002 > Post.all**
Post Load (0.2ms) SELECT "posts".* FROM "posts"
=> #<ActiveRecord::Relation [#<Post id: 1, content: "첫번째 글 입니다", user_id: 1, created_at: "2020-06-17 01:27:51", updated_at: "2020-06-17 01:27:51">, #<Post id: 2, content: "수정을 해봅시다.\r\n엔터가 적용되나 봅시다.\r\n 잘 수정됩니다.", user_id: 1, created_at: "2020-06-17 01:44:39", updated_at: "2020-06-17 04:59:36">, #<Post id: 4, content: "asd입니다", user_id: 2, created_at: "2020-06-21 13:30:44", updated_at: "2020-06-21 13:30:44">]>
이제 좋아요를 해보자.
**** 유저 아이디가 1번인 유저가 4번 글을 좋아함 ****
**2.6.3 :004 > Like.create(user_id: 1, post_id: 4)**
(0.1ms) begin transaction
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT ? [["id", 4], ["LIMIT", 1]]
SQL (1.7ms) INSERT INTO "likes" ("user_id", "post_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["user_id", 1], ["post_id", 4], ["created_at", "2020-06-21 13:33:10.587067"], ["updated_at", "2020-06-21 13:33:10.587067"]]
(4.7ms) commit transaction
=> #<Like id: 1, user_id: 1, post_id: 4, created_at: "2020-06-21 13:33:10", updated_at: "2020-06-21 13:33:10">
**** post 변수에 4번째 글 할당 ****
**2.6.3 :011 > post = Post.find(4)**
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT ? [["id", 4], ["LIMIT", 1]]
=> #<Post id: 4, content: "asd입니다", user_id: 2, created_at: "2020-06-21 13:30:44", updated_at: "2020-06-21 13:30:44">
**** 4번째 글을 좋아했던 유저 찾기 ****
**2.6.3 :012 > post.liked_users**
User Load (0.2ms) SELECT "users".* FROM "users" INNER JOIN "likes" ON "users"."id" = "likes"."user_id" WHERE "likes"."post_id" = ? [["post_id", 4]]
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 1, email: "comp-er@daum.net", name: "정형찬", created_at: "2020-06-16 07:21:14", updated_at: "2020-06-16 07:55:00">]>
'Rails 5 on aws c9' 카테고리의 다른 글
N9. 댓글 기능 구현 (0) | 2020.07.05 |
---|---|
N8. 좋아요 기능 UI 구현하기 (0) | 2020.07.05 |
N6. Post 수정과 삭제 (0) | 2020.07.05 |
N5-1. post 결과물을 json으로 응답받기 (0) | 2020.07.05 |
N5. Post 리스트와 생성 (0) | 2020.07.05 |