Refactor user page to use a presenter object
This commit is contained in:
parent
5dc857ed9e
commit
463f18c207
@ -1,23 +1,16 @@
|
||||
class UsersController < ApplicationController
|
||||
|
||||
PER_PAGE = 15
|
||||
|
||||
before_filter :ensure_authenticated!, :only => [:edit, :update]
|
||||
|
||||
attr_reader :user
|
||||
|
||||
def new
|
||||
@user = build_user
|
||||
end
|
||||
|
||||
def show
|
||||
@user = User.find_by_nickname!(params[:nickname]).decorate
|
||||
|
||||
collection = @user.asciicasts.
|
||||
includes(:user).
|
||||
order("created_at DESC").
|
||||
page(params[:page]).
|
||||
per(PER_PAGE)
|
||||
|
||||
@asciicasts = PaginatingDecorator.new(collection)
|
||||
user = User.find_by_nickname!(params[:nickname])
|
||||
render locals: { page: UserPresenter.build(user, current_user) }
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -9,7 +9,7 @@ class UserDecorator < ApplicationDecorator
|
||||
wrap_with_link(avatar_image_tag)
|
||||
end
|
||||
|
||||
def fullname_and_nickname
|
||||
def full_name
|
||||
if model.name.present?
|
||||
"#{model.name} (#{model.nickname})"
|
||||
else
|
||||
@ -17,6 +17,10 @@ class UserDecorator < ApplicationDecorator
|
||||
end
|
||||
end
|
||||
|
||||
def joined_at
|
||||
created_at.strftime("%b %-d, %Y")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def wrap_with_link(html)
|
||||
|
@ -50,6 +50,17 @@ class User < ActiveRecord::Base
|
||||
asciicasts.where('id <> ?', asciicast.id).order('RANDOM()').limit(limit)
|
||||
end
|
||||
|
||||
def editable_by?(user)
|
||||
user && user.id == id
|
||||
end
|
||||
|
||||
def paged_asciicasts(page, per_page)
|
||||
asciicasts.
|
||||
includes(:user).
|
||||
order("created_at DESC").
|
||||
paginate(page, per_page)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_auth_token
|
||||
|
61
app/presenters/user_presenter.rb
Normal file
61
app/presenters/user_presenter.rb
Normal file
@ -0,0 +1,61 @@
|
||||
class UserPresenter
|
||||
|
||||
PER_PAGE = 15
|
||||
|
||||
attr_reader :user, :current_user, :page, :per_page
|
||||
|
||||
def self.build(user, current_user, page = nil, per_page = nil)
|
||||
new(user.decorate, current_user, page || 1, per_page || PER_PAGE)
|
||||
end
|
||||
|
||||
def initialize(user, current_user, page, per_page)
|
||||
@user = user
|
||||
@current_user = current_user
|
||||
@page = page
|
||||
@per_page = per_page
|
||||
end
|
||||
|
||||
def title
|
||||
"#{user.nickname}'s profile".html_safe
|
||||
end
|
||||
|
||||
def user_full_name
|
||||
user.full_name
|
||||
end
|
||||
|
||||
def user_joined_at
|
||||
user.joined_at
|
||||
end
|
||||
|
||||
def user_avatar_image_tag
|
||||
user.avatar_image_tag
|
||||
end
|
||||
|
||||
def show_settings?
|
||||
user.editable_by?(current_user)
|
||||
end
|
||||
|
||||
def asciicast_count_text(h)
|
||||
count = h.pluralize(user.asciicast_count, 'asciicast')
|
||||
"#{count} by #{user.nickname}"
|
||||
end
|
||||
|
||||
def user_nickname
|
||||
user.nickname
|
||||
end
|
||||
|
||||
def asciicasts
|
||||
@asciicasts ||= get_asciicasts
|
||||
end
|
||||
|
||||
def current_users_profile?
|
||||
current_user && current_user == user
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_asciicasts
|
||||
PaginatingDecorator.new(user.paged_asciicasts(page, per_page))
|
||||
end
|
||||
|
||||
end
|
@ -1,27 +1,33 @@
|
||||
- content_for(:title, "#{@user.nickname}'s profile".html_safe)
|
||||
- content_for(:title, page.title)
|
||||
|
||||
.profile-page
|
||||
section.cinema
|
||||
.container
|
||||
span.user-avatar = @user.avatar_image_tag
|
||||
span.user-avatar = page.user_avatar_image_tag
|
||||
h1
|
||||
= @user.fullname_and_nickname
|
||||
small
|
||||
' Joined on #{@user.created_at.strftime("%b %-d, %Y")}
|
||||
= page.user_full_name
|
||||
small = "Joined on #{page.user_joined_at}"
|
||||
|
||||
- if current_user == @user
|
||||
- if page.show_settings?
|
||||
p.actions = link_to 'Settings', edit_user_path
|
||||
|
||||
.container
|
||||
h2 #{pluralize @user.asciicast_count, 'asciicast'} by #{@user.nickname}
|
||||
h2 = page.asciicast_count_text(self)
|
||||
.row.asciicast-list
|
||||
.col-md-12
|
||||
= render 'asciicasts/previews', asciicasts: @asciicasts, per_row: 3
|
||||
= paginate @asciicasts
|
||||
|
||||
- if @asciicasts.size == 0
|
||||
- if current_user && current_user.id == @user.id
|
||||
' You haven't recorded anything yet.
|
||||
= link_to 'Record now', docs_path('getting-started')
|
||||
- if page.asciicasts.present?
|
||||
= render 'asciicasts/previews', asciicasts: page.asciicasts, per_row: 3
|
||||
= paginate page.asciicasts
|
||||
- else
|
||||
' #{@user.nickname} hasn't recorded anything yet.
|
||||
- if page.current_users_profile?
|
||||
p
|
||||
' Seems like you haven't recorded anything yet.
|
||||
= link_to 'Record now', docs_path('getting-started')
|
||||
' .
|
||||
p
|
||||
' If you have already recorded an asciicast but you don't see it
|
||||
here then associate it with your account by running
|
||||
code asciinema auth
|
||||
' in your terminal.
|
||||
- else
|
||||
' #{page.user_nickname} hasn't recorded anything yet.
|
||||
|
@ -65,8 +65,8 @@ describe UserDecorator do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#fullname_and_nickname' do
|
||||
subject { decorator.fullname_and_nickname }
|
||||
describe '#full_name' do
|
||||
subject { decorator.full_name }
|
||||
|
||||
let(:user) { double('user', nickname: 'sickill', name: name) }
|
||||
|
||||
@ -83,4 +83,12 @@ describe UserDecorator do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#joined_at' do
|
||||
subject { decorator.joined_at }
|
||||
|
||||
let(:user) { double('user', created_at: Time.parse('1970-01-01')) }
|
||||
|
||||
it { should eq('Jan 1, 1970') }
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -136,4 +136,22 @@ describe User do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#editable_by?' do
|
||||
subject { user.editable_by?(other) }
|
||||
|
||||
let(:user) { create(:user) }
|
||||
|
||||
context "when it's the same user" do
|
||||
let(:other) { user }
|
||||
|
||||
it { should be(true) }
|
||||
end
|
||||
|
||||
context "when it's a different user" do
|
||||
let(:other) { create(:user) }
|
||||
|
||||
it { should be(false) }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
167
spec/presenters/user_presenter_spec.rb
Normal file
167
spec/presenters/user_presenter_spec.rb
Normal file
@ -0,0 +1,167 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe UserPresenter do
|
||||
|
||||
describe '.build' do
|
||||
subject { described_class.build(user, current_user, page, per_page) }
|
||||
|
||||
let(:user) { double('user', decorate: decorated_user) }
|
||||
let(:decorated_user) { double('decorated_user') }
|
||||
let(:current_user) { double('current_user') }
|
||||
let(:page) { 2 }
|
||||
let(:per_page) { 5 }
|
||||
|
||||
it "builds presenter instance with given user decorated" do
|
||||
expect(subject.user).to be(decorated_user)
|
||||
end
|
||||
|
||||
it "builds presenter instance with given current_user" do
|
||||
expect(subject.current_user).to be(current_user)
|
||||
end
|
||||
|
||||
it "builds presenter instance with given page" do
|
||||
expect(subject.page).to eq(2)
|
||||
end
|
||||
|
||||
context "when page is nil" do
|
||||
let(:page) { nil }
|
||||
|
||||
it "builds presenter instance with page = 1" do
|
||||
expect(subject.page).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
it "builds presenter instance with given per_page" do
|
||||
expect(subject.per_page).to eq(5)
|
||||
end
|
||||
|
||||
context "when per_page is nil" do
|
||||
let(:per_page) { nil }
|
||||
|
||||
it "builds presenter instance with per_page = PER_PAGE" do
|
||||
expect(subject.per_page).to eq(described_class::PER_PAGE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:presenter) { described_class.new(user, current_user, page, per_page) }
|
||||
let(:user) { double('user', nickname: 'cartman') }
|
||||
let(:current_user) { double('current_user') }
|
||||
let(:page) { 2 }
|
||||
let(:per_page) { 5 }
|
||||
|
||||
let(:view_context) {
|
||||
controller = ApplicationController.new
|
||||
controller.request = ActionController::TestRequest.new
|
||||
controller.view_context
|
||||
}
|
||||
|
||||
describe '#title' do
|
||||
subject { presenter.title }
|
||||
|
||||
it { should eq("cartman's profile") }
|
||||
end
|
||||
|
||||
describe '#user_full_name' do
|
||||
subject { presenter.user_full_name }
|
||||
|
||||
before do
|
||||
allow(user).to receive(:full_name) { 'E.C.' }
|
||||
end
|
||||
|
||||
it { should eq('E.C.') }
|
||||
end
|
||||
|
||||
describe '#user_joined_at' do
|
||||
subject { presenter.user_joined_at }
|
||||
|
||||
before do
|
||||
allow(user).to receive(:joined_at) { 'Jan 1, 1970' }
|
||||
end
|
||||
|
||||
it { should eq('Jan 1, 1970') }
|
||||
end
|
||||
|
||||
describe '#user_avatar_image_tag' do
|
||||
subject { presenter.user_avatar_image_tag }
|
||||
|
||||
before do
|
||||
allow(user).to receive(:avatar_image_tag) { '<img...>' }
|
||||
end
|
||||
|
||||
it { should eq('<img...>') }
|
||||
end
|
||||
|
||||
describe '#show_settings?' do
|
||||
subject { presenter.show_settings? }
|
||||
|
||||
before do
|
||||
allow(user).to receive(:editable_by?).with(current_user) { :right }
|
||||
end
|
||||
|
||||
it { should eq(:right) }
|
||||
end
|
||||
|
||||
describe '#asciicast_count_text' do
|
||||
subject { presenter.asciicast_count_text(view_context) }
|
||||
|
||||
before do
|
||||
allow(user).to receive(:asciicast_count) { 3 }
|
||||
end
|
||||
|
||||
it { should eq('3 asciicasts by cartman') }
|
||||
end
|
||||
|
||||
describe '#user_nickname' do
|
||||
subject { presenter.user_nickname }
|
||||
|
||||
it { should eq('cartman') }
|
||||
end
|
||||
|
||||
describe '#asciicasts' do
|
||||
subject { presenter.asciicasts }
|
||||
|
||||
let(:collection) { [asciicast] }
|
||||
let(:asciicast) { double('asciicast', decorate: double(title: 'quux')) }
|
||||
|
||||
before do
|
||||
allow(user).to receive(:paged_asciicasts) { collection }
|
||||
end
|
||||
|
||||
it "gets user's asciicasts paged" do
|
||||
subject
|
||||
|
||||
expect(user).to have_received(:paged_asciicasts).with(2, 5)
|
||||
end
|
||||
|
||||
it "wraps the asciicasts with paginating decorator" do
|
||||
expect(subject).to respond_to(:current_page)
|
||||
expect(subject).to respond_to(:total_pages)
|
||||
expect(subject).to respond_to(:limit_value)
|
||||
expect(subject.first.title).to eq('quux')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#current_users_profile?' do
|
||||
subject { presenter.current_users_profile? }
|
||||
|
||||
context "when current_user is the same user" do
|
||||
let(:current_user) { user }
|
||||
|
||||
it { should be(true) }
|
||||
end
|
||||
|
||||
context "when current_user is a different user" do
|
||||
let(:current_user) { double('other_user') }
|
||||
|
||||
it { should be(false) }
|
||||
end
|
||||
|
||||
context "when current_user is nil" do
|
||||
let(:current_user) { nil }
|
||||
|
||||
it { should be_falsy }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue
Block a user