Browse Source

Get the form to actually work

master
Peter J. Jones 11 years ago
parent
commit
b335d41b18

+ 7
- 6
TODO View File

@@ -1,9 +1,10 @@
-*- mode: org -*-

* Schema
- [X] Add an approval_code column
* Email
- [ ] Basic Mailer
- [ ] Configuration
- [ ] Sender Email
- [ ] Site Name
- [ ] Record IP Address and other info
* Comment Listing
- [ ] Correct ordering of replies
- [ ] All replies are approved
- [ ] Render comment for replies
* Banter Mailer
- [ ] Reply emails with URL

+ 30
- 18
app/controllers/comments_controller.rb View File

@@ -22,38 +22,39 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
################################################################################
class CommentsController < ActionController::Base
class CommentsController < ApplicationController
################################################################################
before_filter(:fetch_parent, :only => [:new, :create])
before_filter(:calculate_form_id)
################################################################################
def new
@comment = Comment.new
render(:action => (request.xhr? ? 'new.js.rjs' : 'create.html.erb'))
end
################################################################################
def create
@comment = @parent.comments.build(params[:comment])
@comment = Comment.new(params[:comment])
@comment.banter = @parent
@comment.user_id = current_user.id if respond_to?(:current_user)
unless @comment.save
render(request.xhr? ? {:partial => 'form'} : {:action => 'new'})
if @comment.save
# dude, rails is pissing me off by not rendering the correct action
render(:action => (request.xhr? ? 'create.js.rjs' : 'create.html.erb'))
return
end
unless request.xhr?
# redirect to something like page_path(1)
path_helper = @parent.class.to_s.underscore + '_path'
redirect_to(send(path_helper, @parent))
end
render(:action => (request.xhr? ? 'form.js.rjs' : 'new'))
end
################################################################################
private
################################################################################
# You'll probably want to override this method with one that does
# something sane for your application.
# You might want to override this method in your application.
# Although this implementation might work just fine for you.
#
# This version looks for a params key that looks like *_id, which
# can be generated using nested RESTful routes. For example:
@@ -62,18 +63,29 @@ class CommentsController < ActionController::Base
# page.resouces(:comments)
# end
#
# Would give you a page_comments_path helper method, putting
# page_id into the params hash. This method will find the first
# *_id parameter and try to fetch a record from the database. For
# example, params[:page_id] = 1 would turn into Page.find(1).
# Would give you a page_comments_path helper method, putting page_id
# into the params hash. This method will find the first *_id
# parameter and try to fetch a record from the database. For
# example, params[:page_id] = 1 would turn into Page.find(1).
#
# The implementation of this method doesn't allow URL query
# parameters that match *_id to be used. The parent ID must come
# from nested resource routing. This prevents someone from
# attaching comments to any object by manipulating URLs.
#
# If you override this method, it MUST set @parent to the owner of
# this comment. It is a before_filter for new comments.
def fetch_parent
id_spec = params.keys.detect {|k| k.to_s.match(/^\w_id$/)}
id_spec = params.keys.detect {|k| k.to_s.match(/^\w+_id$/) && !request.query_parameters.has_key?(k.to_s)}
raise("I can't seem to find a parent key in params") if id_spec.nil?
klass = id_spec.sub(/_id$/, '').camlize.constantize
@parent = klass.find(id_spec)
klass = id_spec.sub(/_id$/, '').camelize.constantize
@parent = klass.find(params[id_spec])
end

################################################################################
# Figure out the correct form div ID to use.
def calculate_form_id
@comments_form_id ||= params[:reply_id].blank? ? 'comment-form' : "comment-form-#{params[:reply_id]}"
end
end

+ 17
- 5
app/helpers/comments_helper.rb View File

@@ -23,12 +23,24 @@
#
################################################################################
module CommentsHelper

################################################################################
def comments_for (parent_object)
html = render(:partial => 'comments/show', :locals => {:parent => parent_object})
html << comments_form_for(parent_object)
html
end
################################################################################
def comments_form_for (parent_object)
render(:partial => 'comments/form', :locals => {:parent => parent_object})
end
################################################################################
def comment_form_for (parent_object)
old_parent, @parent = @parent, parent_object
@comment = Comment.new
render(:partial => 'comments/form')
@parent = old_parent
def clean_author_name (comment)
url = comment.author_url
url = "http://#{url}" unless url.match(/^http:\/\//)
url
end
end

+ 35
- 0
app/models/banter_mailer.rb View File

@@ -0,0 +1,35 @@
################################################################################
#
# Copyright (C) 2008 pmade inc. (Peter Jones pjones@pmade.com)
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
################################################################################
class BanterMailer < ActionMailer::Base
################################################################################
def moderation_message (comment)
from(Banter::Config.from_email)
recipients(Banter::Config.moderator_email)
subject(Banter::Config.subject_prefix + "New Comment #{comment.approval_code}")
body(:comment => comment)
end
end

+ 33
- 2
app/models/comment.rb View File

@@ -25,14 +25,44 @@
class Comment < ActiveRecord::Base
################################################################################
attr_protected(:user_id, :approved, :was_edited)
attr_accessible(:reply_id, :author_name, :author_email, :author_url,
:wants_replies, :content)
################################################################################
validates_presence_of(:content)
validates_presence_of(:author_name, :content)
################################################################################
belongs_to(:banter, :polymorphic => true)
belongs_to(:head, :class_name => 'Comment', :foreign_key => 'reply_id')
has_many(:replies, :class_name => 'Comment', :foreign_key => 'reply_id')

################################################################################
# Returns all the top-level comments for the given parent object.
def self.for (parent)
parent.comments.find(:all, {
:include => :replies,
:conditions => ["#{table_name}.reply_id IS NULL AND #{table_name}.approved = ?", true],
:order => "#{table_name}.created_at ASC",
})
end
################################################################################
# Return a textual description of the comment's parent object.
def parent_description
desc = banter.class.to_s.underscore.humanize + ': '
if banter.respond_to?(:title)
desc << banter.title
elsif banter.respond_to?(:name)
desc << banter.name
elsif banter.respond_to?(:description)
desc << banter.description.to_s[0, 32]
else
desc << banter.id
end
desc
end
################################################################################
private
@@ -54,6 +84,7 @@ class Comment < ActiveRecord::Base
unless comment.approved?
comment.send(:create_approval_code)
Comment.update_all(["approval_code=?", comment.approval_code], ["id=?", comment.id])
BanterMailer.deliver_moderation_message(comment)
end
end

+ 17
- 0
app/views/banter_mailer/moderation_message.rhtml View File

@@ -0,0 +1,17 @@
A new comment has been posted for:

<%= @comment.parent_description %>
You can post the comment by replying to this email. You can also ignore this
message and the comment will be deleted in a few days.
Comment Info:
Author Name: <%= @comment.author_name %>
Author Email: <%= @comment.author_email %>
Author URL: <%= @comment.author_url %>
Authorization Code: <%= @comment.approval_code %>
------
<%= @comment.content %>
------

+ 15
- 0
app/views/comments/_attributes.html.erb View File

@@ -0,0 +1,15 @@
<div class="author">
<% if !comment.author_url.blank? %>
<p><%= link_to(h(comment.author_name), clean_author_name(comment)) %></p>
<% else %>
<p><%= h(comment.author_name) %></p>
<% end %>
</div>

<div class="date">
<%= h(comment.created_at.to_s(Banter::Config.date_format)) %>
</div>

<div class="body">
<%= sanitize(comment.content_cache) %>
</div>

+ 15
- 0
app/views/comments/_comment.html.erb View File

@@ -0,0 +1,15 @@
<div class="comment">
<%= render(:partial => 'comments/attributes', :locals => {:comment => comment}) %>
<div class="replies">
<% comment.replies.each do |reply| %>
<%= render(:partial => 'comments/reply', :object => reply) %>
<% end %>
</div>
<div class="bottom_reply_link">
Reply
</div>
<div id="comment-form-<%= comment.id %>"></div>
</div>

+ 10
- 6
app/views/comments/_form.html.erb View File

@@ -1,4 +1,10 @@
<% remote_form_for([@parent, @comment], :html => {:id => 'comment_form'}) do |form| %>
<% @parent ||= parent %>
<% @comment ||= Comment.new %>
<% @comments_form_id ||= 'comment-form' %>

<% remote_form_for([@parent, @comment], :html => {:id => @comments_form_id}) do |form| %>
<%= error_messages_for(:comment) %>
<p>
<label>Name:</label>
<%= form.text_field(:author_name) %>
@@ -24,11 +30,9 @@
<%= form.text_area(:content) %>
</p>
<%= submit_button('Submit Comment') %>
<%= submit_tag('Submit Comment', :disable_with => 'Posting') %>
<% end %>

<div id="comment_notice" style="display:none">
<p>
Thank you for your comment. It will appear after it has been approved.
</p>
<div id="<%= @comments_form_id %>-notice" style="display:none">
<%= render(:partial => 'comments/response') %>
</div>

+ 3
- 0
app/views/comments/_reply.html.erb View File

@@ -0,0 +1,3 @@
<div class="reply">
<%= render(:partial => 'comments/attributes', :locals => {:comment => reply}) %>
</div>

+ 3
- 0
app/views/comments/_response.html.erb View File

@@ -0,0 +1,3 @@
<p>
Thank you for your comment. It will appear after it has been approved.
</p>

+ 4
- 0
app/views/comments/_show.html.erb View File

@@ -0,0 +1,4 @@
<div id="comments">
<h1>Comments (<%= parent.comments.count %>)</h1>
<%= render(:partial => 'comments/comment', :collection => Comment.for(parent)) %>
</div>

+ 2
- 0
app/views/comments/create.html.erb View File

@@ -0,0 +1,2 @@
<% @page_title = 'Thank You' %>
<%= render(:partial => 'response') %>

+ 3
- 3
app/views/comments/create.js.rjs View File

@@ -1,3 +1,3 @@
page['comment_form'].hide
page['comment_form'].reset
page['comment_notice'].show
page[@comments_form_id].hide
page[@comments_form_id].reset
page["#{@comments_form_id}-notice"].show

+ 1
- 0
app/views/comments/form.js.rjs View File

@@ -0,0 +1 @@
page[@comments_form_id].replace(:partial => 'form')

+ 2
- 0
app/views/comments/new.html.erb View File

@@ -0,0 +1,2 @@
<% @page_title = 'New Comment' %>
<%= render(:partial => 'form') %>

+ 1
- 0
app/views/comments/new.js.rjs View File

@@ -0,0 +1 @@
page[div_id].

+ 55
- 0
doc/install.muse View File

@@ -0,0 +1,55 @@
#title Installing Banter

* Step 1. Install Rails Engines

Banter is implemented as a [[http://rails-engines.org/][Rails Engine]]. You will need to install and
configure Rails Engines before Banter can work.

* Step 2. Install Banter

Place Banter in your =vendor/plugins= application directory.

* Step 3. Configure Banter

Create a file called =config/initializers/banter.rb= in your Rails
application. Review the =vendor/plugins/banter/lib/banter/config.rb=
file for the possible configuration options.

* Step 4. Configure Routing

Banter works using nested resource routing. For each model that will
have comments, you'll need to configure a route. For example, if you
have a =Page= class that will have comments:

<src lang="ruby">
map.resources(:pages) do |page|
page.resources(:comments)
end
</src>

* Step 5. Configure Your Models

Again, if you have a =Page= class that will have comments:

<src lang="ruby">
class Page < ActiveRecord::Base
has_many(:comments, :as => :banter)
end
</src>

* Step 6. Load the Comments Helper

In your =app/controllers/application.rb=:

<src lang="ruby">
helper(:comments)
</src>

Note: this can also go in each controller that will use the following
view helper methods, instead of the main application controller file.

* Step 7. Use the Following in Your Views

<example>
<%= comments_for(@page) %>
</example>

+ 2
- 1
init.rb View File

@@ -22,4 +22,5 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
################################################################################
require 'digest/md5'
require('digest/md5')
require('banter')

+ 25
- 0
lib/banter.rb View File

@@ -0,0 +1,25 @@
################################################################################
#
# Copyright (C) 2008 pmade inc. (Peter Jones pjones@pmade.com)
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
################################################################################
require('banter/config')

+ 55
- 0
lib/banter/config.rb View File

@@ -0,0 +1,55 @@
################################################################################
#
# Copyright (C) 2008 pmade inc. (Peter Jones pjones@pmade.com)
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
################################################################################
module Banter

################################################################################
# Configuration for the Banter plugin.
class Config
################################################################################
# The From: address for all emails sent by Banter.
cattr_accessor(:from_email)
@@from_email = 'noreply@example.com'
################################################################################
# The email address or addresses for the moderators. Comments
# that need to be moderated will be sent to this address. Can be
# either a string, or an array of strings.
cattr_accessor(:moderator_email)
@@moderator_email = 'moderator@example.com'
################################################################################
# A prefix used in the Subject: of emails sent.
cattr_accessor(:subject_prefix)
@@subject_prefix = '[Banter] '

################################################################################
# The symbol to give to Time.to_s when rendering the created_at
# time for comments.
cattr_accessor(:date_format)
@@date_format = :short
end
end

Loading…
Cancel
Save