Last active
April 21, 2020 10:48
-
-
Save mh-mobile/2fcf17570bef032872ceb4f48be756a5 to your computer and use it in GitHub Desktop.
follow relationship
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
require "bundler/inline" | |
gemfile(true) do | |
source "https://rubygems.org" | |
git_source(:github) { |repo| "https://github.com/#{repo}.git" } | |
# Activate the gem you are reporting the issue against. | |
gem "activerecord", "6.0.0" | |
gem "sqlite3" | |
gem "byebug" | |
end | |
require "active_record" | |
require "minitest/autorun" | |
require "logger" | |
# This connection will do for database-independent bug reports. | |
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") | |
ActiveRecord::Base.logger = Logger.new(STDOUT) | |
ActiveRecord::Schema.define do | |
create_table :users, force: true do |t| | |
t.string :name, null: false | |
end | |
create_table :friendships, force: true do |t| | |
t.belongs_to :follower | |
t.belongs_to :followed | |
end | |
add_index :friendships, [:follower_id, :followed_id], unique: true | |
create_table :books, force: true do |t| | |
t.string :user_id | |
t.string :name | |
end | |
end | |
class ApplicationRecord < ActiveRecord::Base | |
self.abstract_class = true | |
end | |
class User < ApplicationRecord | |
has_many :books | |
has_many :friendships, foreign_key: "follower_id", dependent: :destroy | |
has_many :reverse_friendships, foreign_key: "followed_id", class_name: "Friendship", dependent: :destroy | |
has_many :following, through: :friendships, source: :followed, class_name: "User" | |
has_many :followers, through: :reverse_friendships, class_name: "User" | |
has_many :following_books, through: :following, source: :books, class_name: "Book" | |
def follow!(user) | |
# friendships.create!(followed_id: user.id) | |
following << user | |
end | |
def unfollow!(user) | |
friendships.find_by!(followed_id: user.id).destroy! | |
end | |
def following?(user) | |
following.include?(user) | |
end | |
end | |
class Friendship < ApplicationRecord | |
belongs_to :follower, class_name: "User" | |
belongs_to :followed, class_name: "User" | |
end | |
class Book < ApplicationRecord | |
belongs_to :user | |
default_scope -> { order('create_at DESC') } | |
def self.friend_feeds(user) | |
# 自分の持つ書籍とフォローユーザーが持つ書籍を取得する | |
following_ids = "select followed_id from friendships where follower_id = :user_id" | |
where("user_id in (#{following_ids}) or user_id = :user_id", user_id: user.id) | |
end | |
end | |
class FriendshipTest < Minitest::Test | |
def test_association | |
# テストデータ作成 | |
mh = User.create!(name: "mh") | |
ruby_book = Book.create!(name: "ruby", user_id: mh.id) | |
js_book = Book.create!(name: "js", user_id: mh.id) | |
miro = User.create!(name: "miro") | |
php_book = Book.create!(name: "php", user_id: miro.id) | |
python_book = Book.create!(name: "python", user_id: miro.id) | |
swift_book = Book.create!(name: "swift", user_id: miro.id) | |
haru = User.create!(name: "haru") | |
rust_book = Book.create!(name: "rust", user_id: haru.id) | |
typescript_book = Book.create!(name: "typescript", user_id: haru.id) | |
go_book = Book.create!(name: "go", user_id: haru.id) | |
kotlin = Book.create!(name: "kotlin", user_id: haru.id) | |
# フォローの関連付け | |
assert_equal false, mh.following?(miro) | |
assert_equal false, mh.following?(haru) | |
mh.follow!(miro) | |
mh.follow!(haru) | |
assert_equal true, mh.following?(miro) | |
assert_equal true, mh.following?(haru) | |
# フォローユーザーの取得 | |
following = mh.following | |
# フォローが正しい | |
assert_equal 2, following.count | |
assert_equal miro, following[0] | |
assert_equal haru, following[1] | |
# フォローユーザーの書籍の数が正しい | |
following_books = mh.following_books | |
assert_equal 7, following_books.count | |
# 自分を含めたフォローユーザーの書籍のフィードを取得 | |
feeds = Book.friend_feeds(mh) | |
assert_equal 9, feeds.count | |
# フォローを解除 | |
mh.unfollow!(miro) | |
mh.reload | |
following = mh.following | |
# フォローが正しい | |
assert_equal 1, following.count | |
assert_equal haru, following[0] | |
assert_equal false, mh.following?(miro) | |
assert_equal true, mh.following?(haru) | |
# mhユーザーを削除 | |
mh.destroy | |
# Friendshipのデータ数が0になる | |
assert_equal 0, Friendship.all.count | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment