threadable_comments 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8e83c7e0fa3f4799b786f915c46241a4321c5bde
4
+ data.tar.gz: 6faa2940f9adba73c791febdb6a7990f09515473
5
+ SHA512:
6
+ metadata.gz: 1190c7803b1d67de5961c6b8cf15a29d127ed788139693548ef583c94490287f3df2635f97c0443ef2ef04da18ba37f0cc13898d36a380557480b455c93f6c75
7
+ data.tar.gz: 2ecf93b1aaf627a5a8122ae5f62fc50a2da0fe176f38365afcede5430a413c26417b79ab45869b32ea87ce4484b4adf043c12de2bb31d3b8fa26a0b28435fba4
@@ -0,0 +1,7 @@
1
+ .rvmrc
2
+ .ruby-version
3
+ gemfiles/*.lock
4
+ pkg/*
5
+ spec/debug.log
6
+ Gemfile.lock
7
+ .idea/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,4 @@
1
+ v0.1.0
2
+ ------
3
+
4
+ - Initial Release.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Yves Riel
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,72 @@
1
+ Threadable Comments
2
+ ===================
3
+
4
+ Allows for threaded comments to be added to different models while comment hierarchy is handled via the [ancestry gem](https://github.com/stefankroes/ancestry) (uses a materialised path pattern).
5
+
6
+ Install
7
+ -------
8
+ In your Gemfile, add:
9
+
10
+ gem 'threadable_comments'
11
+
12
+ and run `bundle install`.
13
+
14
+ Migrations
15
+ ----------
16
+ * To install:
17
+
18
+ rails generate threadable_comments:migration
19
+
20
+ This will generate the migration script necessary for the table
21
+
22
+ Usage
23
+ -----
24
+ class Article < ActiveRecord::Base
25
+ has_threadable_comments
26
+ end
27
+
28
+ * Add a comment to a model instance, for example an Article:
29
+
30
+ @user_who_commented = @current_user
31
+ @article.add_comment "This is my comment!", @user_who_commented
32
+
33
+ * To reply to a comment:
34
+
35
+ @comment.reply = "This is a reply!", @user_who_commented
36
+
37
+ * To retrieve all comments for an article, including child comments:
38
+
39
+ @all_comments = @article.comments
40
+
41
+ * To retrieve only the root comments without their child comments:
42
+
43
+ @root_comments = @article.root_comments
44
+
45
+ * To check if a comment has children:
46
+
47
+ @comment.has_children?
48
+
49
+ * To get a comment's parent:
50
+
51
+ @comment.parent
52
+
53
+ * To verify the number of direct children a comment has:
54
+
55
+ @comment.children.count
56
+
57
+ * To verify the number of children and grand-children a comment has:
58
+
59
+ @comment.descendants.count
60
+
61
+ * To retrieve a comment's children:
62
+
63
+ @comment.children
64
+
65
+ Tips
66
+ ----
67
+ Once you have a comment in your hands, you can use all the methods and scope of the [ancestry gem](https://github.com/stefankroes/ancestry) to access children and parents of the comment.
68
+
69
+ Credits
70
+ -------
71
+ * Inspired from [act_as_commentable_with_threading](https://github.com/elight/acts_as_commentable_with_threading)
72
+
@@ -0,0 +1,11 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rspec/core/rake_task'
8
+
9
+ RSpec::Core::RakeTask.new('spec')
10
+
11
+ task default: :spec
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'threadable_comments'
@@ -0,0 +1,16 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ module ThreadableComments
4
+ module Generators
5
+ # Migration generator that creates migration file from template
6
+ class MigrationGenerator < ActiveRecord::Generators::Base
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ argument :name, :type => :string, :default => 'create_comments'
10
+ # Create migration in project's folder
11
+ def generate_files
12
+ migration_template 'migration.rb', "db/migrate/#{name}.rb"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ # Migration responsible for creating a table for comments
2
+ class CreateComments < ActiveRecord::Migration
3
+ # Create table
4
+ def self.up
5
+ create_table :comments, force: true do |t|
6
+ t.belongs_to :commentable, :polymorphic => true, null: false
7
+ t.integer 'user_id', null: false
8
+ t.text 'text', default: ''
9
+ t.text 'parameters', default: ''
10
+ t.string 'ancestry'
11
+ t.timestamps null: false
12
+ end
13
+
14
+ add_index :comments, :user_id
15
+ add_index :comments, :ancestry
16
+ add_index :comments, :commentable_id
17
+ end
18
+
19
+ # Drop table
20
+ def self.down
21
+ drop_table :comments
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ require 'active_record'
2
+ require 'threadable_comments/version'
3
+ require 'threadable_comments/comment'
4
+
5
+ module ThreadableComments
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def has_threadable_comments
10
+ has_many :comments, class_name: '::ThreadableComments::Comment', as: :commentable, dependent: :destroy
11
+ include ThreadableComments::InstanceMethods
12
+ end
13
+ end
14
+
15
+ module InstanceMethods
16
+ # Scope comments to only root threads, no children/replies
17
+ def root_comments
18
+ comments.roots
19
+ end
20
+
21
+ # scope comments to specific user
22
+ def comments_by(user)
23
+ raise ArgumentError.new("User must have an ID property") unless user.respond_to? :id
24
+
25
+ comments.where(user_id: user.id)
26
+ end
27
+
28
+ def add_comment(text, user, parameters = {})
29
+ new_comment = ThreadableComments::Comment.create(commentable: self,
30
+ text: text,
31
+ user_id: user.id,
32
+ parameters: parameters)
33
+ comments << new_comment
34
+ new_comment
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ ActiveRecord::Base.send(:include, ThreadableComments)
@@ -0,0 +1,31 @@
1
+ require 'ancestry'
2
+
3
+ module ThreadableComments
4
+ class Comment < ActiveRecord::Base
5
+ has_ancestry orphan_strategy: :destroy
6
+ default_scope { order(created_at: :desc) }
7
+
8
+ validates :commentable, presence: true
9
+ validates :user, presence: true
10
+
11
+ belongs_to :commentable, polymorphic: true
12
+ belongs_to :user
13
+ serialize :parameters
14
+
15
+ def reply(text, user)
16
+ Comment.create \
17
+ commentable: commentable,
18
+ text: text,
19
+ user_id: user.id,
20
+ parent: self
21
+ end
22
+
23
+ # Scope to find all comments for specific user
24
+ scope :by_user, lambda { |user|
25
+ raise ArgumentError.new("User must have an ID property") unless user.respond_to? :id
26
+
27
+ where(user_id: user.id)
28
+ }
29
+
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module ThreadableComments
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,57 @@
1
+ require 'rspec'
2
+
3
+ describe ThreadableComments::Comment do
4
+
5
+ let(:user) {User.create!}
6
+ let(:commentable) {Commentable.create!}
7
+
8
+ let(:comment) {ThreadableComments::Comment.create(commentable: commentable, user: user, text: 'This is a comment')}
9
+
10
+ after(:example) do
11
+ ThreadableComments::Comment.destroy_all
12
+ end
13
+
14
+
15
+ it 'should validate a commentable' do
16
+ comment.commentable = nil
17
+
18
+ expect(comment.valid?).to be_falsey
19
+ end
20
+
21
+ it 'should validate the presence of user' do
22
+ comment.user = nil
23
+
24
+ expect(comment.valid?).to be_falsey
25
+ end
26
+
27
+ it 'can be replied to' do
28
+ new_comment = comment.reply('this is a reply!', user)
29
+ comment.reply('this is another reply!', user)
30
+
31
+ expect(new_comment.parent).to eq(comment)
32
+ expect(comment.children.count).to eq(2)
33
+ end
34
+
35
+ it 'can have reply to a reply' do
36
+ new_comment = comment.reply('this is a reply!', user).reply('this is a sub reply!', user)
37
+
38
+ expect(comment.descendants.count).to eq(2)
39
+ end
40
+
41
+ it 'destroys all of its children and their descendants' do
42
+ comment.reply('this is a reply!', user).reply('this is a sub reply!', user)
43
+
44
+ expect{comment.destroy}.to change{ThreadableComments::Comment.count}.by(-3)
45
+ end
46
+
47
+ it 'retrieves all comments for a particular user' do
48
+ other_user = User.create!
49
+ comment.reply('this is a reply!', user)
50
+ comment.reply('this is the other user reply!', other_user)
51
+
52
+ expect(ThreadableComments::Comment.count).to eq(3)
53
+ expect(ThreadableComments::Comment.by_user(other_user).count).to eq(1)
54
+ expect(ThreadableComments::Comment.by_user(user).count).to eq(2)
55
+ end
56
+
57
+ end
@@ -0,0 +1,4 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: ":memory:"
4
+ timeout: 500
@@ -0,0 +1,19 @@
1
+ ActiveRecord::Schema.define(version: 1) do
2
+ create_table 'users', force: true
3
+
4
+ create_table 'commentables', force: true
5
+
6
+ create_table 'comments', force: true do |t|
7
+ t.integer 'commentable_id', null: false
8
+ t.string 'commentable_type', null: false
9
+ t.text 'text', default: ''
10
+ t.integer 'user_id', null: false
11
+ t.string 'ancestry'
12
+ t.text 'parameters', default: ''
13
+ t.timestamps null: false
14
+ end
15
+
16
+ add_index 'comments', 'user_id'
17
+ add_index 'comments', 'ancestry'
18
+ add_index 'comments', 'commentable_id'
19
+ end
@@ -0,0 +1,99 @@
1
+ Dir[File.expand_path('../support/**/*.rb',__FILE__)].each { |f| require f }
2
+
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
6
+ # this file to always be loaded, without a need to explicitly require it in any
7
+ # files.
8
+ #
9
+ # Given that it is always loaded, you are encouraged to keep this file as
10
+ # light-weight as possible. Requiring heavyweight dependencies from this file
11
+ # will add to the boot time of your test suite on EVERY test run, even for an
12
+ # individual file that may not need all of that loaded. Instead, consider making
13
+ # a separate helper file that requires the additional dependencies and performs
14
+ # the additional setup, and require it from the spec files that actually need
15
+ # it.
16
+ #
17
+ # The `.rspec` file also contains a few flags that are not defaults but that
18
+ # users commonly want.
19
+ #
20
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
+ RSpec.configure do |config|
22
+ # rspec-expectations config goes here. You can use an alternate
23
+ # assertion/expectation library such as wrong or the stdlib/minitest
24
+ # assertions if you prefer.
25
+ config.expect_with :rspec do |expectations|
26
+ # This option will default to `true` in RSpec 4. It makes the `description`
27
+ # and `failure_message` of custom matchers include text for helper methods
28
+ # defined using `chain`, e.g.:
29
+ # be_bigger_than(2).and_smaller_than(4).description
30
+ # # => "be bigger than 2 and smaller than 4"
31
+ # ...rather than:
32
+ # # => "be bigger than 2"
33
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # The settings below are suggested to provide a good initial experience
46
+ # with RSpec, but feel free to customize to your heart's content.
47
+ =begin
48
+ # These two settings work together to allow you to limit a spec run
49
+ # to individual examples or groups you care about by tagging them with
50
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
51
+ # get run.
52
+ config.filter_run :focus
53
+ config.run_all_when_everything_filtered = true
54
+
55
+ # Allows RSpec to persist some state between runs in order to support
56
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
57
+ # you configure your source control system to ignore this file.
58
+ config.example_status_persistence_file_path = "spec/examples.txt"
59
+
60
+ # Limits the available syntax to the non-monkey patched syntax that is
61
+ # recommended. For more details, see:
62
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
63
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
64
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
65
+ config.disable_monkey_patching!
66
+
67
+ # This setting enables warnings. It's recommended, but in some cases may
68
+ # be too noisy due to issues in dependencies.
69
+ config.warnings = true
70
+
71
+ # Many RSpec users commonly either run the entire suite or an individual
72
+ # file, and it's useful to allow more verbose output when running an
73
+ # individual spec file.
74
+ if config.files_to_run.one?
75
+ # Use the documentation formatter for detailed output,
76
+ # unless a formatter has already been configured
77
+ # (e.g. via a command-line flag).
78
+ config.default_formatter = 'doc'
79
+ end
80
+
81
+ # Print the 10 slowest examples and example groups at the
82
+ # end of the spec run, to help surface which specs are running
83
+ # particularly slow.
84
+ config.profile_examples = 10
85
+
86
+ # Run specs in random order to surface order dependencies. If you find an
87
+ # order dependency and want to debug it, you can fix the order by providing
88
+ # the seed, which is printed after each run.
89
+ # --seed 1234
90
+ config.order = :random
91
+
92
+ # Seed global randomization in this process using the `--seed` CLI option.
93
+ # Setting this allows you to use `--seed` to deterministically reproduce
94
+ # test failures related to randomization by passing the same `--seed` value
95
+ # as the one that triggered the failure.
96
+ Kernel.srand config.seed
97
+ =end
98
+ end
99
+
@@ -0,0 +1,5 @@
1
+ require 'active_record'
2
+
3
+ ActiveRecord::Base.configurations = YAML.load_file(File.expand_path('../../db/database.yml',__FILE__))
4
+ ActiveRecord::Base.establish_connection((ENV['DB'] || 'sqlite3').to_sym)
5
+ load(File.expand_path('../../db/schema.rb',__FILE__))
@@ -0,0 +1,10 @@
1
+ require 'active_record'
2
+ require 'threadable_comments'
3
+
4
+ class User < ActiveRecord::Base
5
+ has_many :comments
6
+ end
7
+
8
+ class Commentable < ActiveRecord::Base
9
+ has_threadable_comments
10
+ end
@@ -0,0 +1,62 @@
1
+ require 'rspec'
2
+
3
+ describe ThreadableComments do
4
+
5
+ describe 'A class that is commentable' do
6
+ let(:user) {User.create!}
7
+ let(:other_user) {User.create!}
8
+ let(:commentable) {Commentable.create!}
9
+ let(:other_commentable) {Commentable.create!}
10
+
11
+ before(:example) do
12
+ commentable.add_comment('This is my comment', user).reply('And this is the reply', user)
13
+ commentable.add_comment('This is another comment', user).reply('And this is its reply', user)
14
+ other_commentable.add_comment('Yet another comment', other_user)
15
+ end
16
+
17
+ after(:example) do
18
+ ThreadableComments::Comment.destroy_all
19
+ end
20
+
21
+ it 'can be commented upon' do
22
+ last_comment = commentable.comments.last
23
+ expect(last_comment.text).to eq('This is my comment')
24
+ expect(last_comment.commentable).to eq(commentable)
25
+ expect(last_comment.user_id).to eq(user.id)
26
+ expect(last_comment.parameters.empty?).to be_truthy
27
+ end
28
+
29
+ it 'accepts parameter hash' do
30
+ new_comment = commentable.add_comment('My Comment', user, param1: true, param2: 'My Param')
31
+
32
+ expect(new_comment.parameters[:param1]).to be_truthy
33
+ expect(new_comment.parameters[:param2]).to eq('My Param')
34
+ end
35
+
36
+ it 'lists the comments by creation date' do
37
+ expect(commentable.comments.first.text).to eq('And this is its reply')
38
+ end
39
+
40
+ it 'can retrieve root comments only' do
41
+ expect(commentable.root_comments.count).to eq(2)
42
+ end
43
+
44
+ it 'can retrieve comments made by a specific user' do
45
+ commentable.root_comments.first.reply('Other user reply', other_user)
46
+
47
+ expect(commentable.comments.count).to eq(5)
48
+ expect(commentable.comments_by(other_user).count).to eq(1)
49
+ end
50
+
51
+ describe 'when it is destroyed' do
52
+ it 'destroys its own root comments along with their children' do
53
+ expect{commentable.destroy}.to change{ThreadableComments::Comment.count}.by(-4)
54
+ end
55
+
56
+ it 'does not destroy other root comments' do
57
+ commentable.destroy
58
+ expect(ThreadableComments::Comment.count).to eq(1)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../lib/threadable_comments/version', __FILE__)
2
+
3
+ # Describe your gem and declare its dependencies:
4
+ Gem::Specification.new do |s|
5
+ s.name = "threadable_comments"
6
+ s.version = ThreadableComments::VERSION
7
+ s.authors = ["Yves Riel"]
8
+ s.email = ["whyves@okapya.com"]
9
+ s.homepage = "https://github.com/Whyves/threadable_comments"
10
+ s.summary = "Allow then creation of comment thread"
11
+ s.description = "Create comments along with their threads on any commentable object. Use Ancestry gem."
12
+ s.license = "MIT"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- spec`.split("\n")
16
+
17
+ s.add_development_dependency "rspec", "~> 3.4"
18
+ s.add_development_dependency "sqlite3"
19
+
20
+ s.add_dependency "rails", "~> 4.0"
21
+ s.add_dependency 'ancestry', '~> 2.1'
22
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: threadable_comments
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yves Riel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.4'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ancestry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.1'
69
+ description: Create comments along with their threads on any commentable object. Use
70
+ Ancestry gem.
71
+ email:
72
+ - whyves@okapya.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - CHANGELOG.md
80
+ - Gemfile
81
+ - MIT-LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - init.rb
85
+ - lib/generators/threadable_comments/migration/migration_generator.rb
86
+ - lib/generators/threadable_comments/migration/templates/migration.rb
87
+ - lib/threadable_comments.rb
88
+ - lib/threadable_comments/comment.rb
89
+ - lib/threadable_comments/version.rb
90
+ - spec/comment_spec.rb
91
+ - spec/db/database.yml
92
+ - spec/db/schema.rb
93
+ - spec/spec_helper.rb
94
+ - spec/support/connection.rb
95
+ - spec/support/environment_setup.rb
96
+ - spec/threadable_comments_spec.rb
97
+ - threadable_comments.gemspec
98
+ homepage: https://github.com/Whyves/threadable_comments
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.2.2
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Allow then creation of comment thread
122
+ test_files:
123
+ - spec/comment_spec.rb
124
+ - spec/db/database.yml
125
+ - spec/db/schema.rb
126
+ - spec/spec_helper.rb
127
+ - spec/support/connection.rb
128
+ - spec/support/environment_setup.rb
129
+ - spec/threadable_comments_spec.rb