finishing up discussions/comments

git-svn-id: http://svn.barleysodas.com/barleysodas/trunk@45 0f7b21a7-9e3a-4941-bbeb-ce5c7c368fa7
master
andrew 2007-11-28 06:17:25 +00:00
parent 2aadbac5b6
commit 83b2373bdf
22 changed files with 183 additions and 130 deletions

View File

@ -29,6 +29,14 @@ class ApplicationController < ActionController::Base
end end
end end
##
# Sets the <tt>@page</tt> variable to allow discussions. This should probably
# have some kind of permission availability check later on.
#
def allow_page_discussions
@page.allow_discussions = true
end
private private
## ##

View File

@ -43,6 +43,7 @@ class BeersController < ApplicationController
@beer = Beer.new(params[:beer]) @beer = Beer.new(params[:beer])
@page = Page.new(params[:page]) @page = Page.new(params[:page])
@beer.page = @page @beer.page = @page
allow_page_discussions
brewery = Brewery.find_by_title(params[:brewery][:title]) rescue nil brewery = Brewery.find_by_title(params[:brewery][:title]) rescue nil
@beer.brewery = brewery @beer.brewery = brewery
respond_to do |format| respond_to do |format|

View File

@ -40,7 +40,7 @@ class BreweriesController < ApplicationController
@brewery = Brewery.new(params[:brewery]) @brewery = Brewery.new(params[:brewery])
@page = Page.new(params[:page]) @page = Page.new(params[:page])
@brewery.page = @page @brewery.page = @page
allow_page_discussions
respond_to do |format| respond_to do |format|
if @brewery.save if @brewery.save
flash[:notice] = 'Brewery was successfully created.' flash[:notice] = 'Brewery was successfully created.'

View File

@ -1,79 +1,73 @@
class DiscussionsController < ApplicationController class DiscussionsController < ApplicationController
append_before_filter :ensure_xhr, :only => [ :allow_discussions,
:deny_discussions ]
# GET /discussions # GET /discussions
# GET /discussions.xml # GET /discussions.xml
def index def index
@discussions = Discussion.find(:all) @content_title = 'Discussion Topics'
@secondary_title = 'All discussion topics'
@pages, @wiki_pages = paginate :pages, :order => 'title ASC',
:conditions => [ 'allow_discussions = ?', true ], :per_page => 25,
:include => [ 'discussions' ]
respond_to do |format| respond_to do |format|
format.html # index.rhtml format.html # index.rhtml
format.xml { render :xml => @discussions.to_xml }
end end
end end
# GET /discussions/1 # GET /discussions/1
# GET /discussions/1.xml # GET /discussions/1.xml
def show def show
@discussion = Discussion.find(params[:id]) @page = Page.find(params[:id], :include => [ 'discussions' ])
@secondary_title = @page.title
@pages, @discussions = paginate :discussion, :order => 'created_at ASC',
:conditions => [ 'page_id = ?', @page.id ], :per_page => 25
respond_to do |format| respond_to do |format|
format.html # show.rhtml format.html # show.rhtml
format.xml { render :xml => @discussion.to_xml } format.xml { render :xml => @discussions.to_xml }
end end
end end
# GET /discussions/new
def new
@discussion = Discussion.new
end
# GET /discussions/1;edit
def edit
@discussion = Discussion.find(params[:id])
end
# POST /discussions # POST /discussions
# POST /discussions.xml # POST /discussions.xml
def create def create
@discussion = Discussion.new(params[:discussion]) @discussion = Discussion.new(params[:discussion])
if @discussion.save
respond_to do |format| render :partial => 'discussion',
if @discussion.save :locals => {
flash[:notice] = 'Discussion was successfully created.' :discussion => @discussion,
format.html { redirect_to discussion_url(@discussion) } :li_number => @discussion.page.discussions.size
format.xml { head :created, :location => discussion_url(@discussion) } }
else else
format.html { render :action => "new" } render :xml => @discussion.errors.to_xml, :status => 500
format.xml { render :xml => @discussion.errors.to_xml }
end
end end
end end
# PUT /discussions/1 # PUT /discussions/1
# PUT /discussions/1.xml # PUT /discussions/1.xml
def update def update
@discussion = Discussion.find(params[:id]) @discussion = Discussion.find(params[:id])
if @discussion.update_attributes(params[:discussion])
respond_to do |format| head :ok
if @discussion.update_attributes(params[:discussion]) else
flash[:notice] = 'Discussion was successfully updated.' render :xml => @discussion.errors.to_xml
format.html { redirect_to discussion_url(@discussion) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @discussion.errors.to_xml }
end
end end
end end
# DELETE /discussions/1 # DELETE /discussions/1
# DELETE /discussions/1.xml # DELETE /discussions/1.xml
def destroy def destroy
@discussion = Discussion.find(params[:id]) @discussion = Discussion.find(params[:id])
@discussion.destroy @discussion.destroy
head :ok
respond_to do |format| end
format.html { redirect_to discussions_url }
format.xml { head :ok } ##
end # Forces an allow of Discussion models on a Page.
#
def allow_discussions
@page = Page.find(params[:id])
status = 500
end end
end end

View File

@ -42,6 +42,7 @@ class PagesController < ApplicationController
# POST /pages.xml # POST /pages.xml
def create def create
@page = Page.new params[:page] @page = Page.new params[:page]
allow_page_discussions
respond_to do |format| respond_to do |format|
if @page.save if @page.save
flash[:notice] = 'Page was successfully created.' flash[:notice] = 'Page was successfully created.'

View File

@ -10,7 +10,7 @@ module ApplicationHelper
# Returns a pretty name for the current chunk. # Returns a pretty name for the current chunk.
# #
def content_title def content_title
return @content_title if @content_title return h(@content_title) if @content_title
controller.class.to_s.gsub(/Controller/, '') controller.class.to_s.gsub(/Controller/, '')
end end
@ -19,7 +19,7 @@ module ApplicationHelper
# action in the controller. # action in the controller.
# #
def secondary_title def secondary_title
return @secondary_title if @secondary_title return h(@secondary_title) if @secondary_title
params[:action].to_s.capitalize.gsub(/_/) do |x| params[:action].to_s.capitalize.gsub(/_/) do |x|
$1.capitalize $1.capitalize
end end
@ -29,6 +29,21 @@ module ApplicationHelper
# Returns a link for a Page model. # Returns a link for a Page model.
# #
def link_to_page(page) def link_to_page(page)
link_to page.title, page_path({ :id => page.title_for_url }) link_to h(page.title), page_path({ :id => page.title_for_url })
end
##
# Helper to set the allow_discussions field in the Page model.
#
def allow_page_discussions
@page.allow_discussions = true
end
##
# Helper to check if Discussion is allowed. This should check the underlying
# permissions first instead of looking in the model.
#
def discussions_allowed?
@page and @page.allow_discussions?
end end
end end

View File

@ -1,2 +1,12 @@
module DiscussionsHelper module DiscussionsHelper
##
# Returns a link to a Page model or to the Page owner if applicable.
#
def page_or_parent_link(page)
if page.owner_type.to_s.empty?
return link_to 'Show Wiki Page', page_path(page.title_for_url)
end
link_to("Show #{page.owner_type} Page",
send("#{page.owner_type.downcase}_path", page.title_for_url))
end
end end

View File

@ -1,2 +1,6 @@
##
# This model will hold all forum and comment type chunks of text for a Page.
#
class Discussion < ActiveRecord::Base class Discussion < ActiveRecord::Base
belongs_to :page
end end

View File

@ -15,12 +15,17 @@ class Page < ActiveRecord::Base
acts_as_taggable acts_as_taggable
belongs_to :owner, :polymorphic => true belongs_to :owner, :polymorphic => true
has_many :discussions, :order => 'discussions.created_at ASC',
:dependent => :destroy
validates_presence_of :title validates_presence_of :title
validates_uniqueness_of :title, :scope => 'owner_type' validates_uniqueness_of :title, :scope => 'owner_type'
validates_format_of :title, :with => /^([A-Za-z0-9 ])+$/, validates_format_of :title, :with => /^([A-Za-z0-9 ])+$/,
:message => 'may only contain letters, numbers and spaces' :message => 'may only contain letters, numbers and spaces'
before_save :update_html before_save :update_html
attr_protected :allow_discussions
## ##
# Returns an url-friendly title for making links. # Returns an url-friendly title for making links.
# #

View File

@ -0,0 +1,9 @@
<li class="discussion" id="discussion-<%= discussion.id %>"<% if defined? li_number -%> value="<%= li_number -%>"<% end -%>>
<div class="author">
<cite>Author Goes Here</cite>
<p>Posted <%= distance_of_time_in_words discussion.created_at, Time.now rescue 'xxx' %> ago.</p>
</div>
<div class="content">
<%= h(discussion.text) %>
</div>
</li>

View File

@ -0,0 +1,26 @@
<div id="discussion_errors">
<%= error_messages_for :discussion %>
</div>
<%= form_remote_tag :url => discussions_path,
:update => { :success => 'comments', :failure => 'comment_errors' },
:position => 'bottom',
:loading => "Element.show('spinner'); Element.hide('preview')",
:complete => "Element.hide('spinner'); $('discussion_form').elements['discussion_text'].value = ''; new Effect.Highlight('comments', {duration:0.75})",
:html => { :id => 'discussion_form', :class => 'discussions' } %>
<%= hidden_field_tag 'discussion[page_id]', @page.id %>
<fieldset>
<h2>Discuss</h2>
<p>
<label>
Comment:
<%= text_area 'discussion', 'text' %>
</label>
</p>
<p>
<%= submit_tag 'Submit' %>
<%= image_tag '/images/spinner.gif', :id => 'spinner', :style => 'display:none' %>
</p>
</fieldset>
</form>

View File

@ -1,12 +0,0 @@
<h1>Editing discussion</h1>
<%= error_messages_for :discussion %>
<% form_for(:discussion, :url => discussion_path(@discussion), :html => { :method => :put }) do |f| %>
<p>
<%= submit_tag "Update" %>
</p>
<% end %>
<%= link_to 'Show', discussion_path(@discussion) %> |
<%= link_to 'Back', discussions_path %>

View File

@ -1,18 +1,10 @@
<h1>Listing discussions</h1> <% unless @wiki_pages.empty? -%>
<ul id="discussions">
<table> <% for page in @wiki_pages -%>
<tr> <li class="<%= page.owner_type.to_s.empty? ? '' : page.owner_type -%>">
</tr> <%= link_to page.title, discussion_path(page) -%> (<%= page.discussions.size -%>)
</li>
<% for discussion in @discussions %>
<tr>
<td><%= link_to 'Show', discussion_path(discussion) %></td>
<td><%= link_to 'Edit', edit_discussion_path(discussion) %></td>
<td><%= link_to 'Destroy', discussion_path(discussion), :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %> <% end %>
</table> </ul>
<%= render :partial => 'shared/pagination_links' %>
<br /> <% end -%>
<%= link_to 'New discussion', new_discussion_path %>

View File

@ -1,11 +0,0 @@
<h1>New discussion</h1>
<%= error_messages_for :discussion %>
<% form_for(:discussion, :url => discussions_path) do |f| %>
<p>
<%= submit_tag "Create" %>
</p>
<% end %>
<%= link_to 'Back', discussions_path %>

View File

@ -1,3 +1,15 @@
<%= render :partial => 'pages/page' %>
<%= link_to 'Edit', edit_discussion_path(@discussion) %> | <ol id="comments" class="comments">
<%= link_to 'Back', discussions_path %> <%= render :partial => 'discussion', :collection => @discussions %>
</ol>
<%= render :partial => 'shared/pagination_links' %>
<% if @page.allow_discussions? -%>
<%= render :partial => 'discussion_form' %>
<% end -%>
<% content_for 'sidebar' do -%>
<%= page_or_parent_link(@page) -%><br />
<% end -%>

View File

@ -31,6 +31,7 @@
<%= link_to_unless_current 'Browse The Beer Wiki', pages_path -%><br /> <%= link_to_unless_current 'Browse The Beer Wiki', pages_path -%><br />
<%= link_to_unless_current 'Browse Beers', beers_path -%><br /> <%= link_to_unless_current 'Browse Beers', beers_path -%><br />
<%= link_to_unless_current 'Browse Breweries', breweries_path -%><br /> <%= link_to_unless_current 'Browse Breweries', breweries_path -%><br />
<%= link_to_unless_current 'Discussions', discussions_path -%><br />
<hr /> <hr />
<%= yield :sidebar %> <%= yield :sidebar %>
</div> </div>

View File

@ -2,7 +2,6 @@
<div class="hentry" id="article-<%= @page.id %>"> <div class="hentry" id="article-<%= @page.id %>">
<h2 class="entry-title"> <h2 class="entry-title">
<%= @page.title %> <%= @page.title %>
<% unless simple -%><span class="comment_count">Comment Size Here</span><% end -%>
</h2> </h2>
<% unless simple -%><div class="vcard"> <% unless simple -%><div class="vcard">
Posted by <span class="fn">Author Name Here</span> Posted by <span class="fn">Author Name Here</span>
@ -19,3 +18,9 @@
<% end if @page.owner and @page.owner.respond_to?("page_attributes") %> <% end if @page.owner and @page.owner.respond_to?("page_attributes") %>
</ul><% end -%> </ul><% end -%>
</div> </div>
<% content_for 'sidebar' do -%>
<% if @page.allow_discussions? or !@page.discussions.empty? -%>
<%= link_to "Discuss (#{@page.discussions.size})", discussion_path(@page) -%><br />
<% end -%>
<% end -%>

View File

@ -1,6 +1,7 @@
<p> <p>
<label for="page_redcloth">Description</label> <%= text_area 'page', 'redcloth' %> <label for="page_redcloth">Description</label> <%= text_area 'page', 'redcloth' %>
</p> </p>
<p><%= content_tag('small', link_to("Textile enabled", "http://hobix.com/textile/")) %></p>
<p> <p>
<label for="page_tag_names">Tags</label> <%= text_field 'page', 'tag_names' %> <label for="page_tag_names">Tags</label> <%= text_field 'page', 'tag_names' %>
</p> </p>

View File

@ -3,10 +3,15 @@ class CreateDiscussions < ActiveRecord::Migration
create_table :discussions do |t| create_table :discussions do |t|
t.column :page_id, :integer t.column :page_id, :integer
t.column :text, :text t.column :text, :text
t.column :created_at, :timestamp
end end
add_column :pages, :allow_discussions, :boolean, :default => false
add_column :page_versions, :allow_discussions, :boolean, :default => false
end end
def self.down def self.down
drop_table :discussions drop_table :discussions
remove_column :pages, :allow_discussions
remove_column :page_versions, :allow_discussions
end end
end end

View File

@ -190,70 +190,65 @@
/* Comments and Trackbacks */ /* Comments and Trackbacks */
#content ol.comments, #content ol.discussions {
#content ol.trackbacks {
list-style-type: none; list-style-type: none;
margin: 0; padding: 0; margin: 0; padding: 0;
} }
#content li.comment, #content li.discussion {
#content li.trackback {
border: 2px solid #ddd; border: 2px solid #ddd;
margin: 0 0 1.5em; padding: 1em; margin: 0 0 1.5em; padding: 1em;
} }
#content li.comment.preview { #content li.discussion.preview {
background: #ffc; background: #ffc;
border: 3px solid #fab444; border: 3px solid #fab444;
margin: 0 0 1.5em; padding: 1em; margin: 0 0 1.5em; padding: 1em;
} }
#content li.comment .author, #content li.discussion .author {
#content li.trackback .author {
font-weight: bold; font-weight: bold;
margin-bottom: 1em; margin-bottom: 1em;
} }
#content li.comment .author cite, #content li.discussion .author cite {
#content li.trackback .author cite {
font-size: 16px; font-size: 16px;
letter-spacing: -1px; letter-spacing: -1px;
} }
#content li.comment .author abbr, #content li.discussion .author abbr { color: #999; }
#content li.trackback .author abbr { color: #999; }
#content li.comment .author .gravatar { #content li.discussion .author .gravatar {
margin: 0 0 0.5em 0.5em; margin: 0 0 0.5em 0.5em;
float: right; float: right;
} }
#content li.comment .author div { #content li.discussion .author div {
margin: 0 0 0.5em 0.5em; margin: 0 0 0.5em 0.5em;
width: 60px; height: 60px; width: 60px; height: 60px;
background: url(/images/gravatar.gif) no-repeat left top; background: url(/images/gravatar.gif) no-repeat left top;
float: right; float: right;
} }
#content form.comments { #content form.discussions {
background: #f2f2f2; background: #f2f2f2;
border-top: 1px solid #ddd; border-top: 1px solid #ddd;
padding: 1em 0.5em; padding: 1em 0.5em;
} }
#content form.comments fieldset { #content form.discussions fieldset {
border: none; border: none;
} }
#content form.comments legend { #content form.discussions legend {
display: none; display: none;
} }
#content form.comments label { #content form.discussions label {
font-weight: bold; font-weight: bold;
} }
#content form.comments textarea { #content form.discussions textarea {
width: 90%; height: 150px; width: 90%; height: 150px;
padding: 3px; padding: 3px;
} }

View File

@ -1,5 +1,9 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one: one:
id: 1 id: 1
page_id: 1
text: booyah
two: two:
id: 2 id: 2
page_id: 3
text: i can has cheeseburger

View File

@ -16,20 +16,14 @@ class DiscussionsControllerTest < Test::Unit::TestCase
def test_should_get_index def test_should_get_index
get :index get :index
assert_response :success assert_response :success
assert assigns(:discussions) assert assigns(:pages)
end end
def test_should_get_new
get :new
assert_response :success
end
def test_should_create_discussion def test_should_create_discussion
old_count = Discussion.count old_count = Discussion.count
post :create, :discussion => { } post :create, :discussion => { :page_id => 1 }
assert_equal old_count+1, Discussion.count assert_equal old_count+1, Discussion.count
assert_response :success
assert_redirected_to discussion_path(assigns(:discussion))
end end
def test_should_show_discussion def test_should_show_discussion
@ -37,21 +31,15 @@ class DiscussionsControllerTest < Test::Unit::TestCase
assert_response :success assert_response :success
end end
def test_should_get_edit def test_should_update_discussion
get :edit, :id => 1 put :update, :id => 1, :discussion => { :page_id => 1 }
assert_response :success assert_response :success
end end
def test_should_update_discussion
put :update, :id => 1, :discussion => { }
assert_redirected_to discussion_path(assigns(:discussion))
end
def test_should_destroy_discussion def test_should_destroy_discussion
old_count = Discussion.count old_count = Discussion.count
delete :destroy, :id => 1 delete :destroy, :id => 1
assert_equal old_count-1, Discussion.count assert_equal old_count-1, Discussion.count
assert_response :success
assert_redirected_to discussions_path
end end
end end