opinio-bootstrap 0.6.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +31 -0
- data/MIT-LICENSE +20 -0
- data/README.md +197 -0
- data/Rakefile +28 -0
- data/app/controllers/opinio/comments_controller.rb +47 -0
- data/app/views/opinio/comments/_comment.html.erb +20 -0
- data/app/views/opinio/comments/_comments.html.erb +12 -0
- data/app/views/opinio/comments/_new.html.erb +19 -0
- data/app/views/opinio/comments/create.js.erb +16 -0
- data/app/views/opinio/comments/destroy.js.erb +3 -0
- data/app/views/opinio/comments/index.html.erb +7 -0
- data/app/views/opinio/comments/reply.js.erb +6 -0
- data/config/locales/opinio.en.yml +16 -0
- data/lib/generators/opinio/install/install_generator.rb +38 -0
- data/lib/generators/opinio/install/templates/initializers/opinio.erb +28 -0
- data/lib/generators/opinio/install/templates/migrations/create_model.rb +13 -0
- data/lib/generators/opinio/install/templates/models/model.rb +3 -0
- data/lib/generators/opinio/views/views_generator.rb +27 -0
- data/lib/opinio.rb +66 -0
- data/lib/opinio/controllers/extensions.rb +39 -0
- data/lib/opinio/controllers/helpers.rb +22 -0
- data/lib/opinio/controllers/internal_helpers.rb +37 -0
- data/lib/opinio/controllers/replies.rb +23 -0
- data/lib/opinio/opinio_model.rb +77 -0
- data/lib/opinio/opinio_model/validations.rb +50 -0
- data/lib/opinio/opinio_subjectum.rb +24 -0
- data/lib/opinio/orm/active_record.rb +19 -0
- data/lib/opinio/rails.rb +8 -0
- data/lib/opinio/rails/routes.rb +20 -0
- data/lib/opinio/railtie.rb +22 -0
- data/lib/opinio/schema.rb +21 -0
- data/lib/opinio/shared_examples.rb +89 -0
- data/lib/opinio/version.rb +5 -0
- metadata +145 -0
data/Gemfile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
gem "kaminari"
|
6
|
+
gem "rails", "~> 3.0.0"
|
7
|
+
gem "sqlite3"
|
8
|
+
gem "jquery-rails"
|
9
|
+
|
10
|
+
group :development do
|
11
|
+
platforms :mri_19 do
|
12
|
+
gem "debugger"
|
13
|
+
end
|
14
|
+
gem 'guard-rspec'
|
15
|
+
if RUBY_PLATFORM =~ /darwin/i
|
16
|
+
gem 'rb-fsevent'
|
17
|
+
gem 'growl'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
group :test do
|
22
|
+
gem "cucumber"
|
23
|
+
gem "cucumber-rails"
|
24
|
+
gem "capybara"
|
25
|
+
gem "launchy"
|
26
|
+
gem "database_cleaner"
|
27
|
+
gem "rspec-rails", :git => "https://github.com/rspec/rspec-rails.git", :tag => "v2.12.2"
|
28
|
+
end
|
29
|
+
# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
|
30
|
+
# gem 'ruby-debug'
|
31
|
+
# gem 'ruby-debug19'
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 YOURNAME
|
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,197 @@
|
|
1
|
+
# Opinio-Bootstrap #
|
2
|
+
|
3
|
+
## Description ##
|
4
|
+
|
5
|
+
This is a fork of Luiz Pereira's great [Opinio](https://github.com/Draiken/opinio) gem for Rails 3+.
|
6
|
+
|
7
|
+
It intends to simply utilize [Twitter Bootstrap](http://twitter.github.com/bootstrap/) styling in views out-of-the-box.
|
8
|
+
|
9
|
+
In particular, it utilizes the media-object component.
|
10
|
+
|
11
|
+
Currently it requires an image_url(:thumb) method (the default for [Carrierwave](https://github.com/jnicklas/carrierwave)) for your User object; If you are set up with Bootstrap and are storing an image on the User, styling will automatically include the User's avatar along with a link to the user, along with the comment and associated links.
|
12
|
+
|
13
|
+
So you need a valid call to
|
14
|
+
|
15
|
+
@user.image_url(:thumb).to_s
|
16
|
+
|
17
|
+
for the avatar image (media object).
|
18
|
+
|
19
|
+
To do: make dynamic the method by which User's image is called; provide a default stock placeholder image for those not utilizing an image mounting system for their User object (e.g. Carrierwave/Paperclip).
|
20
|
+
|
21
|
+
Make sure Bootstrap is in your Rails *Gemfile*:
|
22
|
+
|
23
|
+
gem "bootstrap-sass", ">= 2.2.2.0"
|
24
|
+
|
25
|
+
The remainder of this page is [Opinio](https://github.com/Draiken/opinio)'s original README.
|
26
|
+
|
27
|
+
## Original ##
|
28
|
+
|
29
|
+
**IMPORTANT** Version 0.6 might break some behaviour from 0.5 and lower versions, please refer to the [changelog](https://github.com/Draiken/opinio/blob/master/CHANGELOG.rdoc)
|
30
|
+
|
31
|
+
## Description ##
|
32
|
+
|
33
|
+
Opinio is an engine used to add comments behaviour to your application.
|
34
|
+
The engine is designed to work only with **Rails 3**
|
35
|
+
|
36
|
+
## Intallation ##
|
37
|
+
|
38
|
+
Simply add the following line to your *Gemfile*:
|
39
|
+
|
40
|
+
gem "opinio"
|
41
|
+
|
42
|
+
and run:
|
43
|
+
|
44
|
+
bundle
|
45
|
+
|
46
|
+
## Usage ##
|
47
|
+
|
48
|
+
Opinio provides generators to facilitate it's usage.
|
49
|
+
The most common way to quickly get Opinio working is:
|
50
|
+
|
51
|
+
rails g opinio:install comment
|
52
|
+
|
53
|
+
This will generate the `Comment` model, migration and also generate the opinio initializer for customization of the engine.
|
54
|
+
A `opinio_model` will be added on the `routes.rb`. This method adds the default urls for the model that will act as the comment
|
55
|
+
in your app.
|
56
|
+
|
57
|
+
In order to add the comments functionality to a model, you use the `opinio_subjectum` method
|
58
|
+
|
59
|
+
class Post < ActiveRecord::Base
|
60
|
+
opinio_subjectum
|
61
|
+
end
|
62
|
+
|
63
|
+
On the `routes.rb` you should simply add an `opinio` for your commentable resource
|
64
|
+
|
65
|
+
resources :posts do
|
66
|
+
opinio
|
67
|
+
end
|
68
|
+
|
69
|
+
To render the comments in your views, there is a helper to display the resource's comments easily:
|
70
|
+
|
71
|
+
<%= comments_for @post %>
|
72
|
+
|
73
|
+
This will render the comments and a form for new comment submissions. Alternatively you can render just the comments or just the form like this:
|
74
|
+
|
75
|
+
<%= render_comments @post %>
|
76
|
+
<%= render_comments_form @post %>
|
77
|
+
|
78
|
+
If you need to render the comments with a specific page or limit
|
79
|
+
you can use Kaminari's configurations like `paginates_per 10` on your comment model
|
80
|
+
or you can customize it for specific views on the helpers
|
81
|
+
|
82
|
+
<%= render_comments @post, :page => params[:page], :limit => 5 %>
|
83
|
+
|
84
|
+
This options can also be used on the `comments_for` helper.
|
85
|
+
|
86
|
+
## Customization ##
|
87
|
+
|
88
|
+
### Views ###
|
89
|
+
|
90
|
+
Of course you will want to customize how the comments are displayed or any other customization to the view. To generate the view files on your application, run:
|
91
|
+
|
92
|
+
rails g opinio:views
|
93
|
+
|
94
|
+
And you can customize all the views used by the engine.
|
95
|
+
|
96
|
+
### Behaviour ###
|
97
|
+
|
98
|
+
#### Opinio Model ####
|
99
|
+
|
100
|
+
You can customize the opinio model to suit your needs. The basic customization is the owner class name. It defaults to `User` but you can change that in the initializer or in the model by passing the `:owner_class_name => "MyOwnerClass"` option to the `opinio_model` method call.
|
101
|
+
|
102
|
+
Another customization you can do is set the `counter_cache` to true in the commentable model. You can use the `:counter_cache` option for that.
|
103
|
+
|
104
|
+
The other two customizations are only made through the initializer, and they are the `accept_replies` which defaults to true and `strip_html_tags_on_save` which also defaults to `true`.
|
105
|
+
|
106
|
+
Validations on the opinio model are very basic, just ensuring it has a body, a commentable and an owner, if you want any other kind of validation, like the minimum size of a comment, you can use the regular AR validations as you wish.
|
107
|
+
|
108
|
+
Remember that if you use titles, you need to add that to your comments table, since the generator doesn't add it by default.
|
109
|
+
|
110
|
+
#### Opinio Subjectum ####
|
111
|
+
|
112
|
+
To change how the models that actually have the comments, you can customize them with any option you would use to a regular `has_many` relationship in ActiveRecord.
|
113
|
+
|
114
|
+
The default options are these:
|
115
|
+
|
116
|
+
has_many :comments,
|
117
|
+
:class_name => Opinio.model_name,
|
118
|
+
:as => :commentable,
|
119
|
+
:order => "created_at #{Opinio.sort_order}"),
|
120
|
+
:dependent => :destroy
|
121
|
+
|
122
|
+
The `sort_order` and `model_name` are both setup in the initializer. Here you can do things like, let's say you have moderation in your comments, you can only show the approved comments:
|
123
|
+
|
124
|
+
opinio_subjectum :conditions => ["approved = ?", true]
|
125
|
+
|
126
|
+
Remember you can override any of these options (except `as`) by passing them to the `opinio_subjectum` method.
|
127
|
+
|
128
|
+
#### Pretty Urls ####
|
129
|
+
|
130
|
+
Often times you will want the engine to show the index of comments for a specific item
|
131
|
+
without having to pass the `:commentable_type` or `:commentable_id` parameters.
|
132
|
+
|
133
|
+
In order to do that, opinio provides a method to `ActionController::Base`:
|
134
|
+
|
135
|
+
opinio_identifier do |params|
|
136
|
+
next Review.find(params[:review_id]) if params[:review_id]
|
137
|
+
next Product.find(params[:product_id]) if params[:product_id]
|
138
|
+
end
|
139
|
+
|
140
|
+
Note: you use next instead of return because it is a proc that will be executed later on, and you cannot return on procs
|
141
|
+
|
142
|
+
Basically on this method you receive the `params` variable and you tell the engine, who owns
|
143
|
+
the comments from that page.
|
144
|
+
This allows you to use routes like:
|
145
|
+
|
146
|
+
/products/1/comments
|
147
|
+
/products/1/reviews/1/comments
|
148
|
+
|
149
|
+
Without passing those 2 parameters.
|
150
|
+
I suggest you put this method on the `ApplicationController`
|
151
|
+
|
152
|
+
#### Customize destroy conditions ####
|
153
|
+
|
154
|
+
By default, noone can destroy a comment in the engine. You have to tell the engine who can do it.
|
155
|
+
To setup a custom destroy condition use the methods provided by opinio
|
156
|
+
in our controllers. For instance, if our opinio model is called 'comment'
|
157
|
+
it could be written like this:
|
158
|
+
|
159
|
+
comment_destroy_conditions do |comment|
|
160
|
+
comment.owner == current_user
|
161
|
+
end
|
162
|
+
|
163
|
+
This would make users only be able to remove their own comments.
|
164
|
+
Another example would be using the `CanCan`:
|
165
|
+
|
166
|
+
comment_destroy_conditions do |comment|
|
167
|
+
authorize :destroy, comment
|
168
|
+
end
|
169
|
+
|
170
|
+
You get the picture, you're inside your controller's methods on that block
|
171
|
+
so you can call anything your normal controllers call on actions.
|
172
|
+
|
173
|
+
### Testing ###
|
174
|
+
|
175
|
+
Opinio provides a few shared examples for testing of your model with rspec
|
176
|
+
On your opinio model test case you can require opinio's shared examples and use them
|
177
|
+
|
178
|
+
require 'opinio/shared_examples'
|
179
|
+
|
180
|
+
describe Comment do
|
181
|
+
it_should_behave_like :opinio
|
182
|
+
end
|
183
|
+
|
184
|
+
describe Post do
|
185
|
+
it_should_behave_like :opinio_subjectum
|
186
|
+
end
|
187
|
+
|
188
|
+
## Contribution ##
|
189
|
+
|
190
|
+
If you want to help in any way with **Opinio** please message me or fork the project, make the changes and send me a pull request.
|
191
|
+
For issues please use the github [issues tracker](https://github.com/Draiken/opinio/issues)
|
192
|
+
|
193
|
+
### TODO ###
|
194
|
+
|
195
|
+
* Refactor the `comments_for` helper
|
196
|
+
* Extract documentation to wiki
|
197
|
+
* Add mongoid support
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rake'
|
10
|
+
require 'rdoc/task'
|
11
|
+
|
12
|
+
require 'cucumber'
|
13
|
+
require 'cucumber/rake/task'
|
14
|
+
|
15
|
+
require 'rspec/core'
|
16
|
+
require 'rspec/core/rake_task'
|
17
|
+
|
18
|
+
RSpec::Core::RakeTask.new(:spec)
|
19
|
+
|
20
|
+
task :default => :spec
|
21
|
+
|
22
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
23
|
+
rdoc.rdoc_dir = 'rdoc'
|
24
|
+
rdoc.title = 'Opinio'
|
25
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
26
|
+
rdoc.rdoc_files.include('README.rdoc')
|
27
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
28
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Opinio::CommentsController < ApplicationController
|
2
|
+
include Opinio::Controllers::InternalHelpers
|
3
|
+
include Opinio::Controllers::Replies if Opinio.accept_replies
|
4
|
+
|
5
|
+
def index
|
6
|
+
@comments = resource.comments.page(params[:page])
|
7
|
+
end
|
8
|
+
|
9
|
+
def create
|
10
|
+
@comment = resource.comments.build(params[:comment])
|
11
|
+
@comment.owner = send(Opinio.current_user_method)
|
12
|
+
if @comment.save
|
13
|
+
flash_area = :notice
|
14
|
+
message = t('opinio.messages.comment_sent')
|
15
|
+
else
|
16
|
+
flash_area = :error
|
17
|
+
message = t('opinio.messages.comment_sending_error')
|
18
|
+
end
|
19
|
+
|
20
|
+
respond_to do |format|
|
21
|
+
format.js
|
22
|
+
format.html do
|
23
|
+
set_flash(flash_area, message)
|
24
|
+
redirect_to(opinio_after_create_path(resource))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def destroy
|
30
|
+
@comment = Opinio.model_name.constantize.find(params[:id])
|
31
|
+
|
32
|
+
if can_destroy_opinio?(@comment)
|
33
|
+
@comment.destroy
|
34
|
+
set_flash(:notice, t('opinio.messages.comment_destroyed'))
|
35
|
+
else
|
36
|
+
#flash[:error] = I18n.translate('opinio.comment.not_permitted', :default => "Not permitted")
|
37
|
+
logger.warn "user #{send(Opinio.current_user_method)} tried to remove a comment from another user #{@comment.owner.id}"
|
38
|
+
render :text => "unauthorized", :status => 401 and return
|
39
|
+
end
|
40
|
+
|
41
|
+
respond_to do |format|
|
42
|
+
format.js
|
43
|
+
format.html { redirect_to( opinio_after_destroy_path(@comment) ) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% reply = defined?(reply) ? reply : false %>
|
2
|
+
<div id="comment_<%= comment.id %>" class="media">
|
3
|
+
<a class="pull-left" href="<%= user_path(comment.owner) %>">
|
4
|
+
<img class="media-object" src="<%= comment.owner.image_url(:thumb).to_s %>" />
|
5
|
+
<span><%= comment.owner.name.titlecase %></span>
|
6
|
+
</a>
|
7
|
+
<div class="media-body">
|
8
|
+
<%= simple_format(comment.body) %>
|
9
|
+
<% if comment.owner == send(Opinio.current_user_method) %>
|
10
|
+
<%= link_to t('opinio.actions.delete'), comment_path(comment), :method => :delete, :remote => true %>
|
11
|
+
<% end %>
|
12
|
+
<%# this enables only 1 level of replies %>
|
13
|
+
<% if Opinio.accept_replies && !reply && !(comment.owner == current_user) %>
|
14
|
+
<span><%= link_to t('opinio.actions.reply'), reply_comment_path(comment), :remote => true %></span>
|
15
|
+
<% end %>
|
16
|
+
<div id="comment_<%= comment.id %>_replies" class="replies media">
|
17
|
+
<%= render :partial => "opinio/comments/comment", :collection => comment.comments, :locals => {:reply => true} %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
</div>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<div>
|
2
|
+
<%= paginate comments %>
|
3
|
+
</div>
|
4
|
+
<% unless comments.empty? %>
|
5
|
+
<%= render :partial => 'opinio/comments/comment', :collection => comments %>
|
6
|
+
<% else %>
|
7
|
+
<h3><%= t('opinio.messages.no_comments_found') %></h3>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<div>
|
11
|
+
<%= paginate comments %>
|
12
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<div id="new_comment">
|
2
|
+
<% if send(Opinio.current_user_method) %>
|
3
|
+
<h3 class="addcomment"><%= t('opinio.messages.add_comment') %></h3>
|
4
|
+
<%= form_for Comment.new, :remote => false do |f| %>
|
5
|
+
<p>
|
6
|
+
<%= f.text_area :body, :placeholder => "Enter comment...", rows:"10" %>
|
7
|
+
</p>
|
8
|
+
<%= hidden_field_tag :commentable_id, commentable.id %>
|
9
|
+
<%= hidden_field_tag :commentable_type, commentable.class.base_class.name.to_s %>
|
10
|
+
<%= hidden_field_tag :original_controller, params[:controller] %>
|
11
|
+
<%= hidden_field_tag :original_id, params[:id] %>
|
12
|
+
<%= f.submit t('opinio.actions.add') %>
|
13
|
+
<% end %>
|
14
|
+
<% else %>
|
15
|
+
<p>
|
16
|
+
<%= t('opinio.messages.must_be_logged_in_to_comment') %>
|
17
|
+
</p>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
$('#no_comments').hide();
|
2
|
+
<% if @comment.valid? %>
|
3
|
+
<% if @reply %>
|
4
|
+
if($('#comment_<%= @comment.commentable_id %> ul').length == 0)
|
5
|
+
$('#comment_<%= @comment.commentable_id %>').append('<ul id="comment_<%= @comment.commentable_id %>_replies" class="replies"></ul>');
|
6
|
+
$('#comment_<%= @comment.commentable_id %>_replies').append("<%= escape_javascript( render @comment, :locals => {:reply => @reply} ) %>");
|
7
|
+
$('#commentable_id').val('<%= @comment.commentable.commentable_id %>');
|
8
|
+
$('#commentable_type').val('<%= @comment.commentable.commentable_type %>');
|
9
|
+
<% else %>
|
10
|
+
$('#comments').<%= Opinio.sort_order == 'ASC' ? 'append' : 'prepend'%>("<%= escape_javascript( render @comment, :locals => {:reply => @reply} ) %>");
|
11
|
+
<% end %>
|
12
|
+
$('textarea#comment_body').val('');
|
13
|
+
<% else %>
|
14
|
+
$('#comments').prepend("<%= escape_javascript(flash[:notice]) %>");
|
15
|
+
$('#comments').prepend("<%= escape_javascript(flash[:error]) %>");
|
16
|
+
<% end %>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<% @comment = Comment.find(@commentable_id) %>
|
2
|
+
$("#commentable_id").val('<%= @commentable_id %>');
|
3
|
+
$("#commentable_type").val('<%= @commentable_type %>');
|
4
|
+
$("#new_comment textarea").val('');
|
5
|
+
$("#new_comment h3.addcomment").text('Replying to <%= @comment.owner.name.titlecase %>');
|
6
|
+
$("#new_comment textarea").focus();
|
@@ -0,0 +1,16 @@
|
|
1
|
+
en:
|
2
|
+
opinio:
|
3
|
+
actions:
|
4
|
+
delete: 'Delete'
|
5
|
+
reply: 'Reply'
|
6
|
+
add: 'Add comment'
|
7
|
+
messages:
|
8
|
+
no_comments_found: 'No comments found'
|
9
|
+
must_be_logged_in_to_comment: 'Must be logged in to comment.'
|
10
|
+
add_comment: 'Add comment'
|
11
|
+
comments: 'Comments'
|
12
|
+
comment_sent: 'Comment sent successfully.'
|
13
|
+
comment_sending_error: 'Error while sending the comment.'
|
14
|
+
comment_destroyed: 'Comment removed successfully.'
|
15
|
+
comment_interval: 'You must wait %{time} seconds to comment again.'
|
16
|
+
cannot_be_comment_of_comment: "Cannot reply another comment's reply"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Opinio
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::NamedBase
|
4
|
+
include Rails::Generators::Migration
|
5
|
+
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
|
8
|
+
|
9
|
+
def generate_model
|
10
|
+
template "models/model.rb", "app/models/#{file_name}.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate_migration
|
14
|
+
migration_template "migrations/create_model.rb", "db/migrate/create_#{table_name}", {:assigns => {:name => name, :table_name => table_name}}
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_initializer
|
18
|
+
template "initializers/opinio.erb", "config/initializers/opinio.rb"
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_route
|
22
|
+
route "opinio_model"
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_dependency_gem
|
26
|
+
gem "kaminari"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.next_migration_number(dirname)
|
30
|
+
if ActiveRecord::Base.timestamped_migrations
|
31
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
32
|
+
else
|
33
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Opinio Configuration
|
2
|
+
|
3
|
+
Opinio.setup do |config|
|
4
|
+
|
5
|
+
# Use this to change the class that calls +opinio+ method
|
6
|
+
config.model_name = "<%= class_name %>"
|
7
|
+
|
8
|
+
# This is the owner class of the comment (opinio model)
|
9
|
+
# config.owner_class_name = "User"
|
10
|
+
|
11
|
+
# Change this if you do not want to allow replies on your comments
|
12
|
+
# config.accept_replies = true
|
13
|
+
|
14
|
+
# Here you can change the method called to check who is the current user
|
15
|
+
# config.current_user_method = :current_user
|
16
|
+
|
17
|
+
# Strip html tags on save comment
|
18
|
+
config.strip_html_tags_on_save = true
|
19
|
+
|
20
|
+
# Comments sort order by created_at (DESC or ASC)
|
21
|
+
# Note: you can override that easily within each opinio subjectum
|
22
|
+
config.sort_order = 'DESC'
|
23
|
+
|
24
|
+
# Wether or not the default opinio controller should set the flash
|
25
|
+
# when creating/removing comments
|
26
|
+
config.set_flash = true
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Opinio
|
2
|
+
module Generators
|
3
|
+
class ViewsGenerator < Rails::Generators::Base
|
4
|
+
|
5
|
+
source_root File.expand_path('../../../../../app/views/opinio/comments', __FILE__)
|
6
|
+
|
7
|
+
class_option :haml, :desc => 'Generate HAML views instead of ERB.', :type => :boolean
|
8
|
+
|
9
|
+
def copy_views
|
10
|
+
html_names = ["_comment", "_comments", "_new", "index"]
|
11
|
+
js_names = ["create", "destroy", "reply"]
|
12
|
+
html_names.each do |name|
|
13
|
+
copy_file "#{name}.html.#{view_language}", "app/views/opinio/comments/#{name}.html.#{view_language}"
|
14
|
+
end
|
15
|
+
js_names.each do |name|
|
16
|
+
copy_file "#{name}.js.erb", "app/views/opinio/comments/#{name}.js.erb"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def view_language
|
21
|
+
options.haml? ? 'haml' : 'erb'
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/opinio.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Opinio
|
2
|
+
require 'opinio/schema'
|
3
|
+
|
4
|
+
module Controllers
|
5
|
+
require 'opinio/controllers/helpers'
|
6
|
+
require 'opinio/controllers/internal_helpers'
|
7
|
+
require 'opinio/controllers/replies'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'opinio/railtie'
|
11
|
+
require 'opinio/rails'
|
12
|
+
require 'opinio/orm/active_record'
|
13
|
+
|
14
|
+
mattr_accessor :model_name
|
15
|
+
@@model_name = "Comment"
|
16
|
+
|
17
|
+
mattr_accessor :owner_class_name
|
18
|
+
@@owner_class_name = "User"
|
19
|
+
|
20
|
+
mattr_accessor :use_title
|
21
|
+
@@use_title = false
|
22
|
+
|
23
|
+
mattr_accessor :accept_replies
|
24
|
+
@@accept_replies = false
|
25
|
+
|
26
|
+
mattr_accessor :custom_identifiers
|
27
|
+
@@custom_identifiers = Array.new
|
28
|
+
|
29
|
+
mattr_accessor :interval_between_comments
|
30
|
+
@@interval_between_comments = false
|
31
|
+
|
32
|
+
mattr_accessor :destroy_conditions
|
33
|
+
@@destroy_conditions = Proc.new { false }
|
34
|
+
|
35
|
+
mattr_accessor :current_user_method
|
36
|
+
@@current_user_method = :current_user
|
37
|
+
|
38
|
+
mattr_accessor :strip_html_tags_on_save
|
39
|
+
@@strip_html_tags_on_save = true
|
40
|
+
|
41
|
+
mattr_accessor :sort_order
|
42
|
+
@@sort_order = 'DESC'
|
43
|
+
|
44
|
+
mattr_accessor :set_flash
|
45
|
+
@@set_flash = true
|
46
|
+
|
47
|
+
def self.setup
|
48
|
+
yield self
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.opinio_identifier(block)
|
52
|
+
@@custom_identifiers << block
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.set_destroy_conditions(&block)
|
56
|
+
@@destroy_conditions = block
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.check_custom_identifiers(params)
|
60
|
+
self.custom_identifiers.each do |identifier|
|
61
|
+
identified = identifier.call(params)
|
62
|
+
return identified unless identified.nil?
|
63
|
+
end
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Opinio
|
2
|
+
module Controllers
|
3
|
+
module Extensions
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
base.send :include, InstanceMethods
|
8
|
+
|
9
|
+
base.class_eval do
|
10
|
+
(class << self; self; end).instance_eval do
|
11
|
+
define_method "#{Opinio.model_name.underscore}_destroy_conditions" do |&block|
|
12
|
+
Opinio.set_destroy_conditions( &block )
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
def opinio_identifier(&block)
|
20
|
+
Opinio.opinio_identifier(block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module InstanceMethods
|
25
|
+
def can_destroy_opinio?(opinio)
|
26
|
+
self.instance_exec(opinio, &Opinio.destroy_conditions)
|
27
|
+
end
|
28
|
+
|
29
|
+
def opinio_after_create_path(resource)
|
30
|
+
resource.is_a?(Opinio.model_name.constantize) ? resource.commentable : resource
|
31
|
+
end
|
32
|
+
|
33
|
+
def opinio_after_destroy_path(comment)
|
34
|
+
comment.commentable
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Opinio
|
2
|
+
module Controllers
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
def comments_for(object, options = {})
|
6
|
+
render_comments(object, options) +
|
7
|
+
( render_comments_form(object, options) unless options[:no_new] ).to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def render_comments(object, options = {})
|
11
|
+
limit = options.delete(:limit) || Opinio.model_name.constantize.default_per_page
|
12
|
+
page = options.delete(:page) || 1
|
13
|
+
render( :partial => "opinio/comments/comments", :locals => {:comments => object.comments.page(page).limit(limit), :commentable => object, :options => options} )
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_comments_form(object, options = {})
|
17
|
+
render( :partial => "opinio/comments/new", :locals => {:commentable => object, :options => options} )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Opinio
|
2
|
+
module Controllers
|
3
|
+
module InternalHelpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
helper_method :resource, :resource_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def resource
|
11
|
+
@resource ||= custom_resource_identifier(params) || resource_by_params
|
12
|
+
end
|
13
|
+
|
14
|
+
def resource_by_params
|
15
|
+
if params[:commentable_type]
|
16
|
+
params[:commentable_type].constantize.find(params[:commentable_id])
|
17
|
+
elsif params[:comment]
|
18
|
+
params[:comment][:commentable_type].constantize.find(params[:comment][:commentable_id])
|
19
|
+
else
|
20
|
+
raise "Unable to determine comments holder"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def custom_resource_identifier(params)
|
25
|
+
Opinio.check_custom_identifiers(params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def resource_name
|
29
|
+
Opinio.model_name
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_flash(name, message)
|
33
|
+
flash[name] = message if Opinio.set_flash
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Opinio
|
2
|
+
module Controllers
|
3
|
+
module Replies
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before_filter :check_reply, :only => [:create]
|
8
|
+
end
|
9
|
+
|
10
|
+
def reply
|
11
|
+
@commentable_type = Opinio.model_name
|
12
|
+
@commentable_id = params[:id]
|
13
|
+
@commentable = Opinio.model_name.constantize.find(params[:id])
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def check_reply
|
19
|
+
@reply = params[:commentable_type] == Opinio.model_name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'opinio/opinio_model/validations'
|
2
|
+
|
3
|
+
module Opinio
|
4
|
+
module OpinioModel
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# Adds the Opinio functionallity to the model
|
13
|
+
# You can pass a hash of options to customize the Opinio model
|
14
|
+
def opinio(*args)
|
15
|
+
return if self.included_modules.include?(Opinio::OpinioModel::Validations)
|
16
|
+
options = args.extract_options!
|
17
|
+
|
18
|
+
if Opinio.use_title
|
19
|
+
attr_accessible :title
|
20
|
+
end
|
21
|
+
attr_accessible :body
|
22
|
+
|
23
|
+
belongs_to :commentable, :polymorphic => true, :counter_cache => options.fetch(:counter_cache, false)
|
24
|
+
belongs_to :owner, :class_name => options.fetch(:owner_class_name, Opinio.owner_class_name)
|
25
|
+
|
26
|
+
scope :owned_by, lambda {|owner| where('owner_id = ?', owner.id) }
|
27
|
+
|
28
|
+
send :include, Opinio::OpinioModel::Validations
|
29
|
+
|
30
|
+
if Opinio.accept_replies
|
31
|
+
send :include, RepliesSupport
|
32
|
+
end
|
33
|
+
|
34
|
+
if Opinio.strip_html_tags_on_save
|
35
|
+
send :include, Sanitizing
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module Sanitizing
|
42
|
+
def self.included(base)
|
43
|
+
base.class_eval do
|
44
|
+
send :include, ActionView::Helpers::SanitizeHelper
|
45
|
+
before_save :strip_html_tags
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def strip_html_tags
|
52
|
+
self.body = strip_tags(self.body)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module RepliesSupport
|
57
|
+
def self.included(base)
|
58
|
+
base.class_eval do
|
59
|
+
validate :cannot_be_comment_of_a_comments_comment
|
60
|
+
opinio_subjectum :order => 'created_at ASC'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Validates that you cannot comment on a comment's comment
|
67
|
+
def cannot_be_comment_of_a_comments_comment
|
68
|
+
if new_record? && self.commentable_type == Opinio.model_name
|
69
|
+
if commentable.commentable_type == Opinio.model_name
|
70
|
+
errors.add :base, I18n.t('opinio.messages.cannot_be_comment_of_comment')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Opinio
|
2
|
+
module OpinioModel
|
3
|
+
module Validations
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
|
9
|
+
#TODO: refactor this
|
10
|
+
if Opinio.interval_between_comments
|
11
|
+
include Opinio::OpinioModel::Validations::IntervalMethods
|
12
|
+
validate :validate_last_comment_time, :if => :new_record?
|
13
|
+
cattr_accessor :comments_interval
|
14
|
+
self.comments_interval = options.reverse_merge(:time => Opinio.interval_between_comments)[:time]
|
15
|
+
end
|
16
|
+
|
17
|
+
validates :body, :presence => true
|
18
|
+
validates :commentable, :presence => true
|
19
|
+
validates :owner, :presence => true, :associated => true
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
module IntervalMethods
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Checks the time of the last comment
|
29
|
+
# made by the same owner
|
30
|
+
def validate_last_comment_time
|
31
|
+
last_comment = Comment.owned_by(self.owner).order('created_at DESC').last
|
32
|
+
if last_comment
|
33
|
+
if (Time.now - last_comment.created_at).round >= self.comments_interval
|
34
|
+
true
|
35
|
+
else
|
36
|
+
errors.add(:created_at,
|
37
|
+
I18n.translate('opinio.messages.comment_interval',
|
38
|
+
:time => self.comments_interval))
|
39
|
+
false
|
40
|
+
end
|
41
|
+
else
|
42
|
+
true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end # IntervalMethods
|
47
|
+
|
48
|
+
end # Validations
|
49
|
+
end # OpinioModel
|
50
|
+
end # Opinio
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Opinio
|
2
|
+
module OpinioSubjectum
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def opinio_subjectum(*args)
|
10
|
+
options = args.extract_options!
|
11
|
+
options.delete(:as)
|
12
|
+
|
13
|
+
default_options = { :class_name => Opinio.model_name,
|
14
|
+
:as => :commentable,
|
15
|
+
:order => "created_at #{Opinio.sort_order}",
|
16
|
+
:dependent => :destroy }
|
17
|
+
|
18
|
+
has_many :comments, default_options.merge(options)
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'active_record/connection_adapters/abstract/schema_definitions'
|
2
|
+
|
3
|
+
module Opinio
|
4
|
+
module Orm
|
5
|
+
module ActiveRecord
|
6
|
+
module Schema
|
7
|
+
include Opinio::Schema
|
8
|
+
# Tell how to apply schema methods.
|
9
|
+
def apply_opinio_schema(name, type, options={})
|
10
|
+
column name, type.to_s.downcase.to_sym, options
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
ActiveRecord::ConnectionAdapters::Table.send :include, Opinio::Orm::ActiveRecord::Schema
|
18
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Opinio::Orm::ActiveRecord::Schema
|
19
|
+
|
data/lib/opinio/rails.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module ActionDispatch::Routing
|
2
|
+
class Mapper
|
3
|
+
def opinio(*args)
|
4
|
+
options = args.extract_options!.symbolize_keys
|
5
|
+
route_name = options[:path_name] || Opinio.model_name.pluralize.downcase
|
6
|
+
options[:controller] ||= 'opinio/comments'
|
7
|
+
|
8
|
+
get "#{ route_name }(/:page)" => "#{options[:controller].to_s}#index", :as => :comments
|
9
|
+
end
|
10
|
+
|
11
|
+
def opinio_model(*args)
|
12
|
+
options = args.extract_options!
|
13
|
+
options[:controller] ||= 'opinio/comments'
|
14
|
+
resources :comments, options do
|
15
|
+
get 'reply', :on => :member if Opinio.accept_replies
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Opinio
|
4
|
+
class Railtie < ::Rails::Railtie #:nodoc:
|
5
|
+
initializer 'opinio' do |app|
|
6
|
+
ActiveSupport.on_load(:active_record) do
|
7
|
+
require File.join(File.dirname(__FILE__), 'opinio_model')
|
8
|
+
require File.join(File.dirname(__FILE__), 'opinio_subjectum')
|
9
|
+
::ActiveRecord::Base.send :include, Opinio::OpinioModel
|
10
|
+
::ActiveRecord::Base.send :include, Opinio::OpinioSubjectum
|
11
|
+
end
|
12
|
+
ActiveSupport.on_load(:action_view) do
|
13
|
+
require File.join(File.dirname(__FILE__), 'controllers', 'helpers')
|
14
|
+
::ActionView::Base.send :include, Opinio::Controllers::Helpers
|
15
|
+
end
|
16
|
+
ActiveSupport.on_load(:action_controller) do
|
17
|
+
require File.join(File.dirname(__FILE__), 'controllers', 'extensions')
|
18
|
+
::ActionController::Base.send :include, Opinio::Controllers::Extensions
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Opinio
|
2
|
+
module Schema
|
3
|
+
|
4
|
+
def opinio(options = {})
|
5
|
+
null = options[:null] || false
|
6
|
+
default = options.key?(:default) ? options[:default] : ("" if null == false)
|
7
|
+
|
8
|
+
apply_opinio_schema :owner_id, :integer, :null => false
|
9
|
+
apply_opinio_schema :commentable_id, :integer, :null => false
|
10
|
+
apply_opinio_schema :commentable_type, :string, :null => false
|
11
|
+
apply_opinio_schema :title, :string, :default => default, :null => null if options[:title]
|
12
|
+
apply_opinio_schema :body, :text, :null => false
|
13
|
+
end
|
14
|
+
|
15
|
+
# Overwrite with specific modification to create your own schema.
|
16
|
+
def apply_opinio_schema(name, type, options={})
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
shared_examples_for :opinio do
|
2
|
+
|
3
|
+
let(:comment) { Comment.new }
|
4
|
+
let(:owner) { User.create }
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
@post = Post.new(:title => "My first post", :body => "Damn I really suck at writing")
|
8
|
+
@post.save
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have the correct attributes" do
|
12
|
+
should respond_to(:owner)
|
13
|
+
should respond_to(:body)
|
14
|
+
should respond_to(:commentable)
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
it "should not allow comments of comments" do
|
19
|
+
Comment.class_eval do
|
20
|
+
include Opinio::OpinioModel::RepliesSupport
|
21
|
+
end
|
22
|
+
|
23
|
+
c = Comment.new(:body => "The Comment !")
|
24
|
+
c.commentable = @post
|
25
|
+
c.owner = owner
|
26
|
+
c.save.should == true
|
27
|
+
|
28
|
+
c2 = Comment.new(:body => "The Comment !")
|
29
|
+
c2.owner = owner
|
30
|
+
c2.commentable = c
|
31
|
+
c2.save.should == true
|
32
|
+
|
33
|
+
c3 = c2.dup
|
34
|
+
c3.commentable = c2
|
35
|
+
c3.save.should == false
|
36
|
+
|
37
|
+
c3.errors[:base].count.should == 1
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should validate presence of body and commentable" do
|
41
|
+
comment.should be_invalid
|
42
|
+
comment.errors[:body].should be_present
|
43
|
+
comment.errors[:commentable].should be_present
|
44
|
+
end
|
45
|
+
|
46
|
+
it "and it should insist on having an owner" do
|
47
|
+
c = Comment.new(:body => "The Comment !")
|
48
|
+
c.commentable = @post
|
49
|
+
c.save.should == false
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when strip_html_tags_on_save is true" do
|
53
|
+
it "should strip html tags" do
|
54
|
+
comment = create_valid_comment('<h1>Chuck will save us!</h1>')
|
55
|
+
comment.body.should == 'Chuck will save us!'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when strip_html_tags_on_save is false" do
|
60
|
+
|
61
|
+
# we have to create a different class
|
62
|
+
# because opinio adds the strip tags callbacks
|
63
|
+
# only once when opinio is called on the class
|
64
|
+
class NoSanitizerComment < ActiveRecord::Base
|
65
|
+
self.table_name = :comments
|
66
|
+
end
|
67
|
+
|
68
|
+
before do
|
69
|
+
Opinio.stub(:strip_html_tags_on_save).and_return(false)
|
70
|
+
NoSanitizerComment.class_eval do
|
71
|
+
opinio
|
72
|
+
end
|
73
|
+
end
|
74
|
+
it "should not strip html tags" do
|
75
|
+
comment = create_valid_comment('<h1>Chuck will save us!</h1>', NoSanitizerComment)
|
76
|
+
comment.body.should == '<h1>Chuck will save us!</h1>'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
shared_examples_for :opinio_subjectum do
|
84
|
+
|
85
|
+
it "and should add opinio_subjectum functionallity" do
|
86
|
+
should respond_to(:comments)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opinio-bootstrap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Luiz Felipe Garcia Pereira
|
9
|
+
- Richard Carey
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-02-10 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rails
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '3'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: kaminari
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: jquery-rails
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: bootstrap-sass
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 2.2.2.0
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 2.2.2.0
|
79
|
+
description: Opinio is an engine used to add comments functionallity to rails 3 applications;
|
80
|
+
this version is adapted to Twitter Bootstrap.
|
81
|
+
email:
|
82
|
+
- luiz.felipe.gp@gmail.com
|
83
|
+
- rc@rcdmcg.com
|
84
|
+
executables: []
|
85
|
+
extensions: []
|
86
|
+
extra_rdoc_files: []
|
87
|
+
files:
|
88
|
+
- app/controllers/opinio/comments_controller.rb
|
89
|
+
- app/views/opinio/comments/_comment.html.erb
|
90
|
+
- app/views/opinio/comments/_comments.html.erb
|
91
|
+
- app/views/opinio/comments/_new.html.erb
|
92
|
+
- app/views/opinio/comments/create.js.erb
|
93
|
+
- app/views/opinio/comments/destroy.js.erb
|
94
|
+
- app/views/opinio/comments/index.html.erb
|
95
|
+
- app/views/opinio/comments/reply.js.erb
|
96
|
+
- lib/generators/opinio/install/install_generator.rb
|
97
|
+
- lib/generators/opinio/install/templates/initializers/opinio.erb
|
98
|
+
- lib/generators/opinio/install/templates/migrations/create_model.rb
|
99
|
+
- lib/generators/opinio/install/templates/models/model.rb
|
100
|
+
- lib/generators/opinio/views/views_generator.rb
|
101
|
+
- lib/opinio/controllers/extensions.rb
|
102
|
+
- lib/opinio/controllers/helpers.rb
|
103
|
+
- lib/opinio/controllers/internal_helpers.rb
|
104
|
+
- lib/opinio/controllers/replies.rb
|
105
|
+
- lib/opinio/opinio_model/validations.rb
|
106
|
+
- lib/opinio/opinio_model.rb
|
107
|
+
- lib/opinio/opinio_subjectum.rb
|
108
|
+
- lib/opinio/orm/active_record.rb
|
109
|
+
- lib/opinio/rails/routes.rb
|
110
|
+
- lib/opinio/rails.rb
|
111
|
+
- lib/opinio/railtie.rb
|
112
|
+
- lib/opinio/schema.rb
|
113
|
+
- lib/opinio/shared_examples.rb
|
114
|
+
- lib/opinio/version.rb
|
115
|
+
- lib/opinio.rb
|
116
|
+
- config/locales/opinio.en.yml
|
117
|
+
- MIT-LICENSE
|
118
|
+
- Rakefile
|
119
|
+
- Gemfile
|
120
|
+
- README.md
|
121
|
+
homepage: https://github.com/rceee/opinio-bootstrap
|
122
|
+
licenses: []
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ! '>='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ! '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 1.8.24
|
142
|
+
signing_key:
|
143
|
+
specification_version: 3
|
144
|
+
summary: A rails 3 engine for comments, with Twitter Bootstrap styling.
|
145
|
+
test_files: []
|