Merge branch 'atomaka/feature/simple-user-profile' into 'master'

Add a simple user profile

Adds a profile and links to it.  Also includes a refactor on the page header.

See merge request !16
This commit is contained in:
Andrew Tomaka 2015-08-12 15:56:44 -04:00
commit 76610ede87
21 changed files with 128 additions and 18 deletions

View file

@ -1,4 +1,9 @@
class UsersController < ApplicationController
def show
@user = User.friendly.find(params[:id])
@comments = @user.comments
end
def new
@user = User.new
end

View file

@ -3,6 +3,10 @@ module ApplicationHelper
bootstrap_classes[flash_type] || flash_type.to_s
end
def page_header
content_for(:title) || ''
end
private
def bootstrap_classes

View file

@ -16,13 +16,12 @@ class Subcreddit < ActiveRecord::Base
presence: true,
format: /\A(?! )[a-z0-9 ]*(?<! )\z/i,
uniqueness: true, #{ case_sensitive: false },
length: { minimum: 3, maximum: 21 }
length: { minimum: 3, maximum: 21 },
sluguuidless: true
validates :closed,
format: /\A[01]?\z/
validate :slug_does_not_have_uuid
def closed?
self.closed_at != nil
end
@ -36,10 +35,4 @@ class Subcreddit < ActiveRecord::Base
self.closed_at = nil
end
end
def slug_does_not_have_uuid
if self.slug.match /([a-z0-9]+\-){4}[a-z0-9]+\z/
errors.add(:name, 'must be unique')
end
end
end

View file

@ -1,10 +1,17 @@
class User < ActiveRecord::Base
extend FriendlyId
has_secure_password
has_many :comments
has_many :posts
friendly_id :username, use: :slugged
before_save :downcase_email
validates :email, presence: true, uniqueness: true
validates :username, presence: true, uniqueness: true
validates :username, presence: true, uniqueness: true, sluguuidless: true
validates :password, length: { minimum: 8 }
private

View file

@ -0,0 +1,7 @@
class SluguuidlessValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if record.slug.match /([a-z0-9]+\-){4}[a-z0-9]+\z/
record.errors[attribute] << 'must be unique'
end
end
end

View file

@ -10,8 +10,7 @@
= link_to 'Creddit', root_path, class: 'navbar-brand'
.collapse.navbar-collapse
ul.nav.navbar-nav
- if @subcreddit && @subcreddit.name
li= link_to @subcreddit.name, @subcreddit
li= page_header
ul.nav.navbar-nav.navbar-right
- if logged_in?
li= link_to 'Sign Out', signout_path

View file

@ -18,4 +18,4 @@
.title Moderators
.box
ul
li= @subcreddit.owner_username
li= link_to @subcreddit.owner_username, @subcreddit.owner

View file

@ -1,5 +1,7 @@
.comment
p.details= "#{comment.user_username} X points #{distance_of_time_in_words comment.created_at, Time.now} ago"
p.details
== link_to comment.user_username, comment.user
= " X points #{distance_of_time_in_words comment.created_at, Time.now} ago"
p.content= comment.content
ul.links.list-inline
li= link_to 'permalink', subcreddit_post_comment_path(subcreddit, post, comment)

View file

@ -1,3 +1,4 @@
- content_for(:title, link_to(@subcreddit.name, @subcreddit))
== render 'posts/post', post: @post
.alert.alert-info.in-page
p you are viewing a single comment's thread.

View file

@ -1,7 +1,9 @@
.posts.contents
.post.show
p.title= link_to post.title, [post.subcreddit, post]
p.details= "submitted #{distance_of_time_in_words post.created_at, Time.now} ago by #{post.user_username}"
p.details
= "submitted #{distance_of_time_in_words post.created_at, Time.now} ago by "
== link_to post.user_username, post.user
p.content= post.content
ul.links.list-inline
li= link_to "#{post.comments_count} comments", subcreddit_post_path(post.subcreddit, post)

View file

@ -1,3 +1,4 @@
- content_for(:title, link_to(@subcreddit.name, @subcreddit))
== render 'post', post: @post
- if @post.comments?
.title= "all #{@post.comments_count} comments"

View file

@ -1,3 +1,4 @@
- content_for(:title) { link_to @subcreddit.name, @subcreddit }
- if @subcreddit.closed?
= "Board has been closed"
- else
@ -7,7 +8,9 @@
li
.post
p.title= link_to post.title, subcreddit_post_path(@subcreddit, post)
p.details= "submitted #{distance_of_time_in_words post.created_at, Time.now} ago by #{post.user_username}"
p.details
= "submitted #{distance_of_time_in_words post.created_at, Time.now} ago by "
== link_to post.user_username, post.user
ul.links.list-inline
li= link_to "#{post.comments_count} comments", subcreddit_post_path(@subcreddit, post)
li= link_to 'share', ''

View file

@ -0,0 +1,5 @@
- content_for(:title, link_to(@user.username, @user))
.comments.contents
- @comments.each do |comment|
== render 'comments/comment', subcreddit: comment.post.subcreddit, post: comment.post, comment: comment

View file

@ -22,5 +22,8 @@ module Creddit
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
# So our console continues to work
config.autoload_paths += %W["#{config.root}/app/validators/"]
end
end

View file

@ -10,7 +10,7 @@ Rails.application.routes.draw do
end
resources :user_sessions, only: [:new, :create, :destroy]
resources :users, only: [:new, :create]
resources :users, path: 'u', only: [:show, :new, :create]
root to: 'subcreddits#index'
end

View file

@ -0,0 +1,6 @@
class AddFriendlyIdToUser < ActiveRecord::Migration
def change
add_column :users, :slug, :string
add_index :users, :slug, unique: true
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150804145405) do
ActiveRecord::Schema.define(version: 20150806191452) do
create_table "comments", force: :cascade do |t|
t.integer "user_id"
@ -84,6 +84,9 @@ ActiveRecord::Schema.define(version: 20150804145405) do
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
end
add_index "users", ["slug"], name: "index_users_on_slug", unique: true
end

View file

@ -1,6 +1,25 @@
require 'rails_helper'
describe UsersController, type: :controller do
describe '#show' do
let(:user) { create(:user) }
before(:each) { get :show, id: user }
it 'should render :show' do
expect(response).to render_template(:show)
end
it 'should assign user comments to @comments' do
comments = 5.times.collect { create(:comment, user: user) }
expect(assigns(:comments)).to eq(comments)
end
it 'should assign requested User to @user' do
expect(assigns(:user)).to eq(user)
end
end
describe '#new' do
it 'should render :new' do
get :new

View file

@ -0,0 +1,23 @@
require 'rails_helper'
describe 'Profile', type: :feature do
let!(:user) { create(:user) }
it 'should display a user profile' do
visit user_path(user)
expect(page).to have_content(user.username)
end
context 'when the user has commented' do
let!(:comments) { 5.times.collect { create(:comment, user: user) } }
it 'should display user comments' do
visit user_path(user)
comments.each do |comment|
expect(page).to have_content(comment.content)
end
end
end
end

View file

@ -26,4 +26,20 @@ describe ApplicationHelper do
end
end
end
describe '#page_header' do
context 'when title is provided' do
it 'should return the set title' do
allow(helper).to receive(:content_for).with(:title).and_return('Test')
expect(helper.page_header).to eq 'Test'
end
end
context 'when title is not provided' do
it 'should return blank' do
expect(helper.page_header).to be_blank
end
end
end
end

View file

@ -1,10 +1,15 @@
require 'rails_helper'
require 'securerandom'
describe User, type: :model do
let(:user) { build(:user) }
it { should have_secure_password }
it { should have_many :comments }
it { should have_many :posts }
context 'with valid data' do
it 'should be valid' do
expect(user).to be_valid
@ -44,5 +49,11 @@ describe User, type: :model do
user.password = 'a' * 4
expect(user).to be_invalid
end
it 'should not allow a slug with a UUID' do
user.slug = "test-#{SecureRandom.uuid}"
expect(user).to be_invalid
end
end
end