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.
This commit is contained in:
		
							parent
							
								
									c0b30c56db
								
							
						
					
					
						commit
						8bac0350d1
					
				
							
								
								
									
										12
									
								
								app/controllers/account_follow_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/controllers/account_follow_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| # 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 | ||||
							
								
								
									
										12
									
								
								app/controllers/account_unfollow_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/controllers/account_unfollow_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| # 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 | ||||
| @ -1,12 +1,7 @@ | ||||
| # 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 | ||||
|  | ||||
							
								
								
									
										51
									
								
								app/controllers/concerns/account_controller_concern.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/controllers/concerns/account_controller_concern.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| # 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 | ||||
							
								
								
									
										15
									
								
								app/controllers/follower_accounts_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/controllers/follower_accounts_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| # 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 | ||||
							
								
								
									
										15
									
								
								app/controllers/following_accounts_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/controllers/following_accounts_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| # 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 | ||||
							
								
								
									
										7
									
								
								app/views/accounts/_follow_grid.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/views/accounts/_follow_grid.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| .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 | ||||
|  | ||||
							
								
								
									
										6
									
								
								app/views/follower_accounts/index.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/views/follower_accounts/index.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| - 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 | ||||
							
								
								
									
										6
									
								
								app/views/following_accounts/index.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/views/following_accounts/index.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| - 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 | ||||
|  | ||||
							
								
								
									
										24
									
								
								spec/controllers/account_follow_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								spec/controllers/account_follow_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| 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 | ||||
							
								
								
									
										24
									
								
								spec/controllers/account_unfollow_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								spec/controllers/account_unfollow_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| 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 | ||||
|  | ||||
							
								
								
									
										14
									
								
								spec/controllers/follower_accounts_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								spec/controllers/follower_accounts_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| 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 | ||||
							
								
								
									
										14
									
								
								spec/controllers/following_accounts_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								spec/controllers/following_accounts_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| 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 | ||||
							
								
								
									
										33
									
								
								spec/requests/link_headers_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								spec/requests/link_headers_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| # 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 | ||||
							
								
								
									
										31
									
								
								spec/routing/accounts_routing_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								spec/routing/accounts_routing_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| 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 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user