Add ability to create posts
This commit is contained in:
parent
f8113c22ab
commit
ade54533e6
22 changed files with 445 additions and 2 deletions
3
app/assets/javascripts/posts.coffee
Normal file
3
app/assets/javascripts/posts.coffee
Normal 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/
|
3
app/assets/stylesheets/posts.scss
Normal file
3
app/assets/stylesheets/posts.scss
Normal 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/
|
55
app/controllers/posts_controller.rb
Normal file
55
app/controllers/posts_controller.rb
Normal 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
15
app/models/post.rb
Normal 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
|
|
@ -2,6 +2,7 @@ RESERVED_SLUGS = %w(new edit)
|
||||||
|
|
||||||
class Subcreddit < ActiveRecord::Base
|
class Subcreddit < ActiveRecord::Base
|
||||||
belongs_to :owner, class_name: 'User'
|
belongs_to :owner, class_name: 'User'
|
||||||
|
has_many :posts
|
||||||
|
|
||||||
attr_accessor :closed
|
attr_accessor :closed
|
||||||
|
|
||||||
|
|
7
app/views/posts/_form.html.slim
Normal file
7
app/views/posts/_form.html.slim
Normal 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
|
0
app/views/posts/create.html.slim
Normal file
0
app/views/posts/create.html.slim
Normal file
0
app/views/posts/destroy.html.slim
Normal file
0
app/views/posts/destroy.html.slim
Normal file
1
app/views/posts/edit.html.slim
Normal file
1
app/views/posts/edit.html.slim
Normal file
|
@ -0,0 +1 @@
|
||||||
|
= render 'form', subcreddit: @subcreddit, post: @post
|
1
app/views/posts/new.html.slim
Normal file
1
app/views/posts/new.html.slim
Normal file
|
@ -0,0 +1 @@
|
||||||
|
= render 'form', subcreddit: @subcreddit, post: @post
|
2
app/views/posts/show.html.slim
Normal file
2
app/views/posts/show.html.slim
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
h1= @post.title
|
||||||
|
= @post.content
|
0
app/views/posts/update.html.slim
Normal file
0
app/views/posts/update.html.slim
Normal file
|
@ -1,3 +1,8 @@
|
||||||
h1= @subcreddit.name
|
h1= @subcreddit.name
|
||||||
- if @subcreddit.closed?
|
- if @subcreddit.closed?
|
||||||
= "Board has been 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]
|
||||||
|
|
|
@ -3,7 +3,10 @@ Rails.application.routes.draw do
|
||||||
get 'signin', to: 'user_sessions#new', as: :signin
|
get 'signin', to: 'user_sessions#new', as: :signin
|
||||||
get 'signout', to: 'user_sessions#destroy', as: :signout
|
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 :user_sessions, only: [:new, :create, :destroy]
|
||||||
resources :users, only: [:new, :create]
|
resources :users, only: [:new, :create]
|
||||||
|
|
||||||
|
|
13
db/migrate/20150714200610_create_posts.rb
Normal file
13
db/migrate/20150714200610_create_posts.rb
Normal 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
|
15
db/schema.rb
15
db/schema.rb
|
@ -11,7 +11,20 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# 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|
|
create_table "subcreddits", force: :cascade do |t|
|
||||||
t.integer "owner_id"
|
t.integer "owner_id"
|
||||||
|
|
162
spec/controllers/posts_controller_spec.rb
Normal file
162
spec/controllers/posts_controller_spec.rb
Normal 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
|
9
spec/factories/post_factory.rb
Normal file
9
spec/factories/post_factory.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
FactoryGirl.define do
|
||||||
|
factory :post do
|
||||||
|
user
|
||||||
|
subcreddit
|
||||||
|
title { Faker::Lorem.sentence }
|
||||||
|
link ''
|
||||||
|
content { Faker::Lorem.paragraph }
|
||||||
|
end
|
||||||
|
end
|
32
spec/features/posts/edit_post_spec.rb
Normal file
32
spec/features/posts/edit_post_spec.rb
Normal 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
|
15
spec/features/posts/lists_posts_spec.rb
Normal file
15
spec/features/posts/lists_posts_spec.rb
Normal 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
|
49
spec/features/posts/new_post_spec.rb
Normal file
49
spec/features/posts/new_post_spec.rb
Normal 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
54
spec/models/post_spec.rb
Normal 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
|
Loading…
Reference in a new issue