opinio 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,24 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "kaminari"
6
+ gem "rails", "~> 3.0.4"
7
+ gem "sqlite3"
8
+ gem "jquery-rails"
9
+
10
+ group :development do
11
+ gem "ruby-debug19"
12
+ end
13
+
14
+ group :test do
15
+ gem "cucumber"
16
+ gem "cucumber-rails"
17
+ gem "capybara"
18
+ gem "launchy"
19
+ gem "database_cleaner"
20
+ gem "rspec-rails"
21
+ end
22
+ # To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
23
+ # gem 'ruby-debug'
24
+ # gem 'ruby-debug19'
@@ -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.
@@ -0,0 +1,127 @@
1
+ = Opinio
2
+
3
+ == Description
4
+
5
+ Opinio is an engine used to add comments behaviour to your application.
6
+ The engine is designed to work only with *Rails 3*
7
+
8
+ == Intallation
9
+
10
+ Simply add the following line to your *Gemfile*:
11
+
12
+ gem "opinio"
13
+
14
+ and run:
15
+
16
+ bundle
17
+
18
+ == Documentation
19
+
20
+ Rdocs here:
21
+ http://rubydoc.info/github/Draiken/opinio/master/frames
22
+
23
+
24
+ == Usage
25
+
26
+ Opinio provides generators to facilitate it's usage.
27
+ The most common way to quickly get Opinio working is:
28
+
29
+ rails g opinio:install comment
30
+
31
+ This will generate the *Comment* model, migration and also generate the opinio initializer for customization of the engine.
32
+ A `opinio_model` will be added on the `routes.rb`. This method adds the default urls for the model that will acts as the comment
33
+
34
+ In order to add the comments functionallity to a model, you use the *opinio_subjectum* method
35
+
36
+ class Post < ActiveRecord::Base
37
+ opinio_subjectum
38
+ end
39
+
40
+ On the `routes.rb` you should simply add an `opinio` for your resource that will have comments
41
+
42
+ resources :posts do
43
+ opinio
44
+ end
45
+
46
+ If you want to display the comments for the item outside of the resource, you can simply add this to your views:
47
+
48
+ <%= comments_for @post %>
49
+
50
+ And there you go, you can now comment in your post.
51
+ Aditional options can be found on the {RDocs}[http://rubydoc.info/github/Draiken/opinio/master/frames]
52
+
53
+ == Customization
54
+
55
+ === Views
56
+
57
+ 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:
58
+
59
+ rails g opinio:views
60
+
61
+ And you can customize all the views used by the engine.
62
+
63
+ === Behaviour
64
+
65
+ ==== Pretty Urls
66
+
67
+ Often times you will want the engine to show the index of comments for a specific item
68
+ without having to pass *:commentable_type* or *:commentable_id*.
69
+
70
+ In order to do that, opinio provides a method to *ActionController::Base*:
71
+
72
+ opinio_identifier do |params|
73
+ next Review.find(params[:review_id]) if params[:review_id]
74
+ next Product.find(params[:product_id]) if params[:product_id]
75
+ end
76
+
77
+ Note: you use next instead of return because it is a proc that will be executed later on, and you cannot return on procs
78
+
79
+ Basically on this method you receive the *params* variable and you tell the engine, who owns
80
+ the comments from that page.
81
+ This allows you to use routes like:
82
+
83
+ /products/1/comments
84
+ /products/1/reviews/1/comments
85
+
86
+ Without passing those 2 parameters.
87
+ I suggest you put this method on the *ApplicationController*
88
+
89
+ ==== Customize destroy conditions
90
+
91
+ By default, anyone can destroy any comment in the engine. We don't want that.
92
+ To setup a custom destroy condition we can use the methods provided by opinio
93
+ in our controllers. For instance, if our opinio model is called 'comment'
94
+ it would be like this:
95
+
96
+ comment_destroy_conditions do |comment|
97
+ comment.owner == current_user
98
+ end
99
+
100
+ This would make users only be able to remove their own comments.
101
+ Another example would be using the *CanCan*:
102
+
103
+ comment_destroy_conditions do |comment|
104
+ authorize :destroy, comment
105
+ end
106
+
107
+ You get the picture, you're inside your controller's methods on that block
108
+ so you can call anything your normal controllers call on actions.
109
+
110
+ == Contribution
111
+
112
+ 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.
113
+ For issues please use the github {issues tracker}[https://github.com/Draiken/opinio/issues]
114
+
115
+ Remember this engine is still in development :)
116
+
117
+ === TODO
118
+
119
+ * Haml views
120
+ * Better controller overriding (coding and documentation)
121
+ * Support for deeper levels of replies
122
+ * Refactor the `comments_for` helper
123
+ * Extract documentation to wiki
124
+ * Add tons of rspecs for
125
+ * controllers
126
+ * routes
127
+ * model extensions
@@ -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 'rake/rdoctask'
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,33 @@
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 = current_user
12
+ if @comment.save
13
+ flash[:notice] = I18n.translate('opinio.comment.sent', :default => "Comment sent successfully.")
14
+ else
15
+ flash[:error] = I18n.translate('opinio.comment.error', :default => "Error sending the comment.")
16
+ end
17
+ end
18
+
19
+ def destroy
20
+ @comment = Opinio.model_name.constantize.find(params[:id])
21
+
22
+ if can_destroy_opinio?(@comment)
23
+ @comment.destroy
24
+ flash[:notice] = I18n.translate('opinio.comment.destroyed', :default => "Comment removed successfully")
25
+ else
26
+ #flash[:error] = I18n.translate('opinio.comment.not_permitted', :default => "Not permitted")
27
+ logger.warning "user #{current_user.email} tried to remove a comment from another user #{@comment.owner.email}"
28
+ render :text => "unauthorized", :status => 401
29
+ end
30
+ end
31
+
32
+
33
+ end
@@ -0,0 +1,15 @@
1
+ <% reply = defined?(reply) ? reply : false %>
2
+ <li id="comment_<%= comment.id %>">
3
+ <span>User: <%= comment.owner.id %></span>
4
+ <p>
5
+ <%= comment.body %>
6
+ </p>
7
+ <%= link_to 'Destroy', comment_path(comment), :method => :delete, :remote => true %>
8
+ <%# this enables only 1 level of replies %>
9
+ <% if Opinio.accept_replies && !reply %>
10
+ <span><%= link_to t("opinio.reply", :default => "Reply"), reply_comment_path(comment), :remote => true %></span>
11
+ <ul id="comment_<%= comment.id %>_replies" class="replies">
12
+ <%= render :partial => "opinio/comments/comment", :collection => comment.comments, :locals => {:reply => true} %>
13
+ </ul>
14
+ <% end %>
15
+ </li>
@@ -0,0 +1,15 @@
1
+ <div>
2
+ <%= paginate comments %>
3
+ </div>
4
+
5
+ <ul id="comments">
6
+ <% unless comments.empty? %>
7
+ <%= render :partial => 'opinio/comments/comment', :collection => comments %>
8
+ <% else %>
9
+ <li id="no_comments"><%= t 'opinio.no_comments_found', :default => "No comments found" %></li>
10
+ <% end %>
11
+ </ul>
12
+
13
+ <div>
14
+ <%= paginate comments %>
15
+ </div>
@@ -0,0 +1,18 @@
1
+ <div id="new_comment">
2
+ <% if current_user %>
3
+ <h2>Send Comments</h3>
4
+ <%= form_for Comment.new, :remote => true do |f| %>
5
+ <p>
6
+ <%= f.label :body, "Comment" %>
7
+ <%= f.text_area :body %>
8
+ </p>
9
+ <%= hidden_field_tag :commentable_id, commentable.id %>
10
+ <%= hidden_field_tag :commentable_type, commentable.class.base_class.name.to_s %>
11
+ <%= f.submit "Send Comment" %>
12
+ <% end %>
13
+ <% else %>
14
+ <p>
15
+ Must be logged in to comment.
16
+ </p>
17
+ <% end %>
18
+ </div>
@@ -0,0 +1,11 @@
1
+ jQuery('#no_comments').fadeOut()
2
+ <% if @reply %>
3
+ if(jQuery('#comment_<%= @comment.commentable_id %> ul').length == 0)
4
+ jQuery('#comment_<%= @comment.commentable_id %>').append('<ul id="comment_<%= @comment.commentable_id %>_replies" class="replies"></ul>')
5
+ jQuery('#comment_<%= @comment.commentable_id %>_replies').append("<%= escape_javascript( render @comment, :locals => {:reply => @reply} ) %>")
6
+ jQuery('#commentable_id').val('<%= @comment.commentable.commentable_id %>')
7
+ jQuery('#commentable_type').val('<%= @comment.commentable.commentable_type %>')
8
+ <% else %>
9
+ jQuery('#comments').prepend("<%= escape_javascript( render @comment, :locals => {:reply => @reply} ) %>")
10
+ <% end %>
11
+
@@ -0,0 +1,3 @@
1
+ jQuery('#comment_<%= @comment.id %>').remove();
2
+ jQuery('#comments').prepend("<%= escape_javascript(flash[:notice]) %>");
3
+ jQuery('#comments').prepend("<%= escape_javascript(flash[:error]) %>");
@@ -0,0 +1,7 @@
1
+ <h1>Comments</h1>
2
+
3
+ <%= paginate @comments %>
4
+
5
+ <%= render :partial => "opinio/comments/comments", :locals => { :comments => @comments } %>
6
+
7
+ <%= paginate @comments %>
@@ -0,0 +1,3 @@
1
+ jQuery("#commentable_id").val('<%= @commentable_id %>')
2
+ jQuery("#commentable_type").val('<%= @commentable_type %>')
3
+ jQuery("#new_comment textarea").focus()
@@ -0,0 +1,34 @@
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 self.next_migration_number(dirname)
26
+ if ActiveRecord::Base.timestamped_migrations
27
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
28
+ else
29
+ "%.3d" % (current_migration_number(dirname) + 1)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
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
+ end
@@ -0,0 +1,13 @@
1
+ class Create<%= table_name.camelize %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :<%= table_name %> do |t|
4
+ t.opinio
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :<%= table_name %>
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ class <%= class_name %> < ActiveRecord::Base
2
+ opinio
3
+ end
@@ -0,0 +1,13 @@
1
+ module Opinio
2
+ module Generators
3
+ class ViewsGenerator < Rails::Generators::Base
4
+
5
+ source_root File.expand_path('../../../../../app/views', __FILE__)
6
+
7
+ def copy_views
8
+ directory "opinio", "app/views/opinio"
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ module Opinio
2
+ #autoload :Railtie, 'opinio/railtie'
3
+ autoload :Schema, 'opinio/schema'
4
+
5
+ module Controllers
6
+ autoload :Helpers, 'opinio/controllers/helpers'
7
+ autoload :InternalHelpers, 'opinio/controllers/internal_helpers'
8
+ autoload :Replies, 'opinio/controllers/replies'
9
+ end
10
+
11
+ mattr_accessor :model_name
12
+ @@model_name = "Comment"
13
+
14
+ mattr_accessor :owner_class_name
15
+ @@owner_class_name = "User"
16
+
17
+ mattr_accessor :use_title
18
+ @@use_title = false
19
+
20
+ mattr_accessor :accept_replies
21
+ @@accept_replies = false
22
+
23
+ mattr_accessor :custom_identifiers
24
+ @@custom_identifiers = Array.new
25
+
26
+ mattr_accessor :interval_between_comments
27
+ @@interval_between_comments = false
28
+
29
+ mattr_accessor :destroy_conditions
30
+ @@destroy_conditions = Proc.new { true }
31
+
32
+ def self.setup
33
+ yield self
34
+ end
35
+
36
+ def self.opinio_identifier(block)
37
+ @@custom_identifiers << block
38
+ end
39
+
40
+ def self.set_destroy_conditions(&block)
41
+ @@destroy_conditions = block
42
+ end
43
+
44
+ def self.check_custom_identifiers(params)
45
+ self.custom_identifiers.each do |idf|
46
+ ret = idf.call(params)
47
+ return ret unless ret.nil?
48
+ end
49
+ nil
50
+ end
51
+
52
+ require File.join(File.dirname(__FILE__), 'opinio', 'railtie')
53
+ require File.join(File.dirname(__FILE__), 'opinio', 'rails')
54
+ require File.join(File.dirname(__FILE__), 'opinio', 'orm', 'active_record')
55
+ end
@@ -0,0 +1,27 @@
1
+ module Opinio
2
+ module Controllers
3
+ module Extensions
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ (class << self; self; end).instance_eval do
8
+ define_method "#{Opinio.model_name.underscore}_destroy_conditions" do |&block|
9
+ Opinio.set_destroy_conditions( &block )
10
+ end
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ def opinio_identifier(&block)
16
+ Opinio.opinio_identifier(block)
17
+ end
18
+ end
19
+
20
+ module InstanceMethods
21
+ def can_destroy_opinio?(opinio)
22
+ self.instance_exec(opinio, &Opinio.destroy_conditions)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ 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
+ render( :partial => "opinio/comments/comments", :locals => {:comments => object.comments.page(1).limit(limit), :commentable => object, :options => options} )
13
+ end
14
+
15
+ def render_comments_form(object, options = {})
16
+ render( :partial => "opinio/comments/new", :locals => {:commentable => object, :options => options} )
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,33 @@
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
+ end
32
+ end
33
+ 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,112 @@
1
+ module Opinio
2
+ module OpinioModel
3
+
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ # Adds the Opinio functionallity to the model
11
+ # You can pass a hash of options to customize the Opinio model
12
+ #
13
+ # === Options
14
+ #
15
+ # [:belongs_to]
16
+ # You can specify the class that owns the comments on
17
+ # +config/initializers/opinio.rb+
18
+ # but you can also pass it explicitly here:
19
+ # eg. <tt>:belongs_to => "Admin"</tt>
20
+ # [:counter_cache]
21
+ # Customize the counter cache here, defaults to false
22
+ # [:body_length]
23
+ # You can pass a <tt>Range</tt> to determine the size of the body that will be
24
+ # validated
25
+ # [:title_length]
26
+ # If you are using titles in your opinio model (set on the
27
+ # initializer) you can pass a <tt>Range</tt> so it is validated.
28
+ def opinio(*args)
29
+ return if self.included_modules.include?(Opinio::OpinioModel::InstanceMethods)
30
+ options = args.extract_options!
31
+
32
+ if Opinio.use_title
33
+ attr_accessible :title
34
+ validates :title,
35
+ {}.merge( :length => options[:title_length] )
36
+ end
37
+ attr_accessible :body
38
+
39
+ commentable_options = { :polymorphic => true }
40
+ if options[:counter_cache]
41
+ commentable_options.merge!(:counter_cache => options[:counter_cache])
42
+ end
43
+
44
+ belongs_to :commentable, commentable_options
45
+ belongs_to :owner, :class_name => options.reverse_merge(:belongs_to => Opinio.owner_class_name)[:belongs_to]
46
+
47
+ #TODO: refactor this
48
+ if Opinio.interval_between_comments
49
+ validate :last_comment_time, :if => :new_record?
50
+ cattr_accessor :comments_interval
51
+ self.comments_interval = options.reverse_merge(:time => Opinio.interval_between_comments)[:time]
52
+ end
53
+
54
+ extra_options = {}
55
+ if options[:body_length]
56
+ extra_options = { :length => options[:body_length] }
57
+ end
58
+
59
+ validates :body,
60
+ { :presence => true }.reverse_merge(extra_options)
61
+
62
+ validates_presence_of :commentable
63
+
64
+ scope :owned_by, lambda {|owner| where('owner_id = ?', owner.id) }
65
+
66
+ send :include, Opinio::OpinioModel::InstanceMethods
67
+
68
+ if Opinio.accept_replies
69
+ validate :cannot_be_comment_of_a_comments_comment
70
+ opinio_subjectum :order => 'created_at ASC'
71
+ end
72
+
73
+ end
74
+ end
75
+
76
+ module InstanceMethods
77
+
78
+ private
79
+
80
+ # Checks the time of the last comment
81
+ # made by the same owner
82
+ def last_comment_time
83
+ last_comment = Comment.owned_by(self.owner).order('created_at DESC').last
84
+ if last_comment
85
+ if (Time.now - last_comment.created_at).round >= self.comments_interval
86
+ true
87
+ else
88
+ errors.add(
89
+ :created_at,
90
+ I18n.t('opinio.comment_interval',
91
+ :time => self.comments_interval,
92
+ :default => "You must wait %{time} seconds to comment again.")
93
+ )
94
+ false
95
+ end
96
+ else
97
+ true
98
+ end
99
+ end
100
+
101
+ # Validates that you cannot comment on a comment's comment
102
+ def cannot_be_comment_of_a_comments_comment
103
+ if new_record? && self.commentable_type == Opinio.model_name
104
+ if commentable.commentable_type == Opinio.model_name
105
+ errors.add :base, I18n.translate('opinio.cannot_be_comment_of_comment', :default => 'Cannot reply another comment\'s reply')
106
+ end
107
+ end
108
+ end
109
+
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,28 @@
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
+
12
+ has_many :comments,
13
+ :class_name => Opinio.model_name,
14
+ :as => :commentable,
15
+ :order => options.reverse_merge(:order => "created_at DESC")[:order],
16
+ :dependent => :destroy
17
+
18
+
19
+ send :include, Opinio::OpinioSubjectum::InstanceMethods
20
+ end
21
+ end
22
+
23
+ module InstanceMethods
24
+
25
+ end
26
+
27
+ end
28
+ 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
+
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(__FILE__), 'rails', 'routes')
2
+
3
+ module Opinio
4
+ class Engine < ::Rails::Engine
5
+
6
+ end
7
+ end
8
+
@@ -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, :controller => options[:controller] 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,5 @@
1
+ module Opinio
2
+ class Version
3
+ VERSION = '0.3.0'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opinio
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Luiz Felipe Garcia Pereira
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-09 00:00:00.000000000 -03:00
13
+ default_executable:
14
+ dependencies: []
15
+ description: Opinio is an engine used to add comments functionallity to rails 3 applications.
16
+ email:
17
+ - luiz.felipe.gp@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - app/controllers/opinio/comments_controller.rb
23
+ - app/views/opinio/comments/_comment.html.erb
24
+ - app/views/opinio/comments/_comments.html.erb
25
+ - app/views/opinio/comments/_new.html.erb
26
+ - app/views/opinio/comments/create.js.erb
27
+ - app/views/opinio/comments/destroy.js.erb
28
+ - app/views/opinio/comments/index.html.erb
29
+ - app/views/opinio/comments/reply.js.erb
30
+ - lib/generators/opinio/install/install_generator.rb
31
+ - lib/generators/opinio/install/templates/initializers/opinio.erb
32
+ - lib/generators/opinio/install/templates/migrations/create_model.rb
33
+ - lib/generators/opinio/install/templates/models/model.rb
34
+ - lib/generators/opinio/views/views_generator.rb
35
+ - lib/opinio/controllers/extensions.rb
36
+ - lib/opinio/controllers/helpers.rb
37
+ - lib/opinio/controllers/internal_helpers.rb
38
+ - lib/opinio/controllers/replies.rb
39
+ - lib/opinio/opinio_model.rb
40
+ - lib/opinio/opinio_subjectum.rb
41
+ - lib/opinio/orm/active_record.rb
42
+ - lib/opinio/rails/routes.rb
43
+ - lib/opinio/rails.rb
44
+ - lib/opinio/railtie.rb
45
+ - lib/opinio/schema.rb
46
+ - lib/opinio/version.rb
47
+ - lib/opinio.rb
48
+ - MIT-LICENSE
49
+ - Rakefile
50
+ - Gemfile
51
+ - README.rdoc
52
+ has_rdoc: true
53
+ homepage:
54
+ licenses: []
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 1.6.2
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: A rails 3 engine for comments.
77
+ test_files: []