taxis 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/Gemfile +5 -0
- data/LICENSE +20 -0
- data/README.md +42 -0
- data/Rakefile +2 -0
- data/app/controllers/admin/base_controller.rb +25 -0
- data/app/controllers/admin/taxonomies_controller.rb +58 -0
- data/app/controllers/admin/taxons_controller.rb +94 -0
- data/app/controllers/application_controller.rb +3 -0
- data/app/models/taxon.rb +62 -0
- data/app/models/taxonomy.rb +24 -0
- data/app/views/admin/taxonomies/_form.html.erb +4 -0
- data/app/views/admin/taxonomies/_js_head.html.erb +9 -0
- data/app/views/admin/taxonomies/_list.html.erb +20 -0
- data/app/views/admin/taxonomies/edit.erb +29 -0
- data/app/views/admin/taxonomies/index.html.erb +7 -0
- data/app/views/admin/taxonomies/new.html.erb +11 -0
- data/app/views/admin/taxons/_form.html.erb +5 -0
- data/app/views/admin/taxons/_taxon_table.html.erb +23 -0
- data/app/views/admin/taxons/edit.html.erb +10 -0
- data/app/views/layouts/admin.html.erb +30 -0
- data/config/routes.rb +16 -0
- data/lib/generators/taxis/install_generator.rb +67 -0
- data/lib/generators/taxis/migration_generator.rb +28 -0
- data/lib/generators/taxis/public/jsTree/jquery.jstree.js +3510 -0
- data/lib/generators/taxis/public/jsTree/themes/apple/bg.jpg +0 -0
- data/lib/generators/taxis/public/jsTree/themes/apple/d.png +0 -0
- data/lib/generators/taxis/public/jsTree/themes/apple/dot_for_ie.gif +0 -0
- data/lib/generators/taxis/public/jsTree/themes/apple/style.css +60 -0
- data/lib/generators/taxis/public/jsTree/themes/apple/throbber.gif +0 -0
- data/lib/generators/taxis/public/taxonomy.js +203 -0
- data/lib/generators/taxis/templates/create_taxonomies.rb +13 -0
- data/lib/generators/taxis/templates/create_taxons.rb +18 -0
- data/lib/taxis.rb +3 -0
- data/lib/taxis/engine.rb +10 -0
- data/lib/taxis/version.rb +3 -0
- data/taxis.gemspec +25 -0
- metadata +114 -0
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,60 @@
|
|
1
|
+
/*
|
2
|
+
* jsTree apple theme 1.0
|
3
|
+
* Supported features: dots/no-dots, icons/no-icons, focused, loading
|
4
|
+
* Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search
|
5
|
+
*/
|
6
|
+
|
7
|
+
.jstree-apple > ul { background:url("bg.jpg") left top repeat; }
|
8
|
+
.jstree-apple li,
|
9
|
+
.jstree-apple ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; }
|
10
|
+
.jstree-apple li { background-position:-90px 0; background-repeat:repeat-y; }
|
11
|
+
.jstree-apple li.jstree-last { background:transparent; }
|
12
|
+
.jstree-apple .jstree-open > ins { background-position:-72px 0; }
|
13
|
+
.jstree-apple .jstree-closed > ins { background-position:-54px 0; }
|
14
|
+
.jstree-apple .jstree-leaf > ins { background-position:-36px 0; }
|
15
|
+
|
16
|
+
.jstree-apple a { border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; text-shadow:1px 1px 1px white; }
|
17
|
+
.jstree-apple .jstree-hovered { background:#e7f4f9; border:1px solid #d8f0fa; padding:0 3px 0 1px; text-shadow:1px 1px 1px silver; }
|
18
|
+
.jstree-apple .jstree-clicked { background:#beebff; border:1px solid #99defd; padding:0 3px 0 1px; }
|
19
|
+
.jstree-apple a .jstree-icon { background-position:-56px -20px; }
|
20
|
+
.jstree-apple a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; }
|
21
|
+
|
22
|
+
.jstree-apple.jstree-focused { background:white; }
|
23
|
+
|
24
|
+
.jstree-apple .jstree-no-dots li,
|
25
|
+
.jstree-apple .jstree-no-dots .jstree-leaf > ins { background:transparent; }
|
26
|
+
.jstree-apple .jstree-no-dots .jstree-open > ins { background-position:-18px 0; }
|
27
|
+
.jstree-apple .jstree-no-dots .jstree-closed > ins { background-position:0 0; }
|
28
|
+
|
29
|
+
.jstree-apple .jstree-no-icons a .jstree-icon { display:none; }
|
30
|
+
|
31
|
+
.jstree-apple .jstree-search { font-style:italic; }
|
32
|
+
|
33
|
+
.jstree-apple .jstree-no-icons .jstree-checkbox { display:inline-block; }
|
34
|
+
.jstree-apple .jstree-no-checkboxes .jstree-checkbox { display:none !important; }
|
35
|
+
.jstree-apple .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; }
|
36
|
+
.jstree-apple .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; }
|
37
|
+
.jstree-apple .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; }
|
38
|
+
.jstree-apple .jstree-checked > a > .checkbox:hover { background-position:-38px -37px; }
|
39
|
+
.jstree-apple .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; }
|
40
|
+
.jstree-apple .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; }
|
41
|
+
|
42
|
+
#vakata-dragged.jstree-apple ins { background:transparent !important; }
|
43
|
+
#vakata-dragged.jstree-apple .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; }
|
44
|
+
#vakata-dragged.jstree-apple .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; }
|
45
|
+
#jstree-marker.jstree-apple { background:url("d.png") -41px -57px no-repeat !important; }
|
46
|
+
|
47
|
+
.jstree-apple a.jstree-search { color:aqua; }
|
48
|
+
|
49
|
+
#vakata-contextmenu.jstree-apple-context,
|
50
|
+
#vakata-contextmenu.jstree-apple-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; }
|
51
|
+
#vakata-contextmenu.jstree-apple-context li { }
|
52
|
+
#vakata-contextmenu.jstree-apple-context a { color:black; }
|
53
|
+
#vakata-contextmenu.jstree-apple-context a:hover,
|
54
|
+
#vakata-contextmenu.jstree-apple-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; }
|
55
|
+
#vakata-contextmenu.jstree-apple-context li.jstree-contextmenu-disabled a,
|
56
|
+
#vakata-contextmenu.jstree-apple-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; }
|
57
|
+
#vakata-contextmenu.jstree-apple-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; }
|
58
|
+
#vakata-contextmenu.jstree-apple-context li ul { margin-left:-4px; }
|
59
|
+
|
60
|
+
/* TODO: IE6 support - the `>` selectors */
|
Binary file
|
@@ -0,0 +1,203 @@
|
|
1
|
+
var base_url = "/admin/taxonomies/" + taxonomy_id + "/taxons/";
|
2
|
+
var is_cut = false;
|
3
|
+
var last_rollback = null;
|
4
|
+
|
5
|
+
var handle_ajax_error = function(XMLHttpRequest, textStatus, errorThrown){
|
6
|
+
jQuery.jstree.rollback(last_rollback);
|
7
|
+
jQuery("#ajax_error").show().html("<strong>" + server_error + "</strong><br/>" + taxonomy_tree_error);
|
8
|
+
};
|
9
|
+
|
10
|
+
var handle_move = function(e, data) {
|
11
|
+
console.log("MOVING!");
|
12
|
+
console.log(data);
|
13
|
+
last_rollback = data.rlbk;
|
14
|
+
var position = data.rslt.cp;
|
15
|
+
var node = data.rslt.o;
|
16
|
+
var new_parent = data.rslt.np;
|
17
|
+
|
18
|
+
console.log("new parent");
|
19
|
+
console.log(new_parent.attr("id"));
|
20
|
+
|
21
|
+
console.log("r");
|
22
|
+
console.log(data.rslt.r.attr("id"));
|
23
|
+
var left_of_id = data.rslt.r.attr("id");
|
24
|
+
|
25
|
+
jQuery.ajax({
|
26
|
+
type: "POST",
|
27
|
+
url: base_url + node.attr("id") + ".json",
|
28
|
+
data: ({_method: "put", "taxon[parent_id]": new_parent.attr("id"), "left_of_id": left_of_id, authenticity_token: AUTH_TOKEN}),
|
29
|
+
error: handle_ajax_error
|
30
|
+
});
|
31
|
+
|
32
|
+
return true
|
33
|
+
};
|
34
|
+
|
35
|
+
var handle_create = function(e, data) {
|
36
|
+
last_rollback = data.rlbk;
|
37
|
+
var node = data.rslt.obj;
|
38
|
+
var name = data.rslt.name;
|
39
|
+
var new_parent = data.rslt.parent;
|
40
|
+
|
41
|
+
jQuery.ajax({
|
42
|
+
type: "POST",
|
43
|
+
url: base_url,
|
44
|
+
data: ({"taxon[name]": name, "taxon[parent_id]": new_parent.attr("id"), authenticity_token: AUTH_TOKEN}),
|
45
|
+
error: handle_ajax_error,
|
46
|
+
success: function(id,result) {
|
47
|
+
node.attr('id', id);
|
48
|
+
}
|
49
|
+
});
|
50
|
+
|
51
|
+
};
|
52
|
+
|
53
|
+
var handle_rename = function(e, data) {
|
54
|
+
last_rollback = data.rlbk;
|
55
|
+
var node = data.rslt.obj;
|
56
|
+
var name = data.rslt.new_name;
|
57
|
+
|
58
|
+
jQuery.ajax({
|
59
|
+
type: "POST",
|
60
|
+
url: base_url + node.attr("id") + ".json",
|
61
|
+
data: ({_method: "put", "taxon[name]": name, authenticity_token: AUTH_TOKEN}),
|
62
|
+
error: handle_ajax_error
|
63
|
+
});
|
64
|
+
};
|
65
|
+
|
66
|
+
var handle_delete = function(e, data){
|
67
|
+
last_rollback = data.rlbk;
|
68
|
+
var node = data.rslt.obj;
|
69
|
+
|
70
|
+
jConfirm('Are you sure you want to delete this taxon?', 'Confirm Taxon Deletion', function(r) {
|
71
|
+
if(r){
|
72
|
+
jQuery.ajax({
|
73
|
+
type: "POST",
|
74
|
+
url: base_url + node.attr("id"),
|
75
|
+
data: ({_method: "delete", authenticity_token: AUTH_TOKEN}),
|
76
|
+
error: handle_ajax_error
|
77
|
+
});
|
78
|
+
}else{
|
79
|
+
jQuery.jstree.rollback(last_rollback);
|
80
|
+
last_rollback = null;
|
81
|
+
}
|
82
|
+
});
|
83
|
+
|
84
|
+
};
|
85
|
+
|
86
|
+
jQuery(document).ready(function(){
|
87
|
+
var conf = {
|
88
|
+
json_data : {
|
89
|
+
"data" : initial,
|
90
|
+
"ajax" : {
|
91
|
+
"url" : function(n) {
|
92
|
+
return "/admin/taxons/" + ( n.attr ? n.attr("id") : 0 ) + "/children.json";
|
93
|
+
},
|
94
|
+
"data" : ""
|
95
|
+
}
|
96
|
+
},
|
97
|
+
"themes" : {
|
98
|
+
"theme" : "apple",
|
99
|
+
"url" : "/javascripts/jsTree/themes/apple/style.css"
|
100
|
+
},
|
101
|
+
"strings" : {
|
102
|
+
"new_node" : new_taxon,
|
103
|
+
"loading" : loading + "..."
|
104
|
+
},
|
105
|
+
"crrm" : {
|
106
|
+
"move" : {
|
107
|
+
"check_move" : function (m) {
|
108
|
+
var position = m.cp;
|
109
|
+
var node = m.o;
|
110
|
+
var new_parent = m.np;
|
111
|
+
|
112
|
+
if(!new_parent) return false; //no parent
|
113
|
+
|
114
|
+
if(node.attr("rel")=="root") return false; //can't drag root
|
115
|
+
|
116
|
+
if(new_parent.attr("id")=="taxonomy_tree" && position==0) return false; // can't drop before root
|
117
|
+
|
118
|
+
return true;
|
119
|
+
|
120
|
+
}
|
121
|
+
}
|
122
|
+
},
|
123
|
+
"contextmenu" : {
|
124
|
+
"items" : function(obj) {
|
125
|
+
var id_of_node = obj.attr("id");
|
126
|
+
var type_of_node = obj.attr("rel");
|
127
|
+
var menu = {};
|
128
|
+
if(type_of_node == "root") {
|
129
|
+
menu = {
|
130
|
+
"create" : {
|
131
|
+
"label" : "Create",
|
132
|
+
"action" : function (obj) { this.create(obj); }
|
133
|
+
},
|
134
|
+
"paste" : {
|
135
|
+
"separator_before" : true,
|
136
|
+
"label" : "Paste",
|
137
|
+
"action" : function (obj) { is_cut = false; this.paste(obj); },
|
138
|
+
"_disabled" : is_cut == false
|
139
|
+
},
|
140
|
+
"edit" : {
|
141
|
+
"separator_before" : true,
|
142
|
+
"label" : "Edit",
|
143
|
+
"action" : function (obj) { window.location = base_url + obj.attr("id") + "/edit/"; }
|
144
|
+
}
|
145
|
+
}
|
146
|
+
} else {
|
147
|
+
menu = {
|
148
|
+
"create" : {
|
149
|
+
"label" : "Create",
|
150
|
+
"action" : function (obj) { this.create(obj); }
|
151
|
+
},
|
152
|
+
"rename" : {
|
153
|
+
"label" : "Rename",
|
154
|
+
"action" : function (obj) { this.rename(obj); }
|
155
|
+
},
|
156
|
+
"remove" : {
|
157
|
+
"label" : "Remove",
|
158
|
+
"action" : function (obj) { this.remove(obj); }
|
159
|
+
},
|
160
|
+
"cut" : {
|
161
|
+
"separator_before" : true,
|
162
|
+
"label" : "Cut",
|
163
|
+
"action" : function (obj) { is_cut = true; this.cut(obj); }
|
164
|
+
},
|
165
|
+
"paste" : {
|
166
|
+
"label" : "Paste",
|
167
|
+
"action" : function (obj) { is_cut = false; this.paste(obj); },
|
168
|
+
"_disabled" : is_cut == false
|
169
|
+
},
|
170
|
+
"edit" : {
|
171
|
+
"separator_before" : true,
|
172
|
+
"label" : "Edit",
|
173
|
+
"action" : function (obj) { window.location = "/admin/taxons/" + obj.attr("id") + "/edit/"; }
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
return menu;
|
178
|
+
}
|
179
|
+
},
|
180
|
+
|
181
|
+
"plugins" : [ "themes", "json_data", "dnd", "crrm", "contextmenu"]
|
182
|
+
}
|
183
|
+
|
184
|
+
jQuery("#taxonomy_tree").jstree(conf)
|
185
|
+
.bind("move_node.jstree", handle_move)
|
186
|
+
.bind("remove.jstree", handle_delete)
|
187
|
+
.bind("create.jstree", handle_create)
|
188
|
+
.bind("rename.jstree", handle_rename);
|
189
|
+
|
190
|
+
jQuery("#taxonomy_tree").delegate("a", "dblclick", function (e) {
|
191
|
+
jQuery("#taxonomy_tree").jstree("rename", this)
|
192
|
+
});
|
193
|
+
|
194
|
+
|
195
|
+
jQuery(document).keypress(function(e){
|
196
|
+
//surpress form submit on enter/return
|
197
|
+
if (e.keyCode == 13){
|
198
|
+
e.preventDefault();
|
199
|
+
}
|
200
|
+
});
|
201
|
+
});
|
202
|
+
|
203
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateTaxons < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :taxons do |t|
|
4
|
+
t.string :name
|
5
|
+
t.text :path
|
6
|
+
t.string :url
|
7
|
+
t.integer :taxonomy_id
|
8
|
+
# for acts as set
|
9
|
+
t.integer :parent_id, :lft, :rgt, :root_id
|
10
|
+
t.timestamps
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :taxons
|
17
|
+
end
|
18
|
+
end
|
data/lib/taxis.rb
ADDED
data/lib/taxis/engine.rb
ADDED
data/taxis.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "taxis/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "taxis"
|
7
|
+
s.version = Taxis::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Michael Farmer"]
|
10
|
+
s.email = ["mfarmer@endpoint.com"]
|
11
|
+
s.homepage = "http://github.com/mikefarmer/taxis"
|
12
|
+
s.summary = %q{Rails engine that adds a simple taxonomy structure to your application}
|
13
|
+
s.description = %q{Rails engine that adds a simple taxonomy structure to your application}
|
14
|
+
|
15
|
+
s.rubyforge_project = "taxis"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency('nested_set', '~> 1.6.4')
|
23
|
+
s.add_dependency('stringex', '~> 1.2.1')
|
24
|
+
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: taxis
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Farmer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-04-13 00:00:00 -06:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: nested_set
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 1.6.4
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: stringex
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 1.2.1
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
description: Rails engine that adds a simple taxonomy structure to your application
|
39
|
+
email:
|
40
|
+
- mfarmer@endpoint.com
|
41
|
+
executables: []
|
42
|
+
|
43
|
+
extensions: []
|
44
|
+
|
45
|
+
extra_rdoc_files: []
|
46
|
+
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- app/controllers/admin/base_controller.rb
|
54
|
+
- app/controllers/admin/taxonomies_controller.rb
|
55
|
+
- app/controllers/admin/taxons_controller.rb
|
56
|
+
- app/controllers/application_controller.rb
|
57
|
+
- app/models/taxon.rb
|
58
|
+
- app/models/taxonomy.rb
|
59
|
+
- app/views/admin/taxonomies/_form.html.erb
|
60
|
+
- app/views/admin/taxonomies/_js_head.html.erb
|
61
|
+
- app/views/admin/taxonomies/_list.html.erb
|
62
|
+
- app/views/admin/taxonomies/edit.erb
|
63
|
+
- app/views/admin/taxonomies/index.html.erb
|
64
|
+
- app/views/admin/taxonomies/new.html.erb
|
65
|
+
- app/views/admin/taxons/_form.html.erb
|
66
|
+
- app/views/admin/taxons/_taxon_table.html.erb
|
67
|
+
- app/views/admin/taxons/edit.html.erb
|
68
|
+
- app/views/layouts/admin.html.erb
|
69
|
+
- config/routes.rb
|
70
|
+
- lib/generators/taxis/install_generator.rb
|
71
|
+
- lib/generators/taxis/migration_generator.rb
|
72
|
+
- lib/generators/taxis/public/jsTree/jquery.jstree.js
|
73
|
+
- lib/generators/taxis/public/jsTree/themes/apple/bg.jpg
|
74
|
+
- lib/generators/taxis/public/jsTree/themes/apple/d.png
|
75
|
+
- lib/generators/taxis/public/jsTree/themes/apple/dot_for_ie.gif
|
76
|
+
- lib/generators/taxis/public/jsTree/themes/apple/style.css
|
77
|
+
- lib/generators/taxis/public/jsTree/themes/apple/throbber.gif
|
78
|
+
- lib/generators/taxis/public/taxonomy.js
|
79
|
+
- lib/generators/taxis/templates/create_taxonomies.rb
|
80
|
+
- lib/generators/taxis/templates/create_taxons.rb
|
81
|
+
- lib/taxis.rb
|
82
|
+
- lib/taxis/engine.rb
|
83
|
+
- lib/taxis/version.rb
|
84
|
+
- taxis.gemspec
|
85
|
+
has_rdoc: true
|
86
|
+
homepage: http://github.com/mikefarmer/taxis
|
87
|
+
licenses: []
|
88
|
+
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: "0"
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project: taxis
|
109
|
+
rubygems_version: 1.6.2
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: Rails engine that adds a simple taxonomy structure to your application
|
113
|
+
test_files: []
|
114
|
+
|