acts_as_king 0.0.1
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/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.rdoc +52 -0
- data/Rakefile +20 -0
- data/acts_as_king.gemspec +24 -0
- data/lib/acts_as_king.rb +74 -0
- data/lib/acts_as_king/railtie.rb +12 -0
- data/lib/acts_as_king/version.rb +3 -0
- data/test/acts_as_king_test.rb +46 -0
- data/test/helper.rb +38 -0
- metadata +108 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
== ActsAsKing
|
2
|
+
|
3
|
+
Rails gem to provide self referencing hierarchy for ActiveRecord models.
|
4
|
+
|
5
|
+
=== Installation
|
6
|
+
|
7
|
+
gem install acts_as_king
|
8
|
+
|
9
|
+
More preferrably in your Gemfile
|
10
|
+
gem 'acts_as_king'
|
11
|
+
|
12
|
+
=== Usage
|
13
|
+
|
14
|
+
The target for ActsAsKing is to be an easy to use, self explanitory gem.
|
15
|
+
|
16
|
+
Create a migration to add parent_id to your model:
|
17
|
+
rails g migration AddParentIdToComments
|
18
|
+
|
19
|
+
Add a column to your comments table
|
20
|
+
class AddParentIdToComments < ActiveRecord::Migration
|
21
|
+
def self.up
|
22
|
+
add_column :comments, :parent_id, :integer
|
23
|
+
add_index :comments, :parent_id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
In your model:
|
29
|
+
|
30
|
+
class Comment < ActiveRecord::Base
|
31
|
+
acts_as_king
|
32
|
+
end
|
33
|
+
|
34
|
+
Create a couple of comments
|
35
|
+
|
36
|
+
comment_1 = Comment.create # id: 1
|
37
|
+
comment_2 = Comment.create(:parent => comment_1) # id: 2
|
38
|
+
|
39
|
+
Get all top level comments
|
40
|
+
|
41
|
+
comments = Comment.kings
|
42
|
+
=> [#<Comment id: 1, parent_id: nil>]
|
43
|
+
|
44
|
+
Get the first top level comment and display the immediate children
|
45
|
+
|
46
|
+
comment = Comment.kings.first
|
47
|
+
comment.children
|
48
|
+
=> [#<Comment id: 2, parent_id: 1>]
|
49
|
+
|
50
|
+
=== Contributing
|
51
|
+
|
52
|
+
Contributing is easy. Fork the repository. Hack away. Create tests. Send a pull request.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'hanna/rdoctask'
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
Rake::TestTask.new('test') do |t|
|
8
|
+
t.libs << 'lib'
|
9
|
+
t.pattern = 'test/**/*_test.rb'
|
10
|
+
t.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
Rake::RDocTask.new(:rdoc) do |rd|
|
14
|
+
rd.main = "README.rdoc"
|
15
|
+
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
16
|
+
rd.options << "--all"
|
17
|
+
end
|
18
|
+
|
19
|
+
task :default => :test
|
20
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "acts_as_king/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "acts_as_king"
|
7
|
+
s.version = ActsAsKing::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Drew Tempelmeyer"]
|
10
|
+
s.email = ["drewtemp@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/drewtempelmeyer/acts_as_king"
|
12
|
+
s.summary = %q{Hierarchical ActiveRecord models. Inspired by acts_as_tree. Trees are shady.}
|
13
|
+
s.description = %q{Hierarchical ActiveRecord models. Inspired by acts_as_tree. Trees are shady.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency 'rails', ['>= 3.0.0']
|
20
|
+
s.add_development_dependency 'shoulda'
|
21
|
+
s.add_development_dependency 'sqlite3-ruby'
|
22
|
+
s.add_development_dependency 'hanna'
|
23
|
+
|
24
|
+
end
|
data/lib/acts_as_king.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'acts_as_king/railtie' if defined?(Rails)
|
2
|
+
|
3
|
+
# Written by Drew Tempelmeyer
|
4
|
+
module ActsAsKing
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
# Defines that the model should have a self referencing hierarchy. This allows you to have threaded comments or any other type
|
12
|
+
# of self referencing hierarchy. <tt>ActsAsKing</tt> creates a belongs_to
|
13
|
+
# association (parent) and has_many association (children). It also defines
|
14
|
+
# a <tt>kings</tt> scope for your model to return all top level records.
|
15
|
+
#
|
16
|
+
# === Example
|
17
|
+
#
|
18
|
+
# class Comment < ActiveRecord::Base
|
19
|
+
# acts_as_king
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# comment_1 = Comment.create
|
23
|
+
# comment_2 = Comment.create(:parent => comment_1) # defines parent
|
24
|
+
#
|
25
|
+
# # return an array of all top level records
|
26
|
+
# Comment.kings # => [#<Comment id: 1>]
|
27
|
+
#
|
28
|
+
# # return an array of children belonging to comment_1
|
29
|
+
# comment_1.children # => [#<Comment id: 2>]
|
30
|
+
#
|
31
|
+
# # get the parent record for comment_2
|
32
|
+
# comment_2.parent # => #<Comment id: 1>
|
33
|
+
#
|
34
|
+
#
|
35
|
+
def acts_as_king(options = {})
|
36
|
+
options = { :foreign_key => 'parent_id' }.merge(options)
|
37
|
+
|
38
|
+
belongs_to :parent, :class_name => name, :foreign_key => options[:foreign_key]
|
39
|
+
has_many :children, :class_name => name, :foreign_key => options[:foreign_key], :dependent => :destroy
|
40
|
+
|
41
|
+
class_eval <<-EOL
|
42
|
+
include ActsAsKing::InstanceMethods
|
43
|
+
|
44
|
+
scope :kings, where("#{options[:foreign_key]} IS NULL")
|
45
|
+
EOL
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
module InstanceMethods
|
52
|
+
|
53
|
+
# Retrieves all of the parents of the instance. (Think of it including
|
54
|
+
# grandparents as well.)
|
55
|
+
#
|
56
|
+
# ==== Example
|
57
|
+
#
|
58
|
+
# If you had three records in a structure similar to this:
|
59
|
+
# #<Comment id: 1, parent_id: nil>
|
60
|
+
# #<Comment id: 2, parent_id: 1>
|
61
|
+
# #<Comment id: 3, parent_id: 2>
|
62
|
+
#
|
63
|
+
# You would do the following to return all ancestors
|
64
|
+
# comment_3.ancestors # => [#<Comment id: 2, parent_id: 1>, #<Comment id: 1, parent_id: nil>]
|
65
|
+
#
|
66
|
+
def ancestors
|
67
|
+
current, all = self, []
|
68
|
+
all << current = current.parent while current.parent
|
69
|
+
all
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require './test/helper'
|
2
|
+
|
3
|
+
class ActsAsKingTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "ActsAsKing" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
setup_db
|
9
|
+
@post = Post.create
|
10
|
+
@comment = Comment.create(:post => @post)
|
11
|
+
@sub_comment = Comment.create(:post => @post, :parent => @comment)
|
12
|
+
@level_3 = Comment.create(:post => @post, :parent => @sub_comment)
|
13
|
+
end
|
14
|
+
|
15
|
+
teardown do
|
16
|
+
destroy_db
|
17
|
+
end
|
18
|
+
|
19
|
+
should "be one post" do
|
20
|
+
assert_equal 1, Post.count
|
21
|
+
end
|
22
|
+
|
23
|
+
should "be three comments" do
|
24
|
+
assert_equal 3, Comment.count
|
25
|
+
end
|
26
|
+
|
27
|
+
should "be one king comment" do
|
28
|
+
assert_equal 1, Comment.kings.count
|
29
|
+
end
|
30
|
+
|
31
|
+
should "king comment should have one child" do
|
32
|
+
assert_equal 1, @comment.children.count
|
33
|
+
end
|
34
|
+
|
35
|
+
should "child comment should return array of parents" do
|
36
|
+
assert_equal [@comment], @sub_comment.ancestors
|
37
|
+
end
|
38
|
+
|
39
|
+
should "return multiple ancestors" do
|
40
|
+
assert_equal [@sub_comment, @comment], @level_3.ancestors
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
require 'acts_as_king'
|
5
|
+
require 'test/unit'
|
6
|
+
require 'shoulda'
|
7
|
+
|
8
|
+
ActiveRecord::Base.send(:include, ActsAsKing)
|
9
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
10
|
+
ActiveRecord::Migration.verbose = false
|
11
|
+
|
12
|
+
def setup_db
|
13
|
+
ActiveRecord::Schema.define(:version => 1) do
|
14
|
+
create_table :posts, :force => true do |t|
|
15
|
+
end
|
16
|
+
|
17
|
+
create_table :comments, :force => true do |t|
|
18
|
+
t.integer :post_id, :null => false
|
19
|
+
t.integer :parent_id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy_db
|
25
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
26
|
+
ActiveRecord::Base.connection.drop_table(table)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Post < ActiveRecord::Base
|
31
|
+
has_many :comments, :dependent => :destroy
|
32
|
+
end
|
33
|
+
|
34
|
+
class Comment < ActiveRecord::Base
|
35
|
+
belongs_to :post
|
36
|
+
acts_as_king
|
37
|
+
end
|
38
|
+
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: acts_as_king
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Drew Tempelmeyer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-14 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rails
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.0.0
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: shoulda
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: sqlite3-ruby
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: hanna
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id004
|
59
|
+
description: Hierarchical ActiveRecord models. Inspired by acts_as_tree. Trees are shady.
|
60
|
+
email:
|
61
|
+
- drewtemp@gmail.com
|
62
|
+
executables: []
|
63
|
+
|
64
|
+
extensions: []
|
65
|
+
|
66
|
+
extra_rdoc_files: []
|
67
|
+
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- README.rdoc
|
72
|
+
- Rakefile
|
73
|
+
- acts_as_king.gemspec
|
74
|
+
- lib/acts_as_king.rb
|
75
|
+
- lib/acts_as_king/railtie.rb
|
76
|
+
- lib/acts_as_king/version.rb
|
77
|
+
- test/acts_as_king_test.rb
|
78
|
+
- test/helper.rb
|
79
|
+
homepage: http://github.com/drewtempelmeyer/acts_as_king
|
80
|
+
licenses: []
|
81
|
+
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: "0"
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: "0"
|
99
|
+
requirements: []
|
100
|
+
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 1.8.2
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: Hierarchical ActiveRecord models. Inspired by acts_as_tree. Trees are shady.
|
106
|
+
test_files:
|
107
|
+
- test/acts_as_king_test.rb
|
108
|
+
- test/helper.rb
|