Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User following #22

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions app/controllers/relationships_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class RelationshipsController < ApplicationController
before_action :signed_in_user

def create
@user = User.find(params[:relationship][:followed_id])
current_user.follow!(@user)
respond_to do |format| # only one of these lines gets executed based on the type of request (HTTP vs Ajax)
format.html { redirect_to @user }
format.js
end
end

def destroy
@user = Relationship.find(params[:id]).followed
current_user.unfollow!(@user)
respond_to do |format|
format.html { redirect_to @user }
format.js
end
end
end
16 changes: 15 additions & 1 deletion app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class UsersController < ApplicationController
before_action :not_new_user, only: [:new, :create]
before_action :signed_in_user, only: [:index, :edit, :update, :destroy]
before_action :signed_in_user, only: [:index, :edit, :update, :destroy, :following, :followers]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy

Expand Down Expand Up @@ -46,6 +46,20 @@ def destroy
redirect_to users_url
end

def following
@title = "Following"
@user = User.find(params[:id])
@users = @user.followed_users
render 'show_follow'
end

def followers
@title = "Followers"
@user = User.find(params[:id])
@users = @user.followers
render 'show_follow'
end

private

def user_params
Expand Down
8 changes: 8 additions & 0 deletions app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@ class Post < ActiveRecord::Base
validates :user_id, presence: true
validates :content, presence: true
validates :title, presence: true, length: { maximum: 150 }

def self.from_users_followed_by(user)
followed_user_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"

where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
user_id: user.id)
end
end
7 changes: 7 additions & 0 deletions app/models/relationship.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"

validates :follower_id, presence: true
validates :followed_id, presence: true
end
21 changes: 20 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, through: :relationships, source: :followed

has_many :reverse_relationships, foreign_key: "followed_id",
class_name: "Relationship",
dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower

before_save { self.email = email.downcase }
before_create :create_remember_token
Expand All @@ -24,7 +31,19 @@ def User.encrypt(token)
end

def feed
Post.where("user_id = ?", id)
Post.from_users_followed_by(self)
end

def following?(other_user)
relationships.find_by(followed_id: other_user.id)
end

def follow!(other_user)
relationships.create!(followed_id: other_user.id)
end

def unfollow!(other_user)
relationships.find_by(followed_id: other_user.id).destroy
end

private
Expand Down
2 changes: 2 additions & 0 deletions app/views/relationships/create.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= @user.followers.count %>')
2 changes: 2 additions & 0 deletions app/views/relationships/destroy.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= @user.followers.count %>')
15 changes: 15 additions & 0 deletions app/views/shared/_stats.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<% @user ||= current_user %>
<div class="stats">
<a href="<%= following_user_path(@user) %>">
<strong id="following" class="stat">
<%= @user.followed_users.count %>
</strong>
following
</a>
<a href="<%= followers_user_path(@user) %>">
<strong id="followers" class="stat">
<%= @user.followers.count %>
</strong>
followers
</a>
</div>
3 changes: 3 additions & 0 deletions app/views/static_pages/home.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
<section>
<%= render 'shared/user_info' %>
</section>
<section>
<%= render 'shared/stats' %>
</section>
<section>
<%= render 'shared/post_form' %>
</section>
Expand Down
5 changes: 5 additions & 0 deletions app/views/users/_follow.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<%= form_for(current_user.relationships.build(followed_id: @user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
9 changes: 9 additions & 0 deletions app/views/users/_follow_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<% unless current_user?(@user) %>
<div id="follow_form">
<% if current_user.following?(@user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
5 changes: 5 additions & 0 deletions app/views/users/_unfollow.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<%= form_for(current_user.relationships.find_by(followed_id: @user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
4 changes: 4 additions & 0 deletions app/views/users/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
<section>
<h1><%= @user.name %></h1>
</section>
<section>
<%= render 'shared/stats' %>
</section>
</aside>
<div class="span8">
<%= render 'follow_form' if signed_in? %>
<% if @user.posts.any? %>
<h3>Posts (<%= @user.posts.count %>)</h3>
<ol class="posts">
Expand Down
20 changes: 20 additions & 0 deletions app/views/users/show_follow.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div class="row">
<aside class="span4">
<section>
<h1><%= @user.name %></h1>
<span><%= link_to "view my profile", @user %></span>
<span><b>Posts:</b> <%= @user.posts.count %></span>
</section>
<section>
<%= render 'shared/stats' %>
</section>
</aside>
<div class="span8">
<h3><%= @title %></h3>
<% if @users.any? %>
<ul class="users">
<%= render @users %>
</ul>
<% end %>
</div>
</div>
8 changes: 7 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'

resources :users
resources :users do
member do
get :following, :followers
end
end
match '/signup', to: 'users#new', via: 'get'

resources :sessions, only: [:new, :create, :destroy]
Expand All @@ -12,6 +16,8 @@

resources :posts, only: [:create, :destroy]

resources :relationships, only: [:create, :destroy]

# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".

Expand Down
13 changes: 13 additions & 0 deletions db/migrate/20140126185610_create_relationships.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CreateRelationships < ActiveRecord::Migration
def change
create_table :relationships do |t|
t.integer :follower_id
t.integer :followed_id

t.timestamps
end
add_index :relationships, :follower_id
add_index :relationships, :followed_id
add_index :relationships, [:follower_id, :followed_id], unique: true
end
end
13 changes: 12 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20140122232133) do
ActiveRecord::Schema.define(version: 20140126185610) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand All @@ -27,6 +27,17 @@

add_index "posts", ["user_id", "created_at"], name: "index_posts_on_user_id_and_created_at", using: :btree

create_table "relationships", force: true do |t|
t.integer "follower_id"
t.integer "followed_id"
t.datetime "created_at"
t.datetime "updated_at"
end

add_index "relationships", ["followed_id"], name: "index_relationships_on_followed_id", using: :btree
add_index "relationships", ["follower_id", "followed_id"], name: "index_relationships_on_follower_id_and_followed_id", unique: true, using: :btree
add_index "relationships", ["follower_id"], name: "index_relationships_on_follower_id", using: :btree

create_table "users", force: true do |t|
t.string "email"
t.string "name"
Expand Down
63 changes: 36 additions & 27 deletions lib/tasks/sample_data.rake
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
namespace :db do
desc "Fill database with sample data"
task populate: :environment do
User.create!(name: "Adam Morganaki",
email: "[email protected]",
password: "foobar",
password_confirmation: "foobar",
admin: true)
User.create!(name: "Kill Clean",
email: "[email protected]",
password: "foobar",
password_confirmation: "foobar",
admin: true)
25.times do |n|
name = Faker::Name.name
email = "example-#{n+1}@testing.org"
password = "password"
User.create!(name: name,
email: email,
password: password,
password_confirmation: password)
end
make_users
make_posts
make_relationships
end
end

desc "Fill database with sample data"
task populate: :environment do
users = User.all(limit: 5)
10.times do
title = Faker::Lorem.sentence(5)
content = Faker::Lorem.sentence(5)
users.each { |user| user.posts.create!(title: title, content: content) }
end
def make_users
admin = User.create!(name: "Adam Morganaki",
email: "[email protected]",
password: "foobar",
password_confirmation: "foobar",
admin: true)
99.times do |n|
name = Faker::Name.name
email = "example-#{n+1}@testing.org"
password = "password"
User.create!(name: name,
email: email,
password: password,
password_confirmation: password)
end
end

def make_posts
users = User.all(limit: 5)
10.times do
title = Faker::Lorem.sentence(5)
content = Faker::Lorem.sentence(5)
users.each { |user| user.posts.create!(title: title, content: content) }
end
end

def make_relationships
users = User.all
user = users.first
followed_users = users[2..50]
followers = users[3..40]
followed_users.each { |followed| user.follow!(followed) }
followers.each { |follower| follower.follow!(user) }
end
9 changes: 9 additions & 0 deletions test/fixtures/relationships.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

one:
follower_id: 1
followed_id: 1

two:
follower_id: 1
followed_id: 1
7 changes: 7 additions & 0 deletions test/models/relationship_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'test_helper'

class RelationshipTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end