Use polymorphic relationships for followable

This commit is contained in:
Jesse C. Fisher 2023-11-21 17:19:33 +00:00
parent 5882c82f75
commit b4d0afe90d
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 # GET /profiles/1 or /profiles/1.json
def show def show
authorize @profile authorize @profile
@followable = @profile
if @profile.user == current_user if @profile.user == current_user
@micropost = @profile.microposts.build @micropost = @profile.microposts.build
else else

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,8 @@
class Relationship < ActiveRecord::Base class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User" belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "Profile"
validates :follower_id, presence: true 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 end

View File

@ -10,7 +10,9 @@ class User < ActiveRecord::Base
has_many :active_relationships, class_name: "Relationship", has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id", foreign_key: "follower_id",
dependent: :destroy 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 has_many :microposts, as: :micropostable
def icid def icid
@ -106,14 +108,18 @@ class User < ActiveRecord::Base
devise :invitable, :database_authenticatable, :registerable, devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable :recoverable, :rememberable, :trackable, :validatable
# Follows a user. # Follows a followable leader
def follow(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 end
# Unfollows a user. # Unfollows a followable leader
def unfollow(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 end
# Returns true if the current user is following the leader. # Returns true if the current user is following the leader.

View File

@ -3,11 +3,14 @@
= @project.title = @project.title
- if policy(@project).edit? - if policy(@project).edit?
= link_to 'Edit', edit_project_path(@project) = 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 .description
= @project.description = @project.description
.stats
%p #{@project.followers.count} Followers
- if @project.microposts.any? - if @project.microposts.any?
%section.microposts %section.microposts
%h3 Posts #{@project.microposts.count} %h3 Posts #{@project.microposts.count}

View File

@ -1,3 +1,4 @@
= form_for(current_user.active_relationships.build) do |f| = 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" = f.submit "Follow"

View File

@ -1,5 +1,5 @@
#follow_form #follow_form
- if current_user.following?(@profile) - if current_user.following?(@followable)
= render 'unfollow' = render 'shared/unfollow'
- else - else
= render 'shared/follow' = 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| | html: { method: :delete }) do |f| |
= f.submit "Unfollow" = 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. # 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 # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -129,6 +129,9 @@ ActiveRecord::Schema.define(version: 2023_11_14_160910) do
t.integer "followed_id" t.integer "followed_id"
t.datetime "created_at", precision: 6, null: false t.datetime "created_at", precision: 6, null: false
t.datetime "updated_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 ["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", "followed_id"], name: "index_relationships_on_follower_id_and_followed_id", unique: true
t.index ["follower_id"], name: "index_relationships_on_follower_id" t.index ["follower_id"], name: "index_relationships_on_follower_id"