Merge branch 'atomaka/feature/post' into 'master'

Add posts

Not complete, but implemented basic posting to subcreddits.  Right now, links aren't taken into account (but basic modeling is in).  Enough to continue.

See merge request !11
This commit is contained in:
Andrew Tomaka 2015-07-14 23:11:15 -04:00
commit 1e3665ab42
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