Skip to content
Snippets Groups Projects
Commit 8bac0350 authored by Matt Jankowski's avatar Matt Jankowski Committed by Eugen
Browse files

Restful refactor of accounts/ routes (#2133)

* Add routing specs for accounts followers and following actions

* Use more restful route naming for public account follow pages

Moves two actions:
- accounts#followers to accounts/follower_accounts#index
- accounts#following to accounts/following_accounts#index

Adds routing spec to ensure prior URLs are preserved.
parent c0b30c56
No related branches found
No related tags found
No related merge requests found
Showing
with 275 additions and 63 deletions
# frozen_string_literal: true
class AccountFollowController < ApplicationController
include AccountControllerConcern
before_action :authenticate_user!
def create
FollowService.new.call(current_user.account, @account.acct)
redirect_to account_path(@account)
end
end
# frozen_string_literal: true
class AccountUnfollowController < ApplicationController
include AccountControllerConcern
before_action :authenticate_user!
def create
UnfollowService.new.call(current_user.account, @account)
redirect_to account_path(@account)
end
end
# frozen_string_literal: true
class AccountsController < ApplicationController
layout 'public'
before_action :set_account
before_action :set_link_headers
before_action :authenticate_user!, only: [:follow, :unfollow]
before_action :check_account_suspension
include AccountControllerConcern
def show
respond_to do |format|
......@@ -24,39 +19,9 @@ class AccountsController < ApplicationController
end
end
def follow
FollowService.new.call(current_user.account, @account.acct)
redirect_to account_path(@account)
end
def unfollow
UnfollowService.new.call(current_user.account, @account)
redirect_to account_path(@account)
end
def followers
@followers = @account.followers.order('follows.created_at desc').page(params[:page]).per(12)
end
def following
@following = @account.following.order('follows.created_at desc').page(params[:page]).per(12)
end
private
def set_account
@account = Account.find_local!(params[:username])
end
def set_link_headers
response.headers['Link'] = LinkHeader.new([[webfinger_account_url, [%w(rel lrdd), %w(type application/xrd+xml)]], [account_url(@account, format: 'atom'), [%w(rel alternate), %w(type application/atom+xml)]]])
end
def webfinger_account_url
webfinger_url(resource: @account.to_webfinger_s)
end
def check_account_suspension
gone if @account.suspended?
end
end
# frozen_string_literal: true
module AccountControllerConcern
extend ActiveSupport::Concern
FOLLOW_PER_PAGE = 12
included do
layout 'public'
before_action :set_account
before_action :set_link_headers
before_action :check_account_suspension
end
private
def set_account
@account = Account.find_local!(params[:account_username])
end
def set_link_headers
response.headers['Link'] = LinkHeader.new(
[
webfinger_account_link,
atom_account_url_link,
]
)
end
def webfinger_account_link
[
webfinger_account_url,
[%w(rel lrdd), %w(type application/xrd+xml)],
]
end
def atom_account_url_link
[
account_url(@account, format: 'atom'),
[%w(rel alternate), %w(type application/atom+xml)],
]
end
def webfinger_account_url
webfinger_url(resource: @account.to_webfinger_s)
end
def check_account_suspension
gone if @account.suspended?
end
end
# frozen_string_literal: true
class FollowerAccountsController < ApplicationController
include AccountControllerConcern
def index
@accounts = ordered_accounts.page(params[:page]).per(FOLLOW_PER_PAGE)
end
private
def ordered_accounts
@account.followers.order('follows.created_at desc')
end
end
# frozen_string_literal: true
class FollowingAccountsController < ApplicationController
include AccountControllerConcern
def index
@accounts = ordered_accounts.page(params[:page]).per(FOLLOW_PER_PAGE)
end
private
def ordered_accounts
@account.following.order('follows.created_at desc')
end
end
.accounts-grid
- if accounts.empty?
= render partial: 'accounts/nothing_here'
- else
= render partial: 'accounts/grid_card', collection: accounts, as: :account, cached: true
= paginate accounts
......@@ -2,9 +2,9 @@
- if user_signed_in? && current_account.id != account.id && !current_account.requested?(account)
.controls
- if current_account.following?(account)
= link_to t('accounts.unfollow'), unfollow_account_path(account), data: { method: :post }, class: 'button'
= link_to t('accounts.unfollow'), account_unfollow_path(account), data: { method: :post }, class: 'button'
- else
= link_to t('accounts.follow'), follow_account_path(account), data: { method: :post }, class: 'button'
= link_to t('accounts.follow'), account_follow_path(account), data: { method: :post }, class: 'button'
- elsif !user_signed_in?
.controls
.remote-follow
......@@ -24,11 +24,11 @@
= link_to short_account_url(account), class: 'u-url u-uid' do
%span.counter-label= t('accounts.posts')
%span.counter-number= number_with_delimiter account.statuses_count
.counter{ class: active_nav_class(following_account_url(account)) }
= link_to following_account_url(account) do
.counter{ class: active_nav_class(account_following_index_url(account)) }
= link_to account_following_index_url(account) do
%span.counter-label= t('accounts.following')
%span.counter-number= number_with_delimiter account.following_count
.counter{ class: active_nav_class(followers_account_url(account)) }
= link_to followers_account_url(account) do
.counter{ class: active_nav_class(account_followers_url(account)) }
= link_to account_followers_url(account) do
%span.counter-label= t('accounts.followers')
%span.counter-number= number_with_delimiter account.followers_count
- content_for :page_title do
= t('accounts.people_who_follow', name: display_name(@account))
= render 'accounts/header', account: @account
= render 'accounts/follow_grid', accounts: @accounts
- content_for :page_title do
= t('accounts.people_followed_by', name: display_name(@account))
= render 'accounts/header', account: @account
= render 'accounts/follow_grid', accounts: @accounts
......@@ -37,13 +37,10 @@ Rails.application.routes.draw do
get :remote_follow, to: 'remote_follow#new'
post :remote_follow, to: 'remote_follow#create'
member do
get :followers
get :following
post :follow
post :unfollow
end
resources :followers, only: [:index], controller: :follower_accounts
resources :following, only: [:index], controller: :following_accounts
resource :follow, only: [:create], controller: :account_follow
resource :unfollow, only: [:create], controller: :account_unfollow
end
get '/@:username', to: 'accounts#show', as: :short_account
......
require 'rails_helper'
describe AccountFollowController do
render_views
let(:user) { Fabricate(:user) }
let(:alice) { Fabricate(:account, username: 'alice') }
describe 'POST #create' do
before do
sign_in(user)
end
it 'redirects to account path' do
service = double
allow(FollowService).to receive(:new).and_return(service)
allow(service).to receive(:call)
post :create, params: { account_username: alice.username }
expect(service).to have_received(:call).with(user.account, 'alice')
expect(response).to redirect_to(account_path(alice))
end
end
end
require 'rails_helper'
describe AccountUnfollowController do
render_views
let(:user) { Fabricate(:user) }
let(:alice) { Fabricate(:account, username: 'alice') }
describe 'POST #create' do
before do
sign_in(user)
end
it 'redirects to account path' do
service = double
allow(UnfollowService).to receive(:new).and_return(service)
allow(service).to receive(:call)
post :create, params: { account_username: alice.username }
expect(service).to have_received(:call).with(user.account, alice)
expect(response).to redirect_to(account_path(alice))
end
end
end
......@@ -44,18 +44,4 @@ RSpec.describe AccountsController, type: :controller do
end
end
end
describe 'GET #followers' do
it 'returns http success' do
get :followers, params: { username: alice.username }
expect(response).to have_http_status(:success)
end
end
describe 'GET #following' do
it 'returns http success' do
get :following, params: { username: alice.username }
expect(response).to have_http_status(:success)
end
end
end
require 'rails_helper'
describe FollowerAccountsController do
render_views
let(:alice) { Fabricate(:account, username: 'alice') }
describe 'GET #index' do
it 'returns http success' do
get :index, params: { account_username: alice.username }
expect(response).to have_http_status(:success)
end
end
end
require 'rails_helper'
describe FollowingAccountsController do
render_views
let(:alice) { Fabricate(:account, username: 'alice') }
describe 'GET #index' do
it 'returns http success' do
get :index, params: { account_username: alice.username }
expect(response).to have_http_status(:success)
end
end
end
# frozen_string_literal: true
require 'rails_helper'
describe 'Link headers' do
describe 'on the account show page' do
let(:account) { Fabricate(:account, username: 'test') }
before do
get short_account_path(username: account)
end
it 'contains webfinger url in link header' do
link_header = link_header_with_type('application/xrd+xml')
expect(link_header.href).to match 'http://www.example.com/.well-known/webfinger?resource=acct%3Atest%40cb6e6126.ngrok.io'
expect(link_header.attr_pairs.first).to eq %w[rel lrdd]
end
it 'contains atom url in link header' do
link_header = link_header_with_type('application/atom+xml')
expect(link_header.href).to eq 'http://www.example.com/users/test.atom'
expect(link_header.attr_pairs.first).to eq %w[rel alternate]
end
def link_header_with_type(type)
response.headers['Link'].links.find do |link|
link.attr_pairs.any? { |pair| pair == ['type', type] }
end
end
end
end
require 'rails_helper'
describe 'Routes under accounts/' do
describe 'the route for accounts who are followers of an account' do
it 'routes to the followers action with the right username' do
expect(get('/users/name/followers')).
to route_to('follower_accounts#index', account_username: 'name')
end
end
describe 'the route for accounts who are followed by an account' do
it 'routes to the following action with the right username' do
expect(get('/users/name/following')).
to route_to('following_accounts#index', account_username: 'name')
end
end
describe 'the route for following an account' do
it 'routes to the follow create action with the right username' do
expect(post('/users/name/follow')).
to route_to('account_follow#create', account_username: 'name')
end
end
describe 'the route for unfollowing an account' do
it 'routes to the unfollow create action with the right username' do
expect(post('/users/name/unfollow')).
to route_to('account_unfollow#create', account_username: 'name')
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment