loudmouth 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +22 -0
- data/LICENSE.txt +20 -0
- data/README.md +50 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/app/controllers/loudmouth/comments_controller.rb +146 -0
- data/app/helpers/comments_helper.rb +6 -0
- data/app/views/loudmouth/comments/_comment.html.haml +14 -0
- data/app/views/loudmouth/comments/_comment_form.html.haml +32 -0
- data/app/views/loudmouth/comments/index.html.haml +10 -0
- data/lib/extensions/helper.rb +28 -0
- data/lib/generators/loudmouth/install_generator.rb +24 -0
- data/lib/generators/loudmouth/loudmouth_generator.rb +34 -0
- data/lib/generators/loudmouth/orm_helpers.rb +18 -0
- data/lib/generators/loudmouth/override_controller_generator.rb +17 -0
- data/lib/generators/loudmouth/templates/README +8 -0
- data/lib/generators/loudmouth/templates/README.override_controller +11 -0
- data/lib/generators/loudmouth/templates/comment_model.rb +6 -0
- data/lib/generators/loudmouth/templates/comments_controller.rb +60 -0
- data/lib/generators/loudmouth/templates/comments_migration.rb +15 -0
- data/lib/generators/loudmouth/templates/loudmouth_initializer.rb +9 -0
- data/lib/generators/loudmouth/views_generator.rb +13 -0
- data/lib/loudmouth.rb +36 -0
- data/lib/rails/routes.rb +37 -0
- data/loudmouth.gemspec +80 -0
- data/test/helper.rb +18 -0
- data/test/test_loudmouth.rb +7 -0
- metadata +167 -0
data/.document
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
acts_as_tree (0.1.1)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.6.0)
|
7
|
+
bundler (~> 1.0.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
rake (0.9.1)
|
11
|
+
rcov (0.9.9)
|
12
|
+
shoulda (2.11.3)
|
13
|
+
|
14
|
+
PLATFORMS
|
15
|
+
ruby
|
16
|
+
|
17
|
+
DEPENDENCIES
|
18
|
+
acts_as_tree
|
19
|
+
bundler (~> 1.0.0)
|
20
|
+
jeweler (~> 1.6.0)
|
21
|
+
rcov
|
22
|
+
shoulda
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Peter Giacomo Lombardo
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
Loudmouth
|
2
|
+
---------
|
3
|
+
|
4
|
+
Loudmouth adds comments to any model.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
Install the gem (or add to your Gemfile & bundle install)
|
9
|
+
|
10
|
+
gem install loudmouth
|
11
|
+
|
12
|
+
Run the loudmouth installer to copy an initializer file to your app.
|
13
|
+
|
14
|
+
rails g loudmouth:install
|
15
|
+
|
16
|
+
Usage
|
17
|
+
-----
|
18
|
+
Assuming you want to have 'users' comment on 'articles' add the following to your routes.rb:
|
19
|
+
|
20
|
+
comments_on :articles, :by => :users
|
21
|
+
|
22
|
+
run the generator to create the comment model (ArticleComments):
|
23
|
+
|
24
|
+
rails generate loudmouth Article User
|
25
|
+
|
26
|
+
and you get nested routes like these:
|
27
|
+
|
28
|
+
/articles/:article_id/comments
|
29
|
+
/articles/:article_id/comments/new
|
30
|
+
/articles/:article_id/comments/:id/edit
|
31
|
+
|
32
|
+
Browse to an article and append '/comments' to the end of the URL.
|
33
|
+
|
34
|
+
Contributing to loudmouth
|
35
|
+
-------------------------
|
36
|
+
|
37
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
38
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
39
|
+
* Fork the project
|
40
|
+
* Start a feature/bugfix branch
|
41
|
+
* Commit and push until you are happy with your contribution
|
42
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
43
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
44
|
+
|
45
|
+
Copyright
|
46
|
+
---------
|
47
|
+
|
48
|
+
Copyright (c) 2011 Peter Giacomo Lombardo. See LICENSE.txt for
|
49
|
+
further details.
|
50
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "loudmouth"
|
18
|
+
gem.homepage = "http://github.com/pglombardo/loudmouth"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Comments for one or many models.}
|
21
|
+
gem.description = %Q{Loudmouth adds commenting to one or many of your models.}
|
22
|
+
gem.email = "pglombardo@gmail.com"
|
23
|
+
gem.authors = ["Peter Giacomo Lombardo"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
39
|
+
test.verbose = true
|
40
|
+
test.rcov_opts << '--exclude "gems/*"'
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "loudmouth #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,146 @@
|
|
1
|
+
class Loudmouth::CommentsController < ApplicationController
|
2
|
+
layout Loudmouth.use_layout if Loudmouth.use_layout.length > 0
|
3
|
+
before_filter :authenticate_user!, :except => [ :index ]
|
4
|
+
|
5
|
+
helper_method :topic, :topic_c, :topic_comment, :topic_comment_c, :user, :user_c
|
6
|
+
helper_method :new_comment_content
|
7
|
+
|
8
|
+
def index
|
9
|
+
@topic = topic_c.find(params[topic.foreign_key.to_sym])
|
10
|
+
@comments = topic_comment_c.find(:all, :conditions => { topic.foreign_key.to_sym => @topic.id },
|
11
|
+
:order => 'created_at DESC', :include => [ :author ])
|
12
|
+
@comment = topic_comment_c.new
|
13
|
+
if defined?(@layout)
|
14
|
+
render 'loudmouth/comments/index', :layout => @layout
|
15
|
+
else
|
16
|
+
render 'loudmouth/comments/index'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def edit
|
21
|
+
@comment = topic_c.find(params[:id])
|
22
|
+
end
|
23
|
+
|
24
|
+
def create
|
25
|
+
@comment = topic_comment_c.new(params[topic_comment.to_sym])
|
26
|
+
@user = user_c.find(params[topic_comment.to_sym][('author_' + user.foreign_key).to_sym])
|
27
|
+
@topic = topic_c.find(params[topic_comment.to_sym][topic.foreign_key.to_sym])
|
28
|
+
|
29
|
+
if params[topic_comment.to_sym][:content] == new_comment_content()
|
30
|
+
flash[:error] = new_comment_content().
|
31
|
+
redirect_to :back
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
if @comment.save
|
36
|
+
flash[:success] = 'Comment successfully posted.'
|
37
|
+
redirect_to after_create_path()
|
38
|
+
else
|
39
|
+
flash[:error] = @comment.errors.full_messages.to_sentence if @comment.errors.any?
|
40
|
+
redirect_to :back
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def update
|
45
|
+
@comment = topic_comment_c.find(params[:id])
|
46
|
+
|
47
|
+
if @comment.update_attributes(params[topic_comment.to_sym])
|
48
|
+
flash[:success] = 'Comment successfully updated.'
|
49
|
+
redirect_to after_update_path()
|
50
|
+
else
|
51
|
+
flash[:error] = @comment.errors.full_messages.to_sentence if @comment.errors.any?
|
52
|
+
redirect_to edit_topic_path()
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def destroy
|
57
|
+
@comment = topic_comment_c.find(params[:id])
|
58
|
+
|
59
|
+
if validate_destroy(@comment)
|
60
|
+
@comment.destroy
|
61
|
+
flash[:success] = 'Comment deleted.'
|
62
|
+
redirect_to after_destroy_path()
|
63
|
+
else
|
64
|
+
flash[:error] = 'You can only delete comments that are yours.'
|
65
|
+
redirect_to :back
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# With
|
70
|
+
# comments_on :topics, :by => :users
|
71
|
+
#
|
72
|
+
# topic() => "topic"
|
73
|
+
# topic().to_sym => :topic
|
74
|
+
# topic().foreign_key => "topic_id"
|
75
|
+
# topic().foreign_key.to_sym => :topic_id
|
76
|
+
# topic_c() => Topic
|
77
|
+
#
|
78
|
+
# topic_comment() => "topic_comment"
|
79
|
+
# topic_comment().to_sym => :topic_comment
|
80
|
+
# topic_comment().foreign_key => "topic_comment_id"
|
81
|
+
# topic_comment().foreign_key.to_sym => :topic_comment_id
|
82
|
+
# topic_comment_c() => TopicComment
|
83
|
+
#
|
84
|
+
# user() => "user"
|
85
|
+
# user().to_sym => :user
|
86
|
+
# user().foreign_key => "user_id"
|
87
|
+
# user().foreign_key.to_sym => :user_id
|
88
|
+
# user_c() => User
|
89
|
+
|
90
|
+
def topic
|
91
|
+
@_topic ||= request.env['loudmouth_map'][:topic_model].singularize.downcase
|
92
|
+
end
|
93
|
+
|
94
|
+
def topic_c
|
95
|
+
topic.camelize.constantize
|
96
|
+
end
|
97
|
+
|
98
|
+
def topic_comment
|
99
|
+
@_topic_comment ||= topic + '_comment'
|
100
|
+
end
|
101
|
+
|
102
|
+
def topic_comment_c
|
103
|
+
topic_comment.camelize.constantize
|
104
|
+
end
|
105
|
+
|
106
|
+
def user
|
107
|
+
@_user ||= request.env['loudmouth_map'][:user_model].singularize.downcase
|
108
|
+
end
|
109
|
+
|
110
|
+
def user_c
|
111
|
+
user.camelize.constantize
|
112
|
+
end
|
113
|
+
|
114
|
+
def new_comment_content
|
115
|
+
Loudmouth.new_comment_content
|
116
|
+
end
|
117
|
+
|
118
|
+
def topic_path
|
119
|
+
end
|
120
|
+
|
121
|
+
def edit_topic_path
|
122
|
+
end
|
123
|
+
|
124
|
+
def after_create_path
|
125
|
+
url_for(@user)
|
126
|
+
end
|
127
|
+
|
128
|
+
def after_destroy_path
|
129
|
+
:back
|
130
|
+
end
|
131
|
+
|
132
|
+
def validate_destroy(comment)
|
133
|
+
# Check if the app if there are corresponding instance variables for
|
134
|
+
# topic and user. If so attempt to validate with those.
|
135
|
+
# Otherwise, this function can be overridden.
|
136
|
+
user = instance_variable_get(:"@#{user}")
|
137
|
+
topic = instance_variable_get(:"@#{topic}")
|
138
|
+
|
139
|
+
if user and topic
|
140
|
+
if user.id == topic.send(:"#{user.foreign_key}")
|
141
|
+
return true
|
142
|
+
end
|
143
|
+
end
|
144
|
+
false
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
.comment{ :id => dom_id(comment) }
|
2
|
+
%table{ :style => 'border-top: 1px solid black;' }
|
3
|
+
%tr{ :style => 'vertical-align: top;' }
|
4
|
+
%td{ :style => '' }
|
5
|
+
- cc = simple_format(comment.content)
|
6
|
+
= auto_link(cc)
|
7
|
+
%tr
|
8
|
+
%td{ :style => 'text-align: right;' }
|
9
|
+
= time_ago_in_words(comment.created_at)
|
10
|
+
ago
|
11
|
+
= link_to "Delete", topic_comment_path(topic, comment), :method => :delete, :confirm => "This will delete the comment from your profile. Are you sure?"
|
12
|
+
|
13
|
+
/ - if comment.children and comment.children.length > 0
|
14
|
+
/ = indented_render 1, :partial => 'loudmouth/comments/comment', :collection => comment.children
|
@@ -0,0 +1,32 @@
|
|
1
|
+
:javascript
|
2
|
+
msg = "#{content}"
|
3
|
+
function prepareTextField(e) {
|
4
|
+
if (e) {
|
5
|
+
if (e.value == msg) {
|
6
|
+
e.value = '';
|
7
|
+
}
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
function revertTextField(e) {
|
12
|
+
if (e)
|
13
|
+
if (e.value == '') {
|
14
|
+
e.value = msg;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
%h3 New Comment
|
19
|
+
|
20
|
+
- author_key = 'author_' + user.class.name.underscore.downcase.foreign_key
|
21
|
+
- topic_comment = topic.class.name.underscore.downcase + '_comment'
|
22
|
+
|
23
|
+
= form_for topic_comment.to_sym, :url => send("#{topic.class.name.underscore.downcase}_comments_path", topic) do |f|
|
24
|
+
%table
|
25
|
+
%tr
|
26
|
+
%td{ :style => 'width: 80%;' }
|
27
|
+
= f.text_area :content, :style => 'width: 100%; height: 50px;', :value => content, :onfocus => "prepareTextField(this);", :onblur => "revertTextField(this);"
|
28
|
+
= f.hidden_field topic.class.name.underscore.downcase.foreign_key.to_sym, { :value => topic.id }
|
29
|
+
= f.hidden_field author_key.to_sym, { :value => user.id }
|
30
|
+
%tr
|
31
|
+
%td{ :style => 'text-align: right;' }
|
32
|
+
= submit_tag "Save", :disable_with => "Please wait..."
|
@@ -0,0 +1,10 @@
|
|
1
|
+
- [:alert, :notice, :error, :success].each do |key|
|
2
|
+
- unless flash[key].blank?
|
3
|
+
%p{ :class => "flash #{key}" }= flash[key]
|
4
|
+
|
5
|
+
= render_comment_form_for(@topic, user)
|
6
|
+
|
7
|
+
- @comments.each do |comment|
|
8
|
+
= render :partial => 'loudmouth/comments/comment', :object => comment
|
9
|
+
|
10
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Loudmouth
|
2
|
+
module Controllers
|
3
|
+
module Helpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
helper_method :render_comment_form_for
|
8
|
+
end
|
9
|
+
|
10
|
+
def render_comment_form_for(topic, user)
|
11
|
+
unless Loudmouth.treasure_map.has_key?(topic.class.name.underscore.downcase.to_sym)
|
12
|
+
raise "loudmouth not setup for #{topic.class.name.underscore.downcase.to_sym}"
|
13
|
+
end
|
14
|
+
|
15
|
+
render :partial => 'loudmouth/comments/comment_form',
|
16
|
+
:locals => { :topic => topic, :user => user, :content => Loudmouth.new_comment_content }
|
17
|
+
end
|
18
|
+
|
19
|
+
def topic_comment_path(topic)
|
20
|
+
send("#{topic.class.name.underscore.downcase}_comments_path", topic)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
module InternalHelpers #:nodoc:
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_support/secure_random'
|
2
|
+
|
3
|
+
module Loudmouth
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.join(File.dirname(__FILE__), 'templates')
|
7
|
+
|
8
|
+
desc "Copies a loudmouth initializer and locale files to your application."
|
9
|
+
class_option :orm
|
10
|
+
|
11
|
+
def copy_initializer
|
12
|
+
template "loudmouth_initializer.rb", "config/initializers/loudmouth.rb"
|
13
|
+
end
|
14
|
+
|
15
|
+
def copy_locale
|
16
|
+
#copy_file "../../../config/locales/en.yml", "config/locales/loudmouth.en.yml"
|
17
|
+
end
|
18
|
+
|
19
|
+
def show_readme
|
20
|
+
readme "README" if behavior == :invoke
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
class LoudmouthGenerator < Rails::Generators::Base
|
5
|
+
desc "Generates the migrations and models needed for loudmouths to comment on your TOPIC_MODEL."
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
argument :topic_model, :type => :string, :required => true
|
8
|
+
argument :user_model, :type => :string, :required => true
|
9
|
+
|
10
|
+
# FIXME: Put in argument validation to assure that the models are in singular form or things break.
|
11
|
+
|
12
|
+
def self.source_root
|
13
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Implement the required interface for Rails::Generators::Migration.
|
17
|
+
# taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
|
18
|
+
def self.next_migration_number(dirname)
|
19
|
+
next_migration_number = current_migration_number(dirname) + 1
|
20
|
+
if ActiveRecord::Base.timestamped_migrations
|
21
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
22
|
+
else
|
23
|
+
"%.3d" % next_migration_number
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_groups_migration_file
|
28
|
+
migration_template 'comments_migration.rb', "db/migrate/create_#{topic_model.downcase}_comments.rb"
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_model_files
|
32
|
+
template 'comment_model.rb', "app/models/#{topic_model.downcase}_comment.rb"
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Loudmouth
|
2
|
+
module Generators
|
3
|
+
module OrmHelpers
|
4
|
+
def model_contents
|
5
|
+
<<-CONTENT
|
6
|
+
CONTENT
|
7
|
+
end
|
8
|
+
|
9
|
+
def model_exists?
|
10
|
+
File.exists?(File.join(destination_root, model_path))
|
11
|
+
end
|
12
|
+
|
13
|
+
def model_path
|
14
|
+
@model_path ||= File.join("app", "models", "#{file_path}.rb")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Loudmouth
|
2
|
+
module Generators
|
3
|
+
class OverrideControllerGenerator < Rails::Generators::Base
|
4
|
+
source_root File.join(File.dirname(__FILE__), 'templates')
|
5
|
+
|
6
|
+
desc "Copies an override controller to your application that you can use to further customize and control loudmouth."
|
7
|
+
|
8
|
+
def copy_override_controller
|
9
|
+
directory "comments_controller.rb", "app/controllers/comments_controller.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
def show_readme
|
13
|
+
readme "README.override_controller" if behavior == :invoke
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
class <%= topic_model.camelize %>Comment < ActiveRecord::Base
|
2
|
+
acts_as_tree :order => 'created_at'
|
3
|
+
|
4
|
+
belongs_to :<%= topic_model.downcase %>
|
5
|
+
belongs_to :author, :foreign_key => :author_<%= user_model.downcase %>_id, :class_name => "<%= user_model.camelize %>"
|
6
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class CommentsController < Loudmouth::CommentsController
|
2
|
+
# You can have a dynamic layout specified under conditions defined in :determine layout below.
|
3
|
+
# layout :determine_layout
|
4
|
+
|
5
|
+
# To use this override controller, uncomment the methods you want to override.
|
6
|
+
|
7
|
+
#
|
8
|
+
# You can override any method in the Loudmouth::CommentsController.
|
9
|
+
# Here we override index to locate and declare additional instance variables
|
10
|
+
# and then call super to pass control to the original index method.
|
11
|
+
#
|
12
|
+
# def index
|
13
|
+
# if topic.to_sym == :game
|
14
|
+
# @game = Game.find(params[:game_id])
|
15
|
+
# elsif topic.to_sym == :profile
|
16
|
+
# @profile = Profile.find(params[:profile_id], :include => [ :primary_pic ])
|
17
|
+
# else
|
18
|
+
# raise "unknown model in Comments#index"
|
19
|
+
# end
|
20
|
+
# super
|
21
|
+
# end
|
22
|
+
|
23
|
+
#
|
24
|
+
# after_create_path specifies the path the user is redirected to after
|
25
|
+
# successfully posting a comment.
|
26
|
+
#
|
27
|
+
# def after_create_path
|
28
|
+
# if topic.to_sym == :game
|
29
|
+
# game_comments_path(@game)
|
30
|
+
# elsif topic.to_sym == :profile
|
31
|
+
# profile_comments_path(@profile)
|
32
|
+
# elsif topic.to_sym == :profile_pic
|
33
|
+
# profile_face_path(@profile, @profile_pic)
|
34
|
+
# else
|
35
|
+
# raise "unknown model in Comments#after_create_path"
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
|
39
|
+
#
|
40
|
+
# validate_destroy is called prior to destroying a comment.
|
41
|
+
# Return true or false to indicate whether the current user is authorized to do so.
|
42
|
+
#
|
43
|
+
# def validate_destroy(comment)
|
44
|
+
# [ code to determine if the current user is authorized to destroy comment ]
|
45
|
+
# return true/false
|
46
|
+
# end
|
47
|
+
|
48
|
+
#
|
49
|
+
# You can have a dynamic layout specified under conditions defined below.
|
50
|
+
#
|
51
|
+
# def determine_layout
|
52
|
+
# if params.has_key?(:profile_id)
|
53
|
+
# 'with_left_sidebar'
|
54
|
+
# elsif params.has_key?(:game_id)
|
55
|
+
# 'one_column_900px'
|
56
|
+
# else
|
57
|
+
# 'one_column_900px'
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Create<%= topic_model.camelize %>Comments < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :<%= topic_model.downcase %>_comments do |t|
|
4
|
+
t.references :parent
|
5
|
+
t.integer :<%= topic_model.downcase %>_id
|
6
|
+
t.integer :author_<%= user_model.downcase %>_id
|
7
|
+
t.text :content
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :<%= topic_model.downcase %>_comments
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Loudmouth
|
2
|
+
module Generators
|
3
|
+
class ViewsGenerator < Rails::Generators::Base
|
4
|
+
source_root File.join(File.dirname(__FILE__), '../../../app/views')
|
5
|
+
|
6
|
+
desc "Copies loudmouth views to your application."
|
7
|
+
|
8
|
+
def copy_views
|
9
|
+
directory "loudmouth/comments", "app/views/loudmouth/comments"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/loudmouth.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "loudmouth"
|
2
|
+
require "rails/routes"
|
3
|
+
require "extensions/helper"
|
4
|
+
|
5
|
+
module Loudmouth
|
6
|
+
class Engine < Rails::Engine
|
7
|
+
config.loudmouth = Loudmouth
|
8
|
+
|
9
|
+
initializer "loudmouth.helpers" do
|
10
|
+
Loudmouth.include_helpers()
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
mattr_accessor :use_layout
|
15
|
+
@@use_layout = ''
|
16
|
+
|
17
|
+
mattr_accessor :new_comment_content
|
18
|
+
@@new_comment_content = ''
|
19
|
+
|
20
|
+
mattr_accessor :treasure_map
|
21
|
+
@@treasure_map = {}
|
22
|
+
|
23
|
+
def self.setup
|
24
|
+
yield self
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.include_helpers
|
28
|
+
ActiveSupport.on_load(:action_controller) do
|
29
|
+
include Loudmouth::Controllers::Helpers
|
30
|
+
end
|
31
|
+
|
32
|
+
# ActiveSupport.on_load(:action_view) do
|
33
|
+
# include Loudmouth::Controllers::Helpers
|
34
|
+
# end
|
35
|
+
end
|
36
|
+
end
|
data/lib/rails/routes.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module ActionDispatch::Routing
|
2
|
+
class Mapper
|
3
|
+
|
4
|
+
def comments_on(*resources)
|
5
|
+
options = resources.extract_options!
|
6
|
+
|
7
|
+
unless resources.count == 1
|
8
|
+
raise "too many arguments passed to comments_on. Format is comments_on :articles, :by => :users"
|
9
|
+
end
|
10
|
+
|
11
|
+
unless options.has_key?(:by)
|
12
|
+
raise "comments_on must include an :by option. Format is comments_on :articles, :by => :users"
|
13
|
+
end
|
14
|
+
|
15
|
+
unless options.has_key?(:controller)
|
16
|
+
options[:controller] = 'loudmouth/comments'
|
17
|
+
end
|
18
|
+
|
19
|
+
topic_model = resources.first.to_s
|
20
|
+
user_model = options[:by].to_s
|
21
|
+
options.delete(:by)
|
22
|
+
|
23
|
+
Loudmouth.treasure_map[topic_model.singularize.downcase.to_sym] =
|
24
|
+
{ :by => user_model.singularize.downcase }
|
25
|
+
|
26
|
+
constraint = lambda { |req| req.env["loudmouth_map"] = { :topic_model => topic_model,
|
27
|
+
:user_model => user_model }; true }
|
28
|
+
Rails.application.routes.draw do
|
29
|
+
resources topic_model do
|
30
|
+
constraints(constraint) do
|
31
|
+
resources "comments", options
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/loudmouth.gemspec
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{loudmouth}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Peter Giacomo Lombardo}]
|
12
|
+
s.date = %q{2011-06-12}
|
13
|
+
s.description = %q{Loudmouth adds commenting to one or many of your models.}
|
14
|
+
s.email = %q{pglombardo@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"app/controllers/loudmouth/comments_controller.rb",
|
28
|
+
"app/helpers/comments_helper.rb",
|
29
|
+
"app/views/loudmouth/comments/_comment.html.haml",
|
30
|
+
"app/views/loudmouth/comments/_comment_form.html.haml",
|
31
|
+
"app/views/loudmouth/comments/index.html.haml",
|
32
|
+
"lib/extensions/helper.rb",
|
33
|
+
"lib/generators/loudmouth/install_generator.rb",
|
34
|
+
"lib/generators/loudmouth/loudmouth_generator.rb",
|
35
|
+
"lib/generators/loudmouth/orm_helpers.rb",
|
36
|
+
"lib/generators/loudmouth/override_controller_generator.rb",
|
37
|
+
"lib/generators/loudmouth/templates/README",
|
38
|
+
"lib/generators/loudmouth/templates/README.override_controller",
|
39
|
+
"lib/generators/loudmouth/templates/comment_model.rb",
|
40
|
+
"lib/generators/loudmouth/templates/comments_controller.rb",
|
41
|
+
"lib/generators/loudmouth/templates/comments_migration.rb",
|
42
|
+
"lib/generators/loudmouth/templates/loudmouth_initializer.rb",
|
43
|
+
"lib/generators/loudmouth/views_generator.rb",
|
44
|
+
"lib/loudmouth.rb",
|
45
|
+
"lib/rails/routes.rb",
|
46
|
+
"loudmouth.gemspec",
|
47
|
+
"test/helper.rb",
|
48
|
+
"test/test_loudmouth.rb"
|
49
|
+
]
|
50
|
+
s.homepage = %q{http://github.com/pglombardo/loudmouth}
|
51
|
+
s.licenses = [%q{MIT}]
|
52
|
+
s.require_paths = [%q{lib}]
|
53
|
+
s.rubygems_version = %q{1.8.1}
|
54
|
+
s.summary = %q{Comments for one or many models.}
|
55
|
+
|
56
|
+
if s.respond_to? :specification_version then
|
57
|
+
s.specification_version = 3
|
58
|
+
|
59
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
60
|
+
s.add_runtime_dependency(%q<acts_as_tree>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
62
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
63
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
|
64
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
65
|
+
else
|
66
|
+
s.add_dependency(%q<acts_as_tree>, [">= 0"])
|
67
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
68
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
69
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
|
70
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
71
|
+
end
|
72
|
+
else
|
73
|
+
s.add_dependency(%q<acts_as_tree>, [">= 0"])
|
74
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
75
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
76
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
|
77
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'loudmouth'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: loudmouth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Peter Giacomo Lombardo
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-06-12 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
name: acts_as_tree
|
32
|
+
version_requirements: *id001
|
33
|
+
type: :runtime
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
hash: 3
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
version: "0"
|
45
|
+
name: shoulda
|
46
|
+
version_requirements: *id002
|
47
|
+
type: :development
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
hash: 23
|
56
|
+
segments:
|
57
|
+
- 1
|
58
|
+
- 0
|
59
|
+
- 0
|
60
|
+
version: 1.0.0
|
61
|
+
name: bundler
|
62
|
+
version_requirements: *id003
|
63
|
+
type: :development
|
64
|
+
- !ruby/object:Gem::Dependency
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ~>
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 15
|
72
|
+
segments:
|
73
|
+
- 1
|
74
|
+
- 6
|
75
|
+
- 0
|
76
|
+
version: 1.6.0
|
77
|
+
name: jeweler
|
78
|
+
version_requirements: *id004
|
79
|
+
type: :development
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
prerelease: false
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
name: rcov
|
92
|
+
version_requirements: *id005
|
93
|
+
type: :development
|
94
|
+
description: Loudmouth adds commenting to one or many of your models.
|
95
|
+
email: pglombardo@gmail.com
|
96
|
+
executables: []
|
97
|
+
|
98
|
+
extensions: []
|
99
|
+
|
100
|
+
extra_rdoc_files:
|
101
|
+
- LICENSE.txt
|
102
|
+
- README.md
|
103
|
+
files:
|
104
|
+
- .document
|
105
|
+
- Gemfile
|
106
|
+
- Gemfile.lock
|
107
|
+
- LICENSE.txt
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- VERSION
|
111
|
+
- app/controllers/loudmouth/comments_controller.rb
|
112
|
+
- app/helpers/comments_helper.rb
|
113
|
+
- app/views/loudmouth/comments/_comment.html.haml
|
114
|
+
- app/views/loudmouth/comments/_comment_form.html.haml
|
115
|
+
- app/views/loudmouth/comments/index.html.haml
|
116
|
+
- lib/extensions/helper.rb
|
117
|
+
- lib/generators/loudmouth/install_generator.rb
|
118
|
+
- lib/generators/loudmouth/loudmouth_generator.rb
|
119
|
+
- lib/generators/loudmouth/orm_helpers.rb
|
120
|
+
- lib/generators/loudmouth/override_controller_generator.rb
|
121
|
+
- lib/generators/loudmouth/templates/README
|
122
|
+
- lib/generators/loudmouth/templates/README.override_controller
|
123
|
+
- lib/generators/loudmouth/templates/comment_model.rb
|
124
|
+
- lib/generators/loudmouth/templates/comments_controller.rb
|
125
|
+
- lib/generators/loudmouth/templates/comments_migration.rb
|
126
|
+
- lib/generators/loudmouth/templates/loudmouth_initializer.rb
|
127
|
+
- lib/generators/loudmouth/views_generator.rb
|
128
|
+
- lib/loudmouth.rb
|
129
|
+
- lib/rails/routes.rb
|
130
|
+
- loudmouth.gemspec
|
131
|
+
- test/helper.rb
|
132
|
+
- test/test_loudmouth.rb
|
133
|
+
homepage: http://github.com/pglombardo/loudmouth
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
hash: 3
|
147
|
+
segments:
|
148
|
+
- 0
|
149
|
+
version: "0"
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
hash: 3
|
156
|
+
segments:
|
157
|
+
- 0
|
158
|
+
version: "0"
|
159
|
+
requirements: []
|
160
|
+
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 1.8.1
|
163
|
+
signing_key:
|
164
|
+
specification_version: 3
|
165
|
+
summary: Comments for one or many models.
|
166
|
+
test_files: []
|
167
|
+
|