categoryz3 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/MIT-LICENSE +20 -0
- data/README.rdoc +112 -0
- data/Rakefile +27 -0
- data/app/models/categoryz3/category.rb +30 -0
- data/app/models/categoryz3/child_item.rb +12 -0
- data/app/models/categoryz3/item.rb +31 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20121003060539_create_categoryz3_categories.rb +14 -0
- data/db/migrate/20121003060933_create_categoryz3_items.rb +12 -0
- data/db/migrate/20121003061056_create_categoryz3_child_items.rb +14 -0
- data/lib/categoryz3/categorizable.rb +79 -0
- data/lib/categoryz3/engine.rb +5 -0
- data/lib/categoryz3/validators/child_item_category_validator.rb +11 -0
- data/lib/categoryz3/version.rb +3 -0
- data/lib/categoryz3.rb +8 -0
- data/lib/generators/categoryz3/migrations/USAGE +8 -0
- data/lib/generators/categoryz3/migrations/migrations_generator.rb +22 -0
- data/lib/tasks/categoryz3_tasks.rake +4 -0
- metadata +150 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 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.rdoc
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
= Categoryz3
|
2
|
+
{<img src="https://secure.travis-ci.org/tscolari/categoryz3.png" />}[http://travis-ci.org/tscolari/categoryz3]
|
3
|
+
{<img src="https://gemnasium.com/tscolari/categoryz3.png" />}[https://gemnasium.com/tscolari/categoryz3]
|
4
|
+
{<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/tscolari/categoryz3]
|
5
|
+
|
6
|
+
Simple categorization to ActiveRecord models.
|
7
|
+
|
8
|
+
Works like a simple tagging system, but instead of tags it has categories, and categories may have an ilimited level of subcategories.
|
9
|
+
|
10
|
+
Using an auxiliary table, it's easy and fast to fetch items from any category, including all level of subcategories it may have.
|
11
|
+
|
12
|
+
== Motivation
|
13
|
+
|
14
|
+
genres_category = Categoryz3::Category.create(name: 'genres')
|
15
|
+
horror_category = Categoryz3::Category.create(name: 'horror', parent: genres_category)
|
16
|
+
cult_horror_category = Categoryz3::Category.create(name: 'horror', parent: horror_category)
|
17
|
+
action_category = Categoryz3::Category.create(name: 'horror', parent: genres_category)
|
18
|
+
|
19
|
+
horror_movie = Movie.find(1)
|
20
|
+
horror_movie.category = cult_horror_category
|
21
|
+
horror_movie.categories
|
22
|
+
#=> [cult_horror_category]
|
23
|
+
|
24
|
+
action_movie = Movie.find(2)
|
25
|
+
action_movie.category = action_category
|
26
|
+
|
27
|
+
Movie.inside_category(genres_category).all
|
28
|
+
#=> [horror_movie, action_movie]
|
29
|
+
Movie.inside_category(horror_category).all
|
30
|
+
#=> [horror_movie]
|
31
|
+
Movie.inside_category(cult_horror_category).all
|
32
|
+
#=> [horror_movie]
|
33
|
+
|
34
|
+
horror_category.path
|
35
|
+
#=> [movie_category, horror_category]
|
36
|
+
|
37
|
+
== Installation
|
38
|
+
|
39
|
+
Insert the gem in your Gemfile:
|
40
|
+
|
41
|
+
gem 'categoryz3'
|
42
|
+
|
43
|
+
Generate and run the migrations:
|
44
|
+
|
45
|
+
rails g categoryz3:migrations
|
46
|
+
rake db:migrate
|
47
|
+
|
48
|
+
Include the categorizable module in the models you want to categorize:
|
49
|
+
|
50
|
+
class Article < ActiveRecord::Base
|
51
|
+
include Categoryz3::Categorizable
|
52
|
+
end
|
53
|
+
|
54
|
+
== Usage
|
55
|
+
|
56
|
+
=== Listing categories from an object
|
57
|
+
|
58
|
+
You can use the method `categories` to list all categories from a model:
|
59
|
+
|
60
|
+
model.categories
|
61
|
+
#=> [category1, category2]
|
62
|
+
|
63
|
+
You can also use the `categories_list`, this will return the categories ids:
|
64
|
+
|
65
|
+
model.categories_list
|
66
|
+
#=> "1, 2"
|
67
|
+
|
68
|
+
=== Adding categories to an object
|
69
|
+
|
70
|
+
There are 2 ways for adding categories to an object:
|
71
|
+
|
72
|
+
model.category = category
|
73
|
+
model.category = [category1, category2, category3]
|
74
|
+
# alias_method :categories=, :category=
|
75
|
+
|
76
|
+
Replaces the object categories for the given ones.
|
77
|
+
|
78
|
+
model.categories_list = "1, 2, 3"
|
79
|
+
|
80
|
+
Replaces the object categories for the ones with ids 1, 2 and 3.
|
81
|
+
|
82
|
+
=== Removing categories from an object
|
83
|
+
|
84
|
+
To remove a category from the model, you can use the `remove_category` method:
|
85
|
+
|
86
|
+
model.remove_category category
|
87
|
+
model.remove_categories category1, category2
|
88
|
+
|
89
|
+
=== Category Path
|
90
|
+
|
91
|
+
Lists all the categories in the path, from the root one, to the category:
|
92
|
+
|
93
|
+
category.path
|
94
|
+
#=> [root_category, some_subcategory, another_subcategory, category]
|
95
|
+
|
96
|
+
=== Categorizable Scopes
|
97
|
+
|
98
|
+
==== inside_category
|
99
|
+
|
100
|
+
Lists all objects that belongs to the category or any subcategory of it
|
101
|
+
|
102
|
+
Article.inside_category(category)
|
103
|
+
|
104
|
+
==== having_category
|
105
|
+
|
106
|
+
Lists all objects that belongs to the category. (No subcategory objects).
|
107
|
+
|
108
|
+
Article.having_category(category)
|
109
|
+
|
110
|
+
= License
|
111
|
+
|
112
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Categoryz3'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Categoryz3
|
2
|
+
class Category < ActiveRecord::Base
|
3
|
+
belongs_to :parent , class_name: 'Categoryz3::Category' , inverse_of: :children
|
4
|
+
has_many :children , class_name: 'Categoryz3::Category' , foreign_key: :parent_id , inverse_of: :parent , dependent: :destroy
|
5
|
+
has_many :direct_items , class_name: 'Categoryz3::Item' , inverse_of: :category , dependent: :destroy
|
6
|
+
has_many :child_items , class_name: 'Categoryz3::ChildItem' , inverse_of: :category , dependent: :destroy
|
7
|
+
validates :name , presence: true
|
8
|
+
|
9
|
+
scope :parent_categories, -> { where(parent_id: nil) }
|
10
|
+
attr_accessible :name, :parent
|
11
|
+
|
12
|
+
# Public: Returns the full categories path from the root category until this category
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# subcategory3.path
|
17
|
+
# #=> [category, subcategory1, subcategory2, subcategory3]
|
18
|
+
#
|
19
|
+
def path
|
20
|
+
return @path_array if @path_array
|
21
|
+
parent_category = self
|
22
|
+
@path_array = [parent_category]
|
23
|
+
while (parent_category = parent_category.parent) != nil do
|
24
|
+
@path_array.insert(0, parent_category)
|
25
|
+
end
|
26
|
+
@path_array
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Categoryz3
|
2
|
+
class ChildItem < ActiveRecord::Base
|
3
|
+
belongs_to :category, inverse_of: :child_items
|
4
|
+
belongs_to :master_item, class_name: 'Categoryz3::Item', inverse_of: :child_items
|
5
|
+
belongs_to :categorizable, polymorphic: true
|
6
|
+
|
7
|
+
validates :category, :master_item, :categorizable, presence: true
|
8
|
+
validates :category_id, uniqueness: { scope: [:categorizable_type, :categorizable_id] }
|
9
|
+
validates_with Categoryz3::Validators::ChildItemCategoryValidator
|
10
|
+
attr_accessible :master_item, :categorizable
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Categoryz3
|
2
|
+
class Item < ActiveRecord::Base
|
3
|
+
belongs_to :category, inverse_of: :direct_items
|
4
|
+
belongs_to :categorizable, polymorphic: true
|
5
|
+
has_many :child_items, foreign_key: 'master_item_id', inverse_of: :master_item, dependent: :destroy
|
6
|
+
|
7
|
+
validates :category, :categorizable, presence: true
|
8
|
+
validates :category_id, uniqueness: { scope: [:categorizable_type, :categorizable_id] }
|
9
|
+
|
10
|
+
after_create :create_child_items
|
11
|
+
attr_accessible :categorizable
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# Private: Creates a child item for the category
|
16
|
+
#
|
17
|
+
def create_child_item_for_category(category)
|
18
|
+
category.child_items.create(categorizable: self.categorizable, master_item: self)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Private: Create a child_item for each subcategory the category from this item have
|
22
|
+
# Also creates a child_item for this category
|
23
|
+
#
|
24
|
+
def create_child_items
|
25
|
+
category.path.each do |category|
|
26
|
+
create_child_item_for_category category
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateCategoryz3Categories < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :categoryz3_categories do |t|
|
4
|
+
t.string :name
|
5
|
+
t.references :parent
|
6
|
+
t.integer :items_count , default: 0
|
7
|
+
t.integer :child_items_count , default: 0
|
8
|
+
t.integer :childrens_count , default: 0
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
add_index :categoryz3_categories, :parent_id
|
12
|
+
add_index :categoryz3_categories, :name
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateCategoryz3Items < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :categoryz3_items do |t|
|
4
|
+
t.references :category, null: false
|
5
|
+
t.references :categorizable, polymorphic: true, null: false
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
add_index :categoryz3_items, [:category_id, :categorizable_type, :categorizable_id], unique: true, name: 'items_unq_idx'
|
9
|
+
add_index :categoryz3_items, [:category_id, :created_at]
|
10
|
+
add_index :categoryz3_items, [:categorizable_type, :categorizable_id], name: 'items_categorizable_idx'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateCategoryz3ChildItems < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :categoryz3_child_items do |t|
|
4
|
+
t.references :category, null: false
|
5
|
+
t.references :categorizable, polymorphic: true, null: false
|
6
|
+
t.references :master_item, null: false
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
add_index :categoryz3_child_items, [:category_id, :created_at]
|
10
|
+
add_index :categoryz3_child_items, [:category_id, :categorizable_type, :categorizable_id], unique: true, name: 'child_items_unq_idx'
|
11
|
+
add_index :categoryz3_child_items, [:categorizable_type, :categorizable_id], name: 'child_items_categorizable_idx'
|
12
|
+
add_index :categoryz3_child_items, [:master_item_id]
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Categoryz3
|
2
|
+
# Adds the categorizable behavior to models
|
3
|
+
#
|
4
|
+
# This will give the model 2 scopes:
|
5
|
+
#
|
6
|
+
# * inside_category(category) : Filter objects that belongs to the category or any of it's subcategories
|
7
|
+
# * having_category(category) : Filter objects that belongs only to the category
|
8
|
+
#
|
9
|
+
# And 2 new relations:
|
10
|
+
#
|
11
|
+
# * direct_category_items : This maps the model to the categories it is directly linked
|
12
|
+
# * child_category_items : This is an auxiliary relation to fast map the objet to any subcategory
|
13
|
+
#
|
14
|
+
module Categorizable
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
included do
|
17
|
+
has_many :direct_category_items , class_name: 'Categoryz3::Item' , as: :categorizable
|
18
|
+
has_many :child_category_items , class_name: 'Categoryz3::ChildItem' , as: :categorizable
|
19
|
+
scope :inside_category , ->(category) { joins(:child_category_items).where('categoryz3_child_items.category_id = ?' , category.id) }
|
20
|
+
scope :having_category , ->(category) { joins(:direct_category_items).where('categoryz3_items.category_id = ?' , category.id) }
|
21
|
+
end
|
22
|
+
|
23
|
+
# Public: List all object categories
|
24
|
+
# Categories are retrieved from direct_category_items association, no subcategories included
|
25
|
+
#
|
26
|
+
def categories
|
27
|
+
return @categories if @categories
|
28
|
+
category_ids = direct_category_items.all.map { |category| category.id }
|
29
|
+
@categories = Categoryz3::Category.where(id: category_ids)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Public: Adds a category, or categories, to the model
|
33
|
+
#
|
34
|
+
# Examples:
|
35
|
+
#
|
36
|
+
# categorizable_object.category = dummy_category
|
37
|
+
# categorizable_object.categories = [dummy_category1, dummy_category2]
|
38
|
+
#
|
39
|
+
def category=(categories)
|
40
|
+
self.direct_category_items.destroy_all
|
41
|
+
[categories].flatten.each do |category|
|
42
|
+
category.direct_items.create(categorizable: self) if category
|
43
|
+
end
|
44
|
+
@categories = nil
|
45
|
+
end
|
46
|
+
alias_method :categories=, :category=
|
47
|
+
|
48
|
+
# Public: Removes a category, or categories, from the model
|
49
|
+
#
|
50
|
+
# Examples:
|
51
|
+
#
|
52
|
+
# categorizable_object.remove_category dummy_category
|
53
|
+
# categorizable_object.remove_categories dummy_category1, dummy_category2
|
54
|
+
#
|
55
|
+
def remove_category(*categories)
|
56
|
+
categories.each do |category|
|
57
|
+
direct_category_items.where(category_id: category).destroy_all
|
58
|
+
end
|
59
|
+
@categories = nil
|
60
|
+
end
|
61
|
+
alias_method :remove_categories, :remove_category
|
62
|
+
|
63
|
+
# Public: Returns the id list of the categories linked to the model
|
64
|
+
#
|
65
|
+
def categories_list
|
66
|
+
categories.map(&:id).join(", ")
|
67
|
+
end
|
68
|
+
|
69
|
+
# Public: Accepts an array of category ids as parameter and adds all
|
70
|
+
# of them to the model
|
71
|
+
#
|
72
|
+
def categories_list=(ids)
|
73
|
+
self.categories = ids.split(",").map do |id|
|
74
|
+
Category.where(id: id).first
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Categoryz3
|
2
|
+
module Validators
|
3
|
+
class ChildItemCategoryValidator < ActiveModel::Validator
|
4
|
+
def validate(record)
|
5
|
+
unless record.master_item.category.path.map{ |category| category.id }.include?(record.category_id)
|
6
|
+
record.errors[:category] << "Must match with master_item.category"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/categoryz3.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
class Categoryz3::MigrationsGenerator < Rails::Generators::Base
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
source_root File.expand_path('../../../../../db/migrate', __FILE__)
|
7
|
+
|
8
|
+
def copy_migrations
|
9
|
+
migration_template "20121003060539_create_categoryz3_categories.rb", "db/migrate/create_categoryz3_categories.rb"
|
10
|
+
migration_template "20121003060933_create_categoryz3_items.rb", "db/migrate/create_categoryz3_items.rb"
|
11
|
+
migration_template "20121003061056_create_categoryz3_child_items.rb", "db/migrate/create_categoryz3_child_items.rb"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.next_migration_number( dirname )
|
15
|
+
next_migration_number = current_migration_number(dirname) + 1
|
16
|
+
if ActiveRecord::Base.timestamped_migrations
|
17
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S%6N"), "%.20d" % next_migration_number].max
|
18
|
+
else
|
19
|
+
"%.3d" % next_migration_number
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: categoryz3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: '0.1'
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tiago Scolari
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 3.2.8
|
21
|
+
none: false
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.8
|
27
|
+
none: false
|
28
|
+
prerelease: false
|
29
|
+
type: :runtime
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec-rails
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ! '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
none: false
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
none: false
|
44
|
+
prerelease: false
|
45
|
+
type: :development
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: database_cleaner
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
none: false
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
none: false
|
60
|
+
prerelease: false
|
61
|
+
type: :development
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: factory_girl_rails
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
none: false
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
none: false
|
76
|
+
prerelease: false
|
77
|
+
type: :development
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: ffaker
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
none: false
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
none: false
|
92
|
+
prerelease: false
|
93
|
+
type: :development
|
94
|
+
description: Works like a simple tagging system, but instead of tags it has categories, and categories may have an ilimited level of subcategories.
|
95
|
+
email:
|
96
|
+
- tscolari@gmail.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- app/models/categoryz3/category.rb
|
102
|
+
- app/models/categoryz3/child_item.rb
|
103
|
+
- app/models/categoryz3/item.rb
|
104
|
+
- config/routes.rb
|
105
|
+
- db/migrate/20121003060539_create_categoryz3_categories.rb
|
106
|
+
- db/migrate/20121003060933_create_categoryz3_items.rb
|
107
|
+
- db/migrate/20121003061056_create_categoryz3_child_items.rb
|
108
|
+
- lib/categoryz3.rb
|
109
|
+
- lib/categoryz3/categorizable.rb
|
110
|
+
- lib/categoryz3/engine.rb
|
111
|
+
- lib/categoryz3/version.rb
|
112
|
+
- lib/categoryz3/validators/child_item_category_validator.rb
|
113
|
+
- lib/generators/categoryz3/migrations/migrations_generator.rb
|
114
|
+
- lib/generators/categoryz3/migrations/USAGE
|
115
|
+
- lib/tasks/categoryz3_tasks.rake
|
116
|
+
- MIT-LICENSE
|
117
|
+
- Rakefile
|
118
|
+
- README.rdoc
|
119
|
+
homepage: https://github.com/tscolari/categoryz3
|
120
|
+
licenses: []
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
hash: 2
|
132
|
+
version: '0'
|
133
|
+
none: false
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ! '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
hash: 2
|
141
|
+
version: '0'
|
142
|
+
none: false
|
143
|
+
requirements: []
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 1.8.24
|
146
|
+
signing_key:
|
147
|
+
specification_version: 3
|
148
|
+
summary: Simple categorization to ActiveRecord models.
|
149
|
+
test_files: []
|
150
|
+
...
|