Add ability to create posts

This commit is contained in:
Andrew Tomaka 2015-07-14 16:29:22 -04:00
parent f8113c22ab
commit ade54533e6
22 changed files with 445 additions and 2 deletions

View file

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View file

@ -0,0 +1,3 @@
// Place all the styles related to the Posts controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -0,0 +1,55 @@
class PostsController < ApplicationController
before_filter :set_post, except: [:index, :new, :create]
before_filter :set_subcreddit
def show
end
def new
@post = Post.new
end
def create
@post = @subcreddit.posts.build(post_params)
@post.user = current_user
if @post.save
redirect_to subcreddit_post_path(@subcreddit, @post),
notice: 'Post created'
else
render :new
end
end
def edit
end
def update
if @post.update(post_params)
redirect_to subcreddit_post_path(@subcreddit, @post),
notice: 'Post was updated'
else
render :edit
end
end
def destroy
@post.destroy
redirect_to subcreddits_path(@subcreddit), notice: 'Post was deleted'
end
private
def post_params
params.require(:post).permit(:title, :link, :content, :subcreddit_id)
end
def set_subcreddit
@subcreddit = Subcreddit.find_by_slug(params['subcreddit_id'])
end
def set_post
@post = Post.find(params[:id])
end
end

15
app/models/post.rb Normal file
View file

@ -0,0 +1,15 @@
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :subcreddit
validates :title,
presence: true,
length: { maximum: 300 }
validates :content,
length: { maximum: 15000 }
def to_param
"#{self.id}-#{self.title.parameterize}"
end
end

View file

@ -2,6 +2,7 @@ RESERVED_SLUGS = %w(new edit)
class Subcreddit < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_many :posts
attr_accessor :closed

View file

@ -0,0 +1,7 @@
= simple_form_for [subcreddit, post] do |f|
.form-inputs
= f.input :title
= f.input :link
= f.input :content
.form-actions
= f.button :submit

View file

View file

View file

@ -0,0 +1 @@
= render 'form', subcreddit: @subcreddit, post: @post

View file

@ -0,0 +1 @@
= render 'form', subcreddit: @subcreddit, post: @post

View file

@ -0,0 +1,2 @@
h1= @post.title
= @post.content

View file

View file

@ -1,3 +1,8 @@
h1= @subcreddit.name
- if @subcreddit.closed?
= "Board has been closed"
- else
= link_to 'New Post', new_subcreddit_post_path(@subcreddit)
ul
- @subcreddit.posts.each do |post|
li= link_to post.title, [@subcreddit, post]

View file

@ -3,7 +3,10 @@ Rails.application.routes.draw do
get 'signin', to: 'user_sessions#new', as: :signin
get 'signout', to: 'user_sessions#destroy', as: :signout
resources :subcreddits, path: 'c', except: [:destroy]
resources :subcreddits, path: 'c', except: [:destroy] do
resources :posts, except: [:index]
end
resources :user_sessions, only: [:new, :create, :destroy]
resources :users, only: [:new, :create]

View file

@ -0,0 +1,13 @@
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.references :user, index: true, foreign_key: true
t.references :subcreddit, index: true, foreign_key: true
t.string :title
t.string :link
t.text :content
t.timestamps null: false
end
end
end

View file

@ -11,7 +11,20 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150713045745) do
ActiveRecord::Schema.define(version: 20150714200610) do
create_table "posts", force: :cascade do |t|
t.integer "user_id"
t.integer "subcreddit_id"
t.string "title"
t.string "link"
t.text "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "posts", ["subcreddit_id"], name: "index_posts_on_subcreddit_id"
add_index "posts", ["user_id"], name: "index_posts_on_user_id"
create_table "subcreddits", force: :cascade do |t|
t.integer "owner_id"

View file

@ -0,0 +1,162 @@
require 'rails_helper'
describe PostsController, type: :controller do
let!(:user) { build(:user) }
let!(:subcreddit) { create(:subcreddit) }
let(:data) do
{
title: 'A New Post',
content: 'Here is some content for that post'
}
end
before(:each) do
allow_any_instance_of(ApplicationController)
.to receive(:current_user).and_return(user)
end
describe '#show' do
let(:post) { create(:post) }
before(:each) { get :show, subcreddit_id: post.subcreddit, id: post }
it 'should render :show' do
expect(response).to render_template(:show)
end
it 'should assign correct Post to @post' do
expect(assigns(:post)).to eq(post)
end
end
describe '#new' do
let(:post) { build(:post) }
before(:each) { get :new, subcreddit_id: post.subcreddit }
it 'should render :new' do
expect(response).to render_template(:new)
end
it 'should assign new Post to @post' do
expect(assigns(:post)).to be_a_new(Post)
end
end
describe '#create' do
context 'with valid data' do
it 'should create a post' do
expect { post :create, subcreddit_id: subcreddit, post: data }
.to change(Post, :count).by(1)
end
it 'should redirect to the new post' do
expect(post :create, subcreddit_id: subcreddit, post: data)
.to redirect_to(subcreddit_post_path(assigns(:post).subcreddit,
assigns(:post)))
end
it 'should send a notice flash message' do
post :create, subcreddit_id: subcreddit, post: data
expect(flash[:notice]).to be_present
end
end
context 'with invalid data' do
before(:each) { data['title'] = '' }
it 'should not create a post' do
expect { post :create, subcreddit_id: subcreddit, post: data }
.to change(Post, :count).by(0)
end
it 'should render :new' do
post :create, subcreddit_id: subcreddit, post: data
expect(response).to render_template(:new)
end
end
end
context '#edit' do
let!(:post) { create(:post) }
before(:each) { get :edit, id: post, subcreddit_id: post.subcreddit }
context 'with valid post' do
it 'should render :edit' do
expect(response).to render_template(:edit)
end
it 'should assign correct Post to @post' do
expect(assigns(:post)).to eq(post)
end
end
end
context '#update' do
let!(:post) { create(:post) }
let(:data) do
{
title: 'New title',
content: 'New content'
}
end
context 'with valid data' do
before(:each) do
put :update, id: post, subcreddit_id: post.subcreddit, post: data
end
it 'should assign correct Post to @post' do
expect(assigns(:post)).to eq(post)
end
it 'should update the post' do
post.reload
expect(post.title).to eq(data[:title])
expect(post.content).to eq(data[:content])
end
it 'should redirect to the post' do
expect(response)
.to redirect_to(subcreddit_post_path(assigns(:post).subcreddit,
assigns(:post)))
end
it 'should display a notice flash message' do
expect(flash[:notice]).to be_present
end
end
context 'with invalid data' do
before(:each) { data[:title] = '' }
it 'should render :edit' do
put :update, id: post, subcreddit_id: post.subcreddit, post: data
expect(response).to render_template(:edit)
end
end
end
context '#destroy' do
let!(:post) { create(:post, subcreddit: subcreddit) }
it 'should delete the post' do
expect { delete :destroy, subcreddit_id: subcreddit, id: post }
.to change(Post, :count).by(-1)
end
it 'should redirect to the subcreddit index' do
expect(delete :destroy, subcreddit_id: subcreddit, id: post)
.to redirect_to(subcreddits_path(subcreddit))
end
it 'should flash notify that the post was deleted' do
delete :destroy, subcreddit_id: subcreddit, id: post
expect(flash[:notice]).to be_present
end
end
end

View file

@ -0,0 +1,9 @@
FactoryGirl.define do
factory :post do
user
subcreddit
title { Faker::Lorem.sentence }
link ''
content { Faker::Lorem.paragraph }
end
end

View file

@ -0,0 +1,32 @@
require 'rails_helper'
describe 'Edit Post', type: :feature do
context 'when signed in' do
let!(:user) { create(:user) }
let!(:subcreddit) { create(:subcreddit) }
let!(:post) { create(:post, subcreddit: subcreddit, user: user) }
let(:new_post) { build_stubbed(:post) }
before(:each) { signin(user: user) }
context 'with valid data' do
before(:each) do
visit edit_subcreddit_post_path(subcreddit, post)
fill_in :post_title, with: new_post.title
fill_in :post_link, with: new_post.link
fill_in :post_content, with: new_post.content
click_button 'Update Post'
end
it 'should notify that the post was edited' do
expect(page).to have_content('updated')
end
it 'should show the post' do
expect(page).to have_content(new_post.title)
end
end
end
end

View file

@ -0,0 +1,15 @@
require 'rails_helper'
describe 'List Posts', type: :feature do
let!(:subcreddit) { create(:subcreddit) }
let!(:posts) { 10.times.collect { create(:post, subcreddit: subcreddit) } }
it 'should list all posts for a subcreddit' do
visit subcreddit_path(subcreddit)
posts.each do |post|
expect(page)
.to have_link(post.title, subcreddit_post_path(post, post.subcreddit))
end
end
end

View file

@ -0,0 +1,49 @@
require 'rails_helper'
describe 'New Post', type: :feature do
context 'when signed in' do
let!(:user) { create(:user) }
let!(:subcreddit) { create(:subcreddit) }
let!(:post) { build(:post, subcreddit: subcreddit) }
before(:each) { signin(user: user) }
context 'with valid data' do
before(:each) do
visit new_subcreddit_post_path(subcreddit)
fill_in :post_title, with: post.title
fill_in :post_link, with: post.link
fill_in :post_content, with: post.content
click_button 'Create Post'
end
it 'should notify that a new post was created' do
expect(page).to have_content('created')
end
it 'should display the new post' do
expect(page).to have_content(post.title)
end
end
context 'with invalid data' do
before(:each) do
visit new_subcreddit_post_path(subcreddit)
post.title = ''
fill_in :post_title, with: post.title
fill_in :post_link, with: post.link
fill_in :post_content, with: post.content
click_button 'Create Post'
end
it 'should display errors' do
expect(page).to have_content("can't be blank")
end
end
end
end

54
spec/models/post_spec.rb Normal file
View file

@ -0,0 +1,54 @@
require 'rails_helper'
describe Post, type: :model do
let(:post) { build(:post) }
it { should belong_to(:user) }
it { should belong_to(:subcreddit) }
context 'with valid data' do
it 'should be valid' do
expect(post).to be_valid
end
it 'should allow blank content' do
post.content = ''
expect(post).to be_valid
end
it 'should allow a blank link' do
post.link = ''
expect(post).to be_valid
end
end
context 'with invalid data' do
it 'should not allow a blank title' do
post.title = ''
expect(post).to be_invalid
end
it 'should not allow a long title' do
post.title = 'a' * 301
expect(post).to be_invalid
end
it 'should not allow long content' do
post.content = 'a' * 15001
expect(post).to be_invalid
end
end
context '#to_param' do
it 'generates the correct param' do
post.save
expect(post.to_param).to eq("#{post.id}-#{post.title.parameterize}")
end
end
end