Use polymorphic relationships for followable

This commit is contained in:
Jesse C. Fisher 2023-11-21 17:19:33 +00:00 committed by TheNeedful-DO
parent e13ba15989
commit 24e346ce60
13 changed files with 53 additions and 26 deletions

View File

@ -10,6 +10,7 @@ class ProfilesController < ApplicationController
# GET /profiles/1 or /profiles/1.json
def show
authorize @profile
@followable = @profile
if @profile.user == current_user
@micropost = @profile.microposts.build
else

View File

@ -9,6 +9,7 @@ class ProjectsController < ApplicationController
# GET /projects/1 or /projects/1.json
def show
authorize @project
@followable = @project
end
# GET /projects/new

View File

@ -1,15 +1,16 @@
class RelationshipsController < ApplicationController
def create
profile = Profile.find(params[:followed_id])
authorize Relationship
current_user.follow(profile)
redirect_to profile
leader = params[:followable_type].constantize.find(params[:followable_id])
current_user.follow(leader)
redirect_to leader
end
def destroy
profile = Relationship.find(params[:id]).followed
authorize profile
current_user.unfollow(profile)
redirect_to profile
relationship = Relationship.find(params[:id])
authorize relationship
leader = relationship.followable
current_user.unfollow(leader)
redirect_to leader
end
end

View File

@ -2,11 +2,15 @@ class Profile < ActiveRecord::Base
belongs_to :user
has_many :social_links
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
foreign_key: "followable_id",
dependent: :destroy
has_many :followers, through: :passive_relationships, source: :follower
# has_many :followers, through: :passive_relationships, source: :follower
has_many :microposts, as: :micropostable
def followers
Relationship.where("followable_id = ? AND followable_type = ?", self.id, self.class.to_s)
end
def display_name
name
end

View File

@ -1,10 +1,10 @@
class Project < ActiveRecord::Base
belongs_to :user
has_many :microposts, as: :micropostable
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :followers, through: :passive_relationships, source: :follower
def followers
Relationship.where("followable_id = ? AND followable_type = ?", self.id, self.class.to_s)
end
def display_name
title

View File

@ -1,6 +1,8 @@
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "Profile"
validates :follower_id, presence: true
validates :followed_id, presence: true
belongs_to :followable, polymorphic: true
# belongs_to :followed, class_name: "Profile"
# validates :followed_id, presence: true
# belongs_to :followerable, polymorphic: true
end

View File

@ -10,7 +10,9 @@ class User < ActiveRecord::Base
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
# has_many :following, through: :active_relationships, source: :followed
has_many :following_profiles, through: :active_relationships, source: :followable, source_type: "Profile"
has_many :following_projects, through: :active_relationships, source: :followable, source_type: "Project"
has_many :microposts, as: :micropostable
def icid
@ -106,14 +108,18 @@ class User < ActiveRecord::Base
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Follows a user.
# Follows a followable leader
def follow(leader)
active_relationships.create(followed_id: leader.id)
active_relationships.create(followable_id: leader.id, followable_type: leader.class.to_s)
end
# Unfollows a user.
# Unfollows a followable leader
def unfollow(leader)
active_relationships.find_by(followed_id: leader.id).destroy
active_relationships.find_by(followable_id: leader.id, followable_type: leader.class.to_s).destroy
end
def following
active_relationships.map{|ar| ar.followable }
end
# Returns true if the current user is following the leader.

View File

@ -3,11 +3,14 @@
= @project.title
- if policy(@project).edit?
= link_to 'Edit', edit_project_path(@project)
-# = render 'shared/follow_form' if current_user.signed_in?
= render 'shared/follow_form' if current_user.signed_in?
.description
= @project.description
.stats
%p #{@project.followers.count} Followers
- if @project.microposts.any?
%section.microposts
%h3 Posts #{@project.microposts.count}

View File

@ -1,3 +1,4 @@
= form_for(current_user.active_relationships.build) do |f|
%div= hidden_field_tag :followed_id, @profile.id
%div= hidden_field_tag :followable_id, @followable.id
%div= hidden_field_tag :followable_type, @followable.class.to_s
= f.submit "Follow"

View File

@ -1,5 +1,5 @@
#follow_form
- if current_user.following?(@profile)
= render 'unfollow'
- if current_user.following?(@followable)
= render 'shared/unfollow'
- else
= render 'shared/follow'

View File

@ -1,3 +1,3 @@
= form_for(current_user.active_relationships.find_by(followed_id: @profile.id), |
= form_for(current_user.active_relationships.find_by(followable_id: @followable.id), |
html: { method: :delete }) do |f| |
= f.submit "Unfollow"

View File

@ -0,0 +1,5 @@
class AddFollowableToRelationship < ActiveRecord::Migration[6.1]
def change
add_reference :relationships, :followable, polymorphic: true
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2023_11_14_160910) do
ActiveRecord::Schema.define(version: 2023_11_21_150256) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -129,6 +129,9 @@ ActiveRecord::Schema.define(version: 2023_11_14_160910) do
t.integer "followed_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "followable_type"
t.bigint "followable_id"
t.index ["followable_type", "followable_id"], name: "index_relationships_on_followable"
t.index ["followed_id"], name: "index_relationships_on_followed_id"
t.index ["follower_id", "followed_id"], name: "index_relationships_on_follower_id_and_followed_id", unique: true
t.index ["follower_id"], name: "index_relationships_on_follower_id"