opinio 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []