Skip to content

Commit e3384d5

Browse files
committed
Add user following
1 parent 233f5bb commit e3384d5

25 files changed

+401
-29
lines changed

app/assets/stylesheets/custom.scss

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,44 @@ aside {
167167
margin-top: 15px;
168168
}
169169

170+
.stats {
171+
overflow: auto;
172+
margin-top: 0;
173+
padding: 0;
174+
a {
175+
float: left;
176+
padding: 0 10px;
177+
border-left: 1px solid $gray-lighter;
178+
color: gray;
179+
&:first-child {
180+
padding-left: 0;
181+
border: 0;
182+
}
183+
&:hover {
184+
text-decoration: none;
185+
color: blue;
186+
}
187+
}
188+
strong {
189+
display: block;
190+
}
191+
}
192+
193+
.user_avatars {
194+
overflow: auto;
195+
margin-top: 10px;
196+
.gravatar {
197+
margin: 1px 1px;
198+
}
199+
a {
200+
padding: 0;
201+
}
202+
}
203+
204+
.users.follow {
205+
padding: 0;
206+
}
207+
170208
/* forms */
171209

172210
input, textarea, select, .uneditable-input {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class RelationshipsController < ApplicationController
2+
before_action :logged_in_user
3+
4+
def create
5+
@user = User.find(params[:followed_id])
6+
current_user.follow(@user)
7+
respond_to do |format|
8+
format.html { redirect_to @user }
9+
format.turbo_stream
10+
end
11+
end
12+
13+
def destroy
14+
@user = Relationship.find(params[:id]).followed
15+
current_user.unfollow(@user)
16+
respond_to do |format|
17+
format.html { redirect_to @user, status: :see_other }
18+
format.turbo_stream
19+
end
20+
end
21+
end

app/controllers/users_controller.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
class UsersController < ApplicationController
2-
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
2+
before_action :logged_in_user, only: [:index, :edit, :update, :destroy,
3+
:following, :followers]
34
before_action :correct_user, only: [:edit, :update]
45
before_action :admin_user, only: :destroy
56

@@ -47,6 +48,20 @@ def destroy
4748
redirect_to users_url, status: :see_other
4849
end
4950

51+
def following
52+
@title = "Following"
53+
@user = User.find(params[:id])
54+
@users = @user.following.paginate(page: params[:page])
55+
render 'show_follow'
56+
end
57+
58+
def followers
59+
@title = "Followers"
60+
@user = User.find(params[:id])
61+
@users = @user.followers.paginate(page: params[:page])
62+
render 'show_follow'
63+
end
64+
5065
private
5166

5267
def user_params

app/helpers/relationships_helper.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
module RelationshipsHelper
2+
end

app/models/relationship.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Relationship < ApplicationRecord
2+
belongs_to :follower, class_name: "User"
3+
belongs_to :followed, class_name: "User"
4+
validates :follower_id, presence: true
5+
validates :followed_id, presence: true
6+
end

app/models/user.rb

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
class User < ApplicationRecord
22
has_many :microposts, dependent: :destroy
3+
has_many :active_relationships, class_name: "Relationship",
4+
foreign_key: "follower_id",
5+
dependent: :destroy
6+
has_many :passive_relationships, class_name: "Relationship",
7+
foreign_key: "followed_id",
8+
dependent: :destroy
9+
has_many :following, through: :active_relationships, source: :followed
10+
has_many :followers, through: :passive_relationships, source: :follower
311
attr_accessor :remember_token, :activation_token, :reset_token
412
before_save :downcase_email
513
before_create :create_activation_digest
@@ -76,10 +84,28 @@ def password_reset_expired?
7684
reset_sent_at < 2.hours.ago
7785
end
7886

79-
# Defines a proto-feed.
80-
# See "Following users" for the full implementation.
87+
# Returns a user's status feed.
8188
def feed
82-
Micropost.where("user_id = ?", id)
89+
following_ids = "SELECT followed_id FROM relationships
90+
WHERE follower_id = :user_id"
91+
Micropost.where("user_id IN (#{following_ids})
92+
OR user_id = :user_id", user_id: id)
93+
.includes(:user, image_attachment: :blob)
94+
end
95+
96+
# Follows a user.
97+
def follow(other_user)
98+
following << other_user unless self == other_user
99+
end
100+
101+
# Unfollows a user.
102+
def unfollow(other_user)
103+
following.delete(other_user)
104+
end
105+
106+
# Returns true if the current user is following the other user.
107+
def following?(other_user)
108+
following.include?(other_user)
83109
end
84110

85111
private
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<%= turbo_stream.update "follow_form" do %>
2+
<%= render partial: "users/unfollow" %>
3+
<% end %>
4+
<%= turbo_stream.update "followers" do %>
5+
<%= @user.followers.count %>
6+
<% end %>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<%= turbo_stream.update "follow_form" do %>
2+
<%= render partial: "users/follow" %>
3+
<% end %>
4+
<%= turbo_stream.update "followers" do %>
5+
<%= @user.followers.count %>
6+
<% end %>

app/views/shared/_stats.html.erb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<% @user ||= current_user %>
2+
<div class="stats">
3+
<a href="<%= following_user_path(@user) %>">
4+
<strong id="following" class="stat">
5+
<%= @user.following.count %>
6+
</strong>
7+
following
8+
</a>
9+
<a href="<%= followers_user_path(@user) %>">
10+
<strong id="followers" class="stat">
11+
<%= @user.followers.count %>
12+
</strong>
13+
followers
14+
</a>
15+
</div>

app/views/static_pages/home.html.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
<section class="user_info">
55
<%= render 'shared/user_info' %>
66
</section>
7+
<section class="stats">
8+
<%= render 'shared/stats' %>
9+
</section>
710
<section class="micropost_form">
811
<%= render 'shared/micropost_form' %>
912
</section>

0 commit comments

Comments
 (0)