From 3cff543184b59fb22f9f361b5d084a7460bec9dc Mon Sep 17 00:00:00 2001 From: gnattery Date: Wed, 6 Feb 2013 14:49:49 +1100 Subject: [PATCH 1/7] rails g scaffold Comment --- app/assets/javascripts/comments.js.coffee | 3 + app/controllers/comments_controller.rb | 83 ++++++++++ app/helpers/comments_helper.rb | 2 + app/models/comment.rb | 3 + app/views/comments/_form.html.haml | 19 +++ app/views/comments/edit.html.haml | 7 + app/views/comments/index.html.haml | 23 +++ app/views/comments/new.html.haml | 5 + app/views/comments/show.html.haml | 15 ++ config/routes.rb | 3 + db/migrate/20130206033956_create_comments.rb | 11 ++ db/schema.rb | 10 +- spec/controllers/comments_controller_spec.rb | 164 +++++++++++++++++++ spec/factories/comments.rb | 9 + spec/models/comment_spec.rb | 2 + spec/requests/comments_spec.rb | 11 ++ spec/routing/comments_routing_spec.rb | 35 ++++ spec/views/comments/edit.html.haml_spec.rb | 22 +++ spec/views/comments/index.html.haml_spec.rb | 26 +++ spec/views/comments/new.html.haml_spec.rb | 22 +++ spec/views/comments/show.html.haml_spec.rb | 19 +++ 21 files changed, 493 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/comments.js.coffee create mode 100644 app/controllers/comments_controller.rb create mode 100644 app/helpers/comments_helper.rb create mode 100644 app/models/comment.rb create mode 100644 app/views/comments/_form.html.haml create mode 100644 app/views/comments/edit.html.haml create mode 100644 app/views/comments/index.html.haml create mode 100644 app/views/comments/new.html.haml create mode 100644 app/views/comments/show.html.haml create mode 100644 db/migrate/20130206033956_create_comments.rb create mode 100644 spec/controllers/comments_controller_spec.rb create mode 100644 spec/factories/comments.rb create mode 100644 spec/models/comment_spec.rb create mode 100644 spec/requests/comments_spec.rb create mode 100644 spec/routing/comments_routing_spec.rb create mode 100644 spec/views/comments/edit.html.haml_spec.rb create mode 100644 spec/views/comments/index.html.haml_spec.rb create mode 100644 spec/views/comments/new.html.haml_spec.rb create mode 100644 spec/views/comments/show.html.haml_spec.rb diff --git a/app/assets/javascripts/comments.js.coffee b/app/assets/javascripts/comments.js.coffee new file mode 100644 index 000000000..761567942 --- /dev/null +++ b/app/assets/javascripts/comments.js.coffee @@ -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://jashkenas.github.com/coffee-script/ diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb new file mode 100644 index 000000000..dfb5f63c6 --- /dev/null +++ b/app/controllers/comments_controller.rb @@ -0,0 +1,83 @@ +class CommentsController < ApplicationController + # GET /comments + # GET /comments.json + def index + @comments = Comment.all + + respond_to do |format| + format.html # index.html.erb + format.json { render json: @comments } + end + end + + # GET /comments/1 + # GET /comments/1.json + def show + @comment = Comment.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @comment } + end + end + + # GET /comments/new + # GET /comments/new.json + def new + @comment = Comment.new + + respond_to do |format| + format.html # new.html.erb + format.json { render json: @comment } + end + end + + # GET /comments/1/edit + def edit + @comment = Comment.find(params[:id]) + end + + # POST /comments + # POST /comments.json + def create + @comment = Comment.new(params[:comment]) + + respond_to do |format| + if @comment.save + format.html { redirect_to @comment, notice: 'Comment was successfully created.' } + format.json { render json: @comment, status: :created, location: @comment } + else + format.html { render action: "new" } + format.json { render json: @comment.errors, status: :unprocessable_entity } + end + end + end + + # PUT /comments/1 + # PUT /comments/1.json + def update + @comment = Comment.find(params[:id]) + + respond_to do |format| + if @comment.update_attributes(params[:comment]) + format.html { redirect_to @comment, notice: 'Comment was successfully updated.' } + format.json { head :no_content } + else + format.html { render action: "edit" } + format.json { render json: @comment.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /comments/1 + # DELETE /comments/1.json + def destroy + @comment = Comment.find(params[:id]) + @comment.destroy + + respond_to do |format| + format.html { redirect_to comments_url } + format.json { head :no_content } + end + end +end diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb new file mode 100644 index 000000000..0ec9ca5f2 --- /dev/null +++ b/app/helpers/comments_helper.rb @@ -0,0 +1,2 @@ +module CommentsHelper +end diff --git a/app/models/comment.rb b/app/models/comment.rb new file mode 100644 index 000000000..7dfdd6c41 --- /dev/null +++ b/app/models/comment.rb @@ -0,0 +1,3 @@ +class Comment < ActiveRecord::Base + attr_accessible :author_id, :body, :post_id +end diff --git a/app/views/comments/_form.html.haml b/app/views/comments/_form.html.haml new file mode 100644 index 000000000..4a7db6193 --- /dev/null +++ b/app/views/comments/_form.html.haml @@ -0,0 +1,19 @@ += form_for @comment do |f| + - if @comment.errors.any? + #error_explanation + %h2= "#{pluralize(@comment.errors.count, "error")} prohibited this comment from being saved:" + %ul + - @comment.errors.full_messages.each do |msg| + %li= msg + + .field + = f.label :post_id + = f.number_field :post_id + .field + = f.label :author_id + = f.number_field :author_id + .field + = f.label :body + = f.text_area :body + .actions + = f.submit 'Save' diff --git a/app/views/comments/edit.html.haml b/app/views/comments/edit.html.haml new file mode 100644 index 000000000..da858a956 --- /dev/null +++ b/app/views/comments/edit.html.haml @@ -0,0 +1,7 @@ +%h1 Editing comment + += render 'form' + += link_to 'Show', @comment +\| += link_to 'Back', comments_path diff --git a/app/views/comments/index.html.haml b/app/views/comments/index.html.haml new file mode 100644 index 000000000..14dffe74e --- /dev/null +++ b/app/views/comments/index.html.haml @@ -0,0 +1,23 @@ +%h1 Listing comments + +%table + %tr + %th Post + %th Author + %th Body + %th + %th + %th + + - @comments.each do |comment| + %tr + %td= comment.post_id + %td= comment.author_id + %td= comment.body + %td= link_to 'Show', comment + %td= link_to 'Edit', edit_comment_path(comment) + %td= link_to 'Destroy', comment, method: :delete, data: { confirm: 'Are you sure?' } + +%br + += link_to 'New Comment', new_comment_path diff --git a/app/views/comments/new.html.haml b/app/views/comments/new.html.haml new file mode 100644 index 000000000..874b7895b --- /dev/null +++ b/app/views/comments/new.html.haml @@ -0,0 +1,5 @@ +%h1 New comment + += render 'form' + += link_to 'Back', comments_path diff --git a/app/views/comments/show.html.haml b/app/views/comments/show.html.haml new file mode 100644 index 000000000..79b7ff31e --- /dev/null +++ b/app/views/comments/show.html.haml @@ -0,0 +1,15 @@ +%p#notice= notice + +%p + %b Post: + = @comment.post_id +%p + %b Author: + = @comment.author_id +%p + %b Body: + = @comment.body + += link_to 'Edit', edit_comment_path(@comment) +\| += link_to 'Back', comments_path diff --git a/config/routes.rb b/config/routes.rb index fe39180dd..4e74cbac4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,7 @@ Growstuff::Application.routes.draw do + resources :comments + + devise_for :members resources :plantings diff --git a/db/migrate/20130206033956_create_comments.rb b/db/migrate/20130206033956_create_comments.rb new file mode 100644 index 000000000..6fc9d9279 --- /dev/null +++ b/db/migrate/20130206033956_create_comments.rb @@ -0,0 +1,11 @@ +class CreateComments < ActiveRecord::Migration + def change + create_table :comments do |t| + t.integer :post_id + t.integer :author_id + t.text :body + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 9ee8655cc..ceb9be432 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,15 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130118043431) do +ActiveRecord::Schema.define(:version => 20130206033956) do + + create_table "comments", :force => true do |t| + t.integer "post_id" + t.integer "author_id" + t.text "body" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end create_table "crops", :force => true do |t| t.string "system_name", :null => false diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb new file mode 100644 index 000000000..fdde2fc7d --- /dev/null +++ b/spec/controllers/comments_controller_spec.rb @@ -0,0 +1,164 @@ +require 'spec_helper' + +# This spec was generated by rspec-rails when you ran the scaffold generator. +# It demonstrates how one might use RSpec to specify the controller code that +# was generated by Rails when you ran the scaffold generator. +# +# It assumes that the implementation code is generated by the rails scaffold +# generator. If you are using any extension libraries to generate different +# controller code, this generated spec may or may not pass. +# +# It only uses APIs available in rails and/or rspec-rails. There are a number +# of tools you can use to make these specs even more expressive, but we're +# sticking to rails and rspec-rails APIs to keep things simple and stable. +# +# Compared to earlier versions of this generator, there is very limited use of +# stubs and message expectations in this spec. Stubs are only used when there +# is no simpler way to get a handle on the object needed for the example. +# Message expectations are only used when there is no simpler way to specify +# that an instance is receiving a specific message. + +describe CommentsController do + + # This should return the minimal set of attributes required to create a valid + # Comment. As you add validations to Comment, be sure to + # update the return value of this method accordingly. + def valid_attributes + { "post_id" => "1" } + end + + # This should return the minimal set of values that should be in the session + # in order to pass any filters (e.g. authentication) defined in + # CommentsController. Be sure to keep this updated too. + def valid_session + {} + end + + describe "GET index" do + it "assigns all comments as @comments" do + comment = Comment.create! valid_attributes + get :index, {}, valid_session + assigns(:comments).should eq([comment]) + end + end + + describe "GET show" do + it "assigns the requested comment as @comment" do + comment = Comment.create! valid_attributes + get :show, {:id => comment.to_param}, valid_session + assigns(:comment).should eq(comment) + end + end + + describe "GET new" do + it "assigns a new comment as @comment" do + get :new, {}, valid_session + assigns(:comment).should be_a_new(Comment) + end + end + + describe "GET edit" do + it "assigns the requested comment as @comment" do + comment = Comment.create! valid_attributes + get :edit, {:id => comment.to_param}, valid_session + assigns(:comment).should eq(comment) + end + end + + describe "POST create" do + describe "with valid params" do + it "creates a new Comment" do + expect { + post :create, {:comment => valid_attributes}, valid_session + }.to change(Comment, :count).by(1) + end + + it "assigns a newly created comment as @comment" do + post :create, {:comment => valid_attributes}, valid_session + assigns(:comment).should be_a(Comment) + assigns(:comment).should be_persisted + end + + it "redirects to the created comment" do + post :create, {:comment => valid_attributes}, valid_session + response.should redirect_to(Comment.last) + end + end + + describe "with invalid params" do + it "assigns a newly created but unsaved comment as @comment" do + # Trigger the behavior that occurs when invalid params are submitted + Comment.any_instance.stub(:save).and_return(false) + post :create, {:comment => { "post_id" => "invalid value" }}, valid_session + assigns(:comment).should be_a_new(Comment) + end + + it "re-renders the 'new' template" do + # Trigger the behavior that occurs when invalid params are submitted + Comment.any_instance.stub(:save).and_return(false) + post :create, {:comment => { "post_id" => "invalid value" }}, valid_session + response.should render_template("new") + end + end + end + + describe "PUT update" do + describe "with valid params" do + it "updates the requested comment" do + comment = Comment.create! valid_attributes + # Assuming there are no other comments in the database, this + # specifies that the Comment created on the previous line + # receives the :update_attributes message with whatever params are + # submitted in the request. + Comment.any_instance.should_receive(:update_attributes).with({ "post_id" => "1" }) + put :update, {:id => comment.to_param, :comment => { "post_id" => "1" }}, valid_session + end + + it "assigns the requested comment as @comment" do + comment = Comment.create! valid_attributes + put :update, {:id => comment.to_param, :comment => valid_attributes}, valid_session + assigns(:comment).should eq(comment) + end + + it "redirects to the comment" do + comment = Comment.create! valid_attributes + put :update, {:id => comment.to_param, :comment => valid_attributes}, valid_session + response.should redirect_to(comment) + end + end + + describe "with invalid params" do + it "assigns the comment as @comment" do + comment = Comment.create! valid_attributes + # Trigger the behavior that occurs when invalid params are submitted + Comment.any_instance.stub(:save).and_return(false) + put :update, {:id => comment.to_param, :comment => { "post_id" => "invalid value" }}, valid_session + assigns(:comment).should eq(comment) + end + + it "re-renders the 'edit' template" do + comment = Comment.create! valid_attributes + # Trigger the behavior that occurs when invalid params are submitted + Comment.any_instance.stub(:save).and_return(false) + put :update, {:id => comment.to_param, :comment => { "post_id" => "invalid value" }}, valid_session + response.should render_template("edit") + end + end + end + + describe "DELETE destroy" do + it "destroys the requested comment" do + comment = Comment.create! valid_attributes + expect { + delete :destroy, {:id => comment.to_param}, valid_session + }.to change(Comment, :count).by(-1) + end + + it "redirects to the comments list" do + comment = Comment.create! valid_attributes + delete :destroy, {:id => comment.to_param}, valid_session + response.should redirect_to(comments_url) + end + end + +end diff --git a/spec/factories/comments.rb b/spec/factories/comments.rb new file mode 100644 index 000000000..9a067805f --- /dev/null +++ b/spec/factories/comments.rb @@ -0,0 +1,9 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :comment do + post_id 1 + author_id 1 + body "MyText" + end +end diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb new file mode 100644 index 000000000..51f5efc44 --- /dev/null +++ b/spec/models/comment_spec.rb @@ -0,0 +1,2 @@ +require 'spec_helper' + diff --git a/spec/requests/comments_spec.rb b/spec/requests/comments_spec.rb new file mode 100644 index 000000000..7a38a46e8 --- /dev/null +++ b/spec/requests/comments_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe "Comments" do + describe "GET /comments" do + it "works! (now write some real specs)" do + # Run the generator again with the --webrat flag if you want to use webrat methods/matchers + get comments_path + response.status.should be(200) + end + end +end diff --git a/spec/routing/comments_routing_spec.rb b/spec/routing/comments_routing_spec.rb new file mode 100644 index 000000000..73c80563e --- /dev/null +++ b/spec/routing/comments_routing_spec.rb @@ -0,0 +1,35 @@ +require "spec_helper" + +describe CommentsController do + describe "routing" do + + it "routes to #index" do + get("/comments").should route_to("comments#index") + end + + it "routes to #new" do + get("/comments/new").should route_to("comments#new") + end + + it "routes to #show" do + get("/comments/1").should route_to("comments#show", :id => "1") + end + + it "routes to #edit" do + get("/comments/1/edit").should route_to("comments#edit", :id => "1") + end + + it "routes to #create" do + post("/comments").should route_to("comments#create") + end + + it "routes to #update" do + put("/comments/1").should route_to("comments#update", :id => "1") + end + + it "routes to #destroy" do + delete("/comments/1").should route_to("comments#destroy", :id => "1") + end + + end +end diff --git a/spec/views/comments/edit.html.haml_spec.rb b/spec/views/comments/edit.html.haml_spec.rb new file mode 100644 index 000000000..b3d496b9e --- /dev/null +++ b/spec/views/comments/edit.html.haml_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "comments/edit" do + before(:each) do + @comment = assign(:comment, stub_model(Comment, + :post_id => 1, + :author_id => 1, + :body => "MyText" + )) + end + + it "renders the edit comment form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => comments_path(@comment), :method => "post" do + assert_select "input#comment_post_id", :name => "comment[post_id]" + assert_select "input#comment_author_id", :name => "comment[author_id]" + assert_select "textarea#comment_body", :name => "comment[body]" + end + end +end diff --git a/spec/views/comments/index.html.haml_spec.rb b/spec/views/comments/index.html.haml_spec.rb new file mode 100644 index 000000000..fe8aa0338 --- /dev/null +++ b/spec/views/comments/index.html.haml_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe "comments/index" do + before(:each) do + assign(:comments, [ + stub_model(Comment, + :post_id => 1, + :author_id => 2, + :body => "MyText" + ), + stub_model(Comment, + :post_id => 1, + :author_id => 2, + :body => "MyText" + ) + ]) + end + + it "renders a list of comments" do + render + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "tr>td", :text => 1.to_s, :count => 2 + assert_select "tr>td", :text => 2.to_s, :count => 2 + assert_select "tr>td", :text => "MyText".to_s, :count => 2 + end +end diff --git a/spec/views/comments/new.html.haml_spec.rb b/spec/views/comments/new.html.haml_spec.rb new file mode 100644 index 000000000..cdae1772f --- /dev/null +++ b/spec/views/comments/new.html.haml_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "comments/new" do + before(:each) do + assign(:comment, stub_model(Comment, + :post_id => 1, + :author_id => 1, + :body => "MyText" + ).as_new_record) + end + + it "renders new comment form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => comments_path, :method => "post" do + assert_select "input#comment_post_id", :name => "comment[post_id]" + assert_select "input#comment_author_id", :name => "comment[author_id]" + assert_select "textarea#comment_body", :name => "comment[body]" + end + end +end diff --git a/spec/views/comments/show.html.haml_spec.rb b/spec/views/comments/show.html.haml_spec.rb new file mode 100644 index 000000000..3760f18ff --- /dev/null +++ b/spec/views/comments/show.html.haml_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe "comments/show" do + before(:each) do + @comment = assign(:comment, stub_model(Comment, + :post_id => 1, + :author_id => 2, + :body => "MyText" + )) + end + + it "renders attributes in

" do + render + # Run the generator again with the --webrat flag if you want to use webrat matchers + rendered.should match(/1/) + rendered.should match(/2/) + rendered.should match(/MyText/) + end +end From 6da3e4fae5cda39347059658eb87e354fd39d457 Mon Sep 17 00:00:00 2001 From: gnattery Date: Wed, 6 Feb 2013 15:20:44 +1100 Subject: [PATCH 2/7] Added associations and tested them --- app/models/comment.rb | 2 ++ app/models/member.rb | 1 + app/models/post.rb | 1 + spec/factories/comments.rb | 8 +++----- spec/models/comment_spec.rb | 14 ++++++++++++++ spec/models/member_spec.rb | 6 ++++++ spec/models/post_spec.rb | 7 +++++++ 7 files changed, 34 insertions(+), 5 deletions(-) diff --git a/app/models/comment.rb b/app/models/comment.rb index 7dfdd6c41..09f25e13b 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,3 +1,5 @@ class Comment < ActiveRecord::Base attr_accessible :author_id, :body, :post_id + belongs_to :author, :class_name => 'Member' + belongs_to :post end diff --git a/app/models/member.rb b/app/models/member.rb index 8f2548d8b..e882d36c7 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -3,6 +3,7 @@ class Member < ActiveRecord::Base friendly_id :login_name, use: :slugged has_many :posts, :foreign_key => 'author_id' + has_many :comments, :foreign_key => 'author_id' has_many :gardens, :foreign_key => 'owner_id' # Include default devise modules. Others available are: diff --git a/app/models/post.rb b/app/models/post.rb index 564cf5f00..de3c9cdcf 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -3,6 +3,7 @@ class Post < ActiveRecord::Base friendly_id :author_date_subject, use: :slugged attr_accessible :body, :subject, :author_id belongs_to :author, :class_name => 'Member' + has_many :comments default_scope order("created_at desc") def author_date_subject diff --git a/spec/factories/comments.rb b/spec/factories/comments.rb index 9a067805f..404ac5313 100644 --- a/spec/factories/comments.rb +++ b/spec/factories/comments.rb @@ -1,9 +1,7 @@ -# Read about factories at https://github.com/thoughtbot/factory_girl - FactoryGirl.define do factory :comment do - post_id 1 - author_id 1 - body "MyText" + post + author + body "OMG LOL" end end diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 51f5efc44..6681fca18 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -1,2 +1,16 @@ require 'spec_helper' +describe Comment do + + before(:each) do + @comment = FactoryGirl.create(:comment) + end + + it "belongs to a post" do + @comment.post.should be_an_instance_of Post + end + + it "belongs to an author" do + @comment.author.should be_an_instance_of Member + end +end diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index bd29cd594..620d144a4 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -44,6 +44,12 @@ describe 'member' do @member.gardens.first.name.should eq "Garden" end + it "has many comments" do + @member.save + @comment1 = FactoryGirl.create(:comment, :author => @member) + @comment2 = FactoryGirl.create(:comment, :author => @member) + @member.comments.length.should == 2 + end end context 'no TOS agreement' do diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 90e7c2cbc..e889322eb 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -20,4 +20,11 @@ describe Post do @datestr.length.should == 4 + @time.year.to_s.size @post.slug.should == "#{@member.login_name}-#{@datestr}-a-post" end + + it "has many comments" do + @post = FactoryGirl.create(:post, :author => @member) + @comment1 = FactoryGirl.create(:comment, :post => @post) + @comment2 = FactoryGirl.create(:comment, :post => @post) + @post.comments.length.should == 2 + end end From a0a88bee1159d40ed7588da1c34d3c2076002660 Mon Sep 17 00:00:00 2001 From: Skud Date: Fri, 8 Feb 2013 14:14:07 +1100 Subject: [PATCH 3/7] comment form shouldn't have author/post fields --- app/controllers/comments_controller.rb | 1 + app/views/comments/_form.html.haml | 8 +------- spec/views/comments/new.html.haml_spec.rb | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index dfb5f63c6..bc52a3a61 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -40,6 +40,7 @@ class CommentsController < ApplicationController # POST /comments # POST /comments.json def create + params[:comment][:author_id] = current_member.id @comment = Comment.new(params[:comment]) respond_to do |format| diff --git a/app/views/comments/_form.html.haml b/app/views/comments/_form.html.haml index 4a7db6193..0cfdf1487 100644 --- a/app/views/comments/_form.html.haml +++ b/app/views/comments/_form.html.haml @@ -6,14 +6,8 @@ - @comment.errors.full_messages.each do |msg| %li= msg - .field - = f.label :post_id - = f.number_field :post_id - .field - = f.label :author_id - = f.number_field :author_id .field = f.label :body - = f.text_area :body + = f.text_area :body, :rows => 6, :class => 'input-block-level' .actions = f.submit 'Save' diff --git a/spec/views/comments/new.html.haml_spec.rb b/spec/views/comments/new.html.haml_spec.rb index cdae1772f..90ab45e86 100644 --- a/spec/views/comments/new.html.haml_spec.rb +++ b/spec/views/comments/new.html.haml_spec.rb @@ -14,8 +14,6 @@ describe "comments/new" do # Run the generator again with the --webrat flag if you want to use webrat matchers assert_select "form", :action => comments_path, :method => "post" do - assert_select "input#comment_post_id", :name => "comment[post_id]" - assert_select "input#comment_author_id", :name => "comment[author_id]" assert_select "textarea#comment_body", :name => "comment[body]" end end From f66b4a64a35482116aec45e1fae75b81006bfc0a Mon Sep 17 00:00:00 2001 From: Skud Date: Fri, 8 Feb 2013 14:22:49 +1100 Subject: [PATCH 4/7] added comment button to posts --- app/models/ability.rb | 8 ++++++-- app/views/posts/_single.html.haml | 4 ++++ spec/views/posts/show.html.haml_spec.rb | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index d80864758..19c89e177 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -20,12 +20,16 @@ class Ability can :update, ScientificName can :destroy, ScientificName - # anyone can create a post, but only the author can edit/destroy - # it. + # anyone can create a post, or comment on a post, + # but only the author can edit/destroy it. can :create, Post can :update, Post, :author_id => member.id can :destroy, Post, :author_id => member.id + can :create, Comment + can :update, Comment, :author_id => member.id + can :destroy, Comment, :author_id => member.id + # same deal for gardens and plantings can :create, Garden can :update, Garden, :owner_id => member.id diff --git a/app/views/posts/_single.html.haml b/app/views/posts/_single.html.haml index fa6c40f3e..f8d31f2fb 100644 --- a/app/views/posts/_single.html.haml +++ b/app/views/posts/_single.html.haml @@ -24,3 +24,7 @@ - if can? :destroy, post = link_to 'Delete', post, method: :delete, | data: { confirm: 'Are you sure?' }, :class => 'btn' + + - if can? :create, Comment + .post-actions + =link_to 'Comment', new_comment_path(), :class => 'btn' diff --git a/spec/views/posts/show.html.haml_spec.rb b/spec/views/posts/show.html.haml_spec.rb index d42cff34a..6a4cf0039 100644 --- a/spec/views/posts/show.html.haml_spec.rb +++ b/spec/views/posts/show.html.haml_spec.rb @@ -34,4 +34,19 @@ describe "posts/show" do rendered.should_not match(/a href="http:\/\/evil.com"/) end + context "signed in" do + before(:each) do + sign_in @author + controller.stub(:current_user) { @author } + @post = assign(:post, + FactoryGirl.create(:post, :author => @author)) + render + end + + it 'shows a comment button' do + assert_select "a[href=#{new_comment_path}]", "Comment" + end + + end + end From ae59b1e18d88e28090fab39a17112895a4b38f69 Mon Sep 17 00:00:00 2001 From: Skud Date: Fri, 8 Feb 2013 14:37:57 +1100 Subject: [PATCH 5/7] pass post_id through to comment --- app/controllers/comments_controller.rb | 1 + app/views/comments/_form.html.haml | 2 + app/views/posts/_single.html.haml | 2 +- spec/controllers/comments_controller_spec.rb | 73 ++++++++------------ spec/views/posts/show.html.haml_spec.rb | 2 +- 5 files changed, 34 insertions(+), 46 deletions(-) diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index bc52a3a61..92edb0af8 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -25,6 +25,7 @@ class CommentsController < ApplicationController # GET /comments/new.json def new @comment = Comment.new + @post = Post.find_by_id(params[:post_id]) || Post.new respond_to do |format| format.html # new.html.erb diff --git a/app/views/comments/_form.html.haml b/app/views/comments/_form.html.haml index 0cfdf1487..31bdc9f74 100644 --- a/app/views/comments/_form.html.haml +++ b/app/views/comments/_form.html.haml @@ -11,3 +11,5 @@ = f.text_area :body, :rows => 6, :class => 'input-block-level' .actions = f.submit 'Save' + .field + = f.hidden_field :post_id, :value => @post.id diff --git a/app/views/posts/_single.html.haml b/app/views/posts/_single.html.haml index f8d31f2fb..d561d28ba 100644 --- a/app/views/posts/_single.html.haml +++ b/app/views/posts/_single.html.haml @@ -27,4 +27,4 @@ - if can? :create, Comment .post-actions - =link_to 'Comment', new_comment_path(), :class => 'btn' + =link_to 'Comment', new_comment_path(:post_id => @post.id), :class => 'btn' diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index fdde2fc7d..a0b3e3638 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -1,43 +1,17 @@ require 'spec_helper' -# This spec was generated by rspec-rails when you ran the scaffold generator. -# It demonstrates how one might use RSpec to specify the controller code that -# was generated by Rails when you ran the scaffold generator. -# -# It assumes that the implementation code is generated by the rails scaffold -# generator. If you are using any extension libraries to generate different -# controller code, this generated spec may or may not pass. -# -# It only uses APIs available in rails and/or rspec-rails. There are a number -# of tools you can use to make these specs even more expressive, but we're -# sticking to rails and rspec-rails APIs to keep things simple and stable. -# -# Compared to earlier versions of this generator, there is very limited use of -# stubs and message expectations in this spec. Stubs are only used when there -# is no simpler way to get a handle on the object needed for the example. -# Message expectations are only used when there is no simpler way to specify -# that an instance is receiving a specific message. - describe CommentsController do - # This should return the minimal set of attributes required to create a valid - # Comment. As you add validations to Comment, be sure to - # update the return value of this method accordingly. + login_member + def valid_attributes { "post_id" => "1" } end - # This should return the minimal set of values that should be in the session - # in order to pass any filters (e.g. authentication) defined in - # CommentsController. Be sure to keep this updated too. - def valid_session - {} - end - describe "GET index" do it "assigns all comments as @comments" do comment = Comment.create! valid_attributes - get :index, {}, valid_session + get :index, {} assigns(:comments).should eq([comment]) end end @@ -45,22 +19,33 @@ describe CommentsController do describe "GET show" do it "assigns the requested comment as @comment" do comment = Comment.create! valid_attributes - get :show, {:id => comment.to_param}, valid_session + get :show, {:id => comment.to_param} assigns(:comment).should eq(comment) end end describe "GET new" do it "assigns a new comment as @comment" do - get :new, {}, valid_session + get :new, {} assigns(:comment).should be_a_new(Comment) end + + it "picks up post from params" do + post = FactoryGirl.create(:post) + get :new, {:post_id => post.id} + assigns(:post).should eq(post) + end + + it "doesn't die if no post specified" do + get :new, {} + assigns(:post).should be_a_new(Post) + end end describe "GET edit" do it "assigns the requested comment as @comment" do comment = Comment.create! valid_attributes - get :edit, {:id => comment.to_param}, valid_session + get :edit, {:id => comment.to_param} assigns(:comment).should eq(comment) end end @@ -69,18 +54,18 @@ describe CommentsController do describe "with valid params" do it "creates a new Comment" do expect { - post :create, {:comment => valid_attributes}, valid_session + post :create, {:comment => valid_attributes} }.to change(Comment, :count).by(1) end it "assigns a newly created comment as @comment" do - post :create, {:comment => valid_attributes}, valid_session + post :create, {:comment => valid_attributes} assigns(:comment).should be_a(Comment) assigns(:comment).should be_persisted end it "redirects to the created comment" do - post :create, {:comment => valid_attributes}, valid_session + post :create, {:comment => valid_attributes} response.should redirect_to(Comment.last) end end @@ -89,14 +74,14 @@ describe CommentsController do it "assigns a newly created but unsaved comment as @comment" do # Trigger the behavior that occurs when invalid params are submitted Comment.any_instance.stub(:save).and_return(false) - post :create, {:comment => { "post_id" => "invalid value" }}, valid_session + post :create, {:comment => { "post_id" => "invalid value" }} assigns(:comment).should be_a_new(Comment) end it "re-renders the 'new' template" do # Trigger the behavior that occurs when invalid params are submitted Comment.any_instance.stub(:save).and_return(false) - post :create, {:comment => { "post_id" => "invalid value" }}, valid_session + post :create, {:comment => { "post_id" => "invalid value" }} response.should render_template("new") end end @@ -111,18 +96,18 @@ describe CommentsController do # receives the :update_attributes message with whatever params are # submitted in the request. Comment.any_instance.should_receive(:update_attributes).with({ "post_id" => "1" }) - put :update, {:id => comment.to_param, :comment => { "post_id" => "1" }}, valid_session + put :update, {:id => comment.to_param, :comment => { "post_id" => "1" }} end it "assigns the requested comment as @comment" do comment = Comment.create! valid_attributes - put :update, {:id => comment.to_param, :comment => valid_attributes}, valid_session + put :update, {:id => comment.to_param, :comment => valid_attributes} assigns(:comment).should eq(comment) end it "redirects to the comment" do comment = Comment.create! valid_attributes - put :update, {:id => comment.to_param, :comment => valid_attributes}, valid_session + put :update, {:id => comment.to_param, :comment => valid_attributes} response.should redirect_to(comment) end end @@ -132,7 +117,7 @@ describe CommentsController do comment = Comment.create! valid_attributes # Trigger the behavior that occurs when invalid params are submitted Comment.any_instance.stub(:save).and_return(false) - put :update, {:id => comment.to_param, :comment => { "post_id" => "invalid value" }}, valid_session + put :update, {:id => comment.to_param, :comment => { "post_id" => "invalid value" }} assigns(:comment).should eq(comment) end @@ -140,7 +125,7 @@ describe CommentsController do comment = Comment.create! valid_attributes # Trigger the behavior that occurs when invalid params are submitted Comment.any_instance.stub(:save).and_return(false) - put :update, {:id => comment.to_param, :comment => { "post_id" => "invalid value" }}, valid_session + put :update, {:id => comment.to_param, :comment => { "post_id" => "invalid value" }} response.should render_template("edit") end end @@ -150,13 +135,13 @@ describe CommentsController do it "destroys the requested comment" do comment = Comment.create! valid_attributes expect { - delete :destroy, {:id => comment.to_param}, valid_session + delete :destroy, {:id => comment.to_param} }.to change(Comment, :count).by(-1) end it "redirects to the comments list" do comment = Comment.create! valid_attributes - delete :destroy, {:id => comment.to_param}, valid_session + delete :destroy, {:id => comment.to_param} response.should redirect_to(comments_url) end end diff --git a/spec/views/posts/show.html.haml_spec.rb b/spec/views/posts/show.html.haml_spec.rb index 6a4cf0039..d4d9979fd 100644 --- a/spec/views/posts/show.html.haml_spec.rb +++ b/spec/views/posts/show.html.haml_spec.rb @@ -44,7 +44,7 @@ describe "posts/show" do end it 'shows a comment button' do - assert_select "a[href=#{new_comment_path}]", "Comment" + assert_select "a[href=#{new_comment_path(:post_id => @post.id)}]", "Comment" end end From b6c759e521f18aa2b5aa0f6cc49c14a62446cc77 Mon Sep 17 00:00:00 2001 From: Skud Date: Fri, 8 Feb 2013 14:49:07 +1100 Subject: [PATCH 6/7] edit comments --- app/controllers/comments_controller.rb | 5 +++++ app/views/comments/_form.html.haml | 5 +++-- ...0130208034248_require_fields_for_comments.rb | 17 +++++++++++++++++ db/schema.rb | 9 +++++---- 4 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20130208034248_require_fields_for_comments.rb diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 92edb0af8..fa62e4efc 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -60,6 +60,11 @@ class CommentsController < ApplicationController def update @comment = Comment.find(params[:id]) + # you should never be able to change the author or post when + # updating + params[:comment].delete("post_id") + params[:comment].delete("author_id") + respond_to do |format| if @comment.update_attributes(params[:comment]) format.html { redirect_to @comment, notice: 'Comment was successfully updated.' } diff --git a/app/views/comments/_form.html.haml b/app/views/comments/_form.html.haml index 31bdc9f74..cae09db74 100644 --- a/app/views/comments/_form.html.haml +++ b/app/views/comments/_form.html.haml @@ -11,5 +11,6 @@ = f.text_area :body, :rows => 6, :class => 'input-block-level' .actions = f.submit 'Save' - .field - = f.hidden_field :post_id, :value => @post.id + - if defined?(@post) + .field + = f.hidden_field :post_id, :value => @post.id diff --git a/db/migrate/20130208034248_require_fields_for_comments.rb b/db/migrate/20130208034248_require_fields_for_comments.rb new file mode 100644 index 000000000..74c26b4af --- /dev/null +++ b/db/migrate/20130208034248_require_fields_for_comments.rb @@ -0,0 +1,17 @@ +class RequireFieldsForComments < ActiveRecord::Migration + def up + change_table :comments do |t| + t.change :post_id, :string, :null => false + t.change :author_id, :string, :null => false + t.change :body, :string, :null => false + end + end + + def down + change_table :comments do |t| + t.change :post_id, :string, :null => true + t.change :author_id, :string, :null => true + t.change :body, :string, :null => true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index ceb9be432..54eca6ad1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,12 +11,12 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130206033956) do +ActiveRecord::Schema.define(:version => 20130208034248) do create_table "comments", :force => true do |t| - t.integer "post_id" - t.integer "author_id" - t.text "body" + t.string "post_id", :null => false + t.string "author_id", :null => false + t.string "body", :null => false t.datetime "created_at", :null => false t.datetime "updated_at", :null => false end @@ -67,6 +67,7 @@ ActiveRecord::Schema.define(:version => 20130206033956) do t.string "login_name" t.string "slug" t.boolean "tos_agreement" + t.boolean "show_email" end add_index "members", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true From 3b3f9d261fe12d8ecb44b881cdd10b305d3d0bc7 Mon Sep 17 00:00:00 2001 From: Skud Date: Fri, 8 Feb 2013 15:02:21 +1100 Subject: [PATCH 7/7] can't create a new post without a post_id --- app/controllers/comments_controller.rb | 13 +++++++++---- app/views/posts/_single.html.haml | 2 +- spec/controllers/comments_controller_spec.rb | 12 ++++++------ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index fa62e4efc..e868b041f 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -25,11 +25,16 @@ class CommentsController < ApplicationController # GET /comments/new.json def new @comment = Comment.new - @post = Post.find_by_id(params[:post_id]) || Post.new + @post = Post.find_by_id(params[:post_id]) - respond_to do |format| - format.html # new.html.erb - format.json { render json: @comment } + if @post + respond_to do |format| + format.html # new.html.erb + format.json { render json: @comment } + end + else + redirect_to request.referer || root_url, + :alert => "Can't post a comment on a non-existent post" end end diff --git a/app/views/posts/_single.html.haml b/app/views/posts/_single.html.haml index d561d28ba..ab28b3392 100644 --- a/app/views/posts/_single.html.haml +++ b/app/views/posts/_single.html.haml @@ -27,4 +27,4 @@ - if can? :create, Comment .post-actions - =link_to 'Comment', new_comment_path(:post_id => @post.id), :class => 'btn' + =link_to 'Comment', new_comment_path(:post_id => post.id), :class => 'btn' diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index a0b3e3638..d8f9a86c9 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -5,7 +5,7 @@ describe CommentsController do login_member def valid_attributes - { "post_id" => "1" } + { :post_id => 1, :author_id => 1, :body => "some text" } end describe "GET index" do @@ -36,9 +36,9 @@ describe CommentsController do assigns(:post).should eq(post) end - it "doesn't die if no post specified" do - get :new, {} - assigns(:post).should be_a_new(Post) + it "dies if no post specified" do + get :new + response.should redirect_to(root_url) end end @@ -95,8 +95,8 @@ describe CommentsController do # specifies that the Comment created on the previous line # receives the :update_attributes message with whatever params are # submitted in the request. - Comment.any_instance.should_receive(:update_attributes).with({ "post_id" => "1" }) - put :update, {:id => comment.to_param, :comment => { "post_id" => "1" }} + Comment.any_instance.should_receive(:update_attributes).with({ "body" => "some text" }) + put :update, {:id => comment.to_param, :comment => { "body" => "some text" }} end it "assigns the requested comment as @comment" do