taxis 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +5 -0
  3. data/LICENSE +20 -0
  4. data/README.md +42 -0
  5. data/Rakefile +2 -0
  6. data/app/controllers/admin/base_controller.rb +25 -0
  7. data/app/controllers/admin/taxonomies_controller.rb +58 -0
  8. data/app/controllers/admin/taxons_controller.rb +94 -0
  9. data/app/controllers/application_controller.rb +3 -0
  10. data/app/models/taxon.rb +62 -0
  11. data/app/models/taxonomy.rb +24 -0
  12. data/app/views/admin/taxonomies/_form.html.erb +4 -0
  13. data/app/views/admin/taxonomies/_js_head.html.erb +9 -0
  14. data/app/views/admin/taxonomies/_list.html.erb +20 -0
  15. data/app/views/admin/taxonomies/edit.erb +29 -0
  16. data/app/views/admin/taxonomies/index.html.erb +7 -0
  17. data/app/views/admin/taxonomies/new.html.erb +11 -0
  18. data/app/views/admin/taxons/_form.html.erb +5 -0
  19. data/app/views/admin/taxons/_taxon_table.html.erb +23 -0
  20. data/app/views/admin/taxons/edit.html.erb +10 -0
  21. data/app/views/layouts/admin.html.erb +30 -0
  22. data/config/routes.rb +16 -0
  23. data/lib/generators/taxis/install_generator.rb +67 -0
  24. data/lib/generators/taxis/migration_generator.rb +28 -0
  25. data/lib/generators/taxis/public/jsTree/jquery.jstree.js +3510 -0
  26. data/lib/generators/taxis/public/jsTree/themes/apple/bg.jpg +0 -0
  27. data/lib/generators/taxis/public/jsTree/themes/apple/d.png +0 -0
  28. data/lib/generators/taxis/public/jsTree/themes/apple/dot_for_ie.gif +0 -0
  29. data/lib/generators/taxis/public/jsTree/themes/apple/style.css +60 -0
  30. data/lib/generators/taxis/public/jsTree/themes/apple/throbber.gif +0 -0
  31. data/lib/generators/taxis/public/taxonomy.js +203 -0
  32. data/lib/generators/taxis/templates/create_taxonomies.rb +13 -0
  33. data/lib/generators/taxis/templates/create_taxons.rb +18 -0
  34. data/lib/taxis.rb +3 -0
  35. data/lib/taxis/engine.rb +10 -0
  36. data/lib/taxis/version.rb +3 -0
  37. data/taxis.gemspec +25 -0
  38. metadata +114 -0
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ */**/.DS_Store
3
+ *.gem
4
+ .rvmrc
5
+ .bundle
6
+ Gemfile.lock
7
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rails", "~> 3.0.4"
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (C) 2011 by End Point Corporation
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
20
+
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Taxis
2
+ Taxis is a simple Rails 3 plugin that will give you a taxonomy structure for your rails application. It was written with the intent of providing a category tree for e-commerce solutions. It is in early development right now so please feel free to submit issues and provide any feedback.
3
+
4
+ # Installation
5
+
6
+ gem install taxis
7
+
8
+ rails g taxis:install
9
+
10
+ # Dependencies
11
+ Taxis provides a very simple interface for administrating the taxonomy. This interface uses the jsTree javascript library, which is a plugin for jQuery. As such, the taxis:install generator installs the jquery-rails gem which removes the prototype framework from your application. If this is not desired, use the --skip-jquery option when you run the generator. The gem also depends on:
12
+
13
+ * stringex
14
+ * nested_set
15
+
16
+ # License
17
+
18
+ Copyright (C) 2011 by End Point Corporation
19
+
20
+ Permission is hereby granted, free of charge, to any person obtaining a copy
21
+ of this software and associated documentation files (the "Software"), to deal
22
+ in the Software without restriction, including without limitation the rights
23
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24
+ copies of the Software, and to permit persons to whom the Software is
25
+ furnished to do so, subject to the following conditions:
26
+
27
+ The above copyright notice and this permission notice shall be included in
28
+ all copies or substantial portions of the Software.
29
+
30
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36
+ THE SOFTWARE.
37
+
38
+
39
+ # Contributing
40
+ Fork, modify, send me a pull request
41
+
42
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,25 @@
1
+ class Admin::BaseController < ApplicationController
2
+ layout 'admin'
3
+
4
+ # For the gem
5
+ unloadable
6
+
7
+
8
+
9
+ protected
10
+
11
+
12
+ def tree_children(taxon)
13
+ children = []
14
+ taxon.children.each do |taxon|
15
+ children << {
16
+ :attr => {:id => taxon.id.to_s},
17
+ :data => taxon.name,
18
+ :state => taxon.children.empty? ? "" : "closed"
19
+ }
20
+ end
21
+
22
+ return children
23
+ end
24
+
25
+ end
@@ -0,0 +1,58 @@
1
+ class Admin::TaxonomiesController < Admin::BaseController
2
+
3
+
4
+ def index
5
+ @taxonomies = Taxonomy.all
6
+ end
7
+
8
+ def show
9
+ @taxonomy = Taxonomy.find(params[:id])
10
+ end
11
+
12
+ def new
13
+ @taxonomy = Taxonomy.new
14
+ end
15
+
16
+ def create
17
+ @taxonomy = Taxonomy.new(params[:taxonomy])
18
+ if @taxonomy.save
19
+ redirect_to edit_admin_taxonomy_url(@taxonomy), :notice => "Successfully created taxonomy."
20
+ else
21
+ render :action => 'new'
22
+ end
23
+ end
24
+
25
+ def edit
26
+ @taxonomy = Taxonomy.find(params[:id])
27
+ @tree = root_tree(@taxonomy)
28
+ end
29
+
30
+ def update
31
+ @taxonomy = Taxonomy.find(params[:id])
32
+ if @taxonomy.update_attributes(params[:taxonomy])
33
+ redirect_to admin_taxonomies_url, :notice => "Successfully updated taxonomy."
34
+ else
35
+ render :action => 'edit'
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ @taxonomy = Taxonomy.find(params[:id])
41
+ @taxonomy.destroy
42
+ redirect_to admin_taxonomies_url, :notice => "Successfully destroyed taxonomy."
43
+ end
44
+
45
+
46
+ private
47
+
48
+ def root_tree(taxonomy)
49
+ tree = {
50
+ :attr => {:id => taxonomy.root.id.to_s, :rel => "root"},
51
+ :data => taxonomy.root.name,
52
+ :state => "open",
53
+ :children => tree_children(taxonomy.root)
54
+ }
55
+ return tree
56
+ end
57
+
58
+ end
@@ -0,0 +1,94 @@
1
+ class Admin::TaxonsController < Admin::BaseController
2
+
3
+ before_filter :find_taxonomy, :except => [:children]
4
+
5
+ def index
6
+
7
+ if @taxonomy
8
+ @taxons = @taxonomy.children.order(:pos)
9
+ else
10
+ @taxons = Taxon.all
11
+ end
12
+
13
+ respond_to do |format|
14
+ format.html # index.html.erb
15
+ format.json { render :json => @taxons}
16
+ end
17
+
18
+
19
+ end
20
+
21
+ def show
22
+ @taxon = Taxon.find(params[:id])
23
+ end
24
+
25
+ def new
26
+ @taxon = Taxon.new
27
+ end
28
+
29
+ def create
30
+ @taxon = Taxon.new(params[:taxon])
31
+ if @taxon.save
32
+ redirect_to edit_admin_taxonomy_url(@taxon.taxonomy), :notice => "Successfully created taxon."
33
+ else
34
+ render :action => 'new'
35
+ end
36
+ end
37
+
38
+ def edit
39
+ @taxon = Taxon.find(params[:id])
40
+ @taxonomy = @taxon.taxonomy
41
+ end
42
+
43
+ def update
44
+ @taxon = Taxon.find(params[:id])
45
+ if @taxon.update_attributes(params[:taxon])
46
+
47
+ # Move the taxon to the correct position
48
+ if params[:left_of_id] != params[:parent_id]
49
+ @right_taxon = Taxon.find(params[:left_of_id])
50
+ @taxon.move_to_left_of(@right_taxon) if @right_taxon && @taxon.siblings.include?(@right_taxon)
51
+ end
52
+
53
+ if params[:format] == :json
54
+ render :json => "ok"
55
+ else
56
+ redirect_to edit_admin_taxonomy_url(@taxon.taxonomy), :notice => "Successfully updated taxon."
57
+ end
58
+ else
59
+ render :action => 'edit'
60
+ end
61
+ end
62
+
63
+ def destroy
64
+ @taxon = Taxon.find(params[:id])
65
+ @taxon.destroy
66
+ redirect_to edit_admin_taxonomy_url(@taxon.taxonomy), :notice => "Successfully destroyed taxon."
67
+ end
68
+
69
+
70
+ # Action for getting the children of a taxon
71
+ # right now it only responds to json requests
72
+ def children
73
+ @taxon = Taxon.find params[:id]
74
+ @children = @taxon.children
75
+ @tree = tree_children(@taxon)
76
+ respond_to do |format|
77
+ format.html
78
+ format.json { render :json => @tree }
79
+ end
80
+
81
+ end
82
+
83
+
84
+ private
85
+
86
+ def find_taxonomy
87
+ if params[:taxonomy_id]
88
+ @taxonomy = Taxonomy.find(params[:taxonomy_id])
89
+ else
90
+ @taxonomy = nil
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,62 @@
1
+ class Taxon < ActiveRecord::Base
2
+
3
+ acts_as_nested_set :dependent => :destroy
4
+
5
+ acts_as_url :name, :sync_url => true
6
+
7
+
8
+ belongs_to :taxonomy
9
+
10
+ before_create :set_path, :set_taxonomy
11
+ after_create :set_root
12
+ before_update :set_path
13
+
14
+
15
+ # TODO: I don't love this implementation as it doesn't allow for effective navigation up the tree
16
+ # but it does provide a nice url breadcrumb trail
17
+
18
+
19
+ # Creates path based on .to_url method provided by stringx gem
20
+ def set_path
21
+
22
+ if self.root?
23
+ self.path = '/'
24
+ else
25
+ ancestor_path = parent_taxon.path rescue "/"
26
+ sep = ancestor_path == "/" ? "" : "/"
27
+ self.path = ancestor_path + sep + self.url
28
+ end
29
+
30
+ #if parent_id.nil?
31
+ #self.path = self.url if self.path.blank?
32
+ #else
33
+ #parent_taxon = Taxon.find(parent_id)
34
+ #self.path = [parent_taxon.path, (self.path.blank? ? name.to_url : self.path.split("/").last)].join('/')
35
+ #end
36
+ end
37
+
38
+ def set_taxonomy
39
+ if ! self.root?
40
+ self.root_id = parent_taxon.root_id
41
+ self.taxonomy_id = parent_taxon.taxonomy_id
42
+ end
43
+ end
44
+
45
+ def set_root
46
+ self.root_id = self.id if self.root?
47
+ save
48
+ end
49
+
50
+
51
+
52
+ private
53
+
54
+ def parent_taxon
55
+ @parent_taxon ||= Taxon.find(self.parent_id)
56
+ end
57
+
58
+
59
+
60
+
61
+
62
+ end
@@ -0,0 +1,24 @@
1
+ class Taxonomy < ActiveRecord::Base
2
+ has_many :taxons
3
+ has_one :root, :class_name => 'Taxon', :conditions => "parent_id is null"
4
+
5
+
6
+ after_create :create_root_taxon
7
+ before_destroy :delete_taxons
8
+
9
+ def create_root_taxon
10
+ self.taxons.create(:name => self.name + "__root")
11
+ end
12
+
13
+
14
+ # Doing this through a callback because it doesn't
15
+ # rely on the destroy conditions of the taxons and
16
+ # makes deleting much more efficient
17
+ def delete_taxons
18
+ # TODO: More to do here.
19
+ # We probably will want to ensure that any items
20
+ # assigned to the taxons get reassigned or cleaned
21
+ # up appropriately.
22
+ Taxon.destroy_all(:taxonomy_id => self.id)
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ <p>
2
+ <%= f.label :name, t("name") %> <span class="required">*</span><br />
3
+ <%= text_field :taxonomy, :name %>
4
+ </p>
@@ -0,0 +1,9 @@
1
+ <% content_for :head do %>
2
+ <%= javascript_tag "var taxonomy_id = #{@taxonomy.id};
3
+ var loading = '#{escape_javascript t('loading')}';
4
+ var new_taxon = '#{escape_javascript t('new_taxon')}';
5
+ var server_error = '#{escape_javascript t('server_error')}';
6
+ var taxonomy_tree_error = '#{escape_javascript t('taxonomy_tree_error')}';"
7
+ %>
8
+ <%= javascript_include_tag 'taxonomy', 'jsTree/jquery.jstree.js' %>
9
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <table class="index" id='listing_taxonomies'>
2
+ <tr>
3
+ <th><%= "Name" %></th>
4
+ <th>&nbsp;</th>
5
+ </tr>
6
+ <% for taxonomy in @taxonomies %>
7
+ <tr id="<%= dom_id taxonomy %>">
8
+ <td>
9
+ <%= taxonomy.name %>
10
+ </td>
11
+ <td class="actions">
12
+ <%= link_to "Edit", edit_admin_taxonomy_url(taxonomy.id), :class => 'edit' %>
13
+ &nbsp;
14
+ <%= link_to "Delete", admin_taxonomy_path(taxonomy), :confirm => 'Are you sure?', :method => :delete %>
15
+
16
+ </td>
17
+ </tr>
18
+ <% end %>
19
+ </table>
20
+
@@ -0,0 +1,29 @@
1
+ <%= render :partial => "js_head" %>
2
+
3
+ <h1><%= t("taxonomy_edit")%></h1>
4
+
5
+ <p id="ajax_error" class="errorExplanation" style="display:none;"></p>
6
+
7
+ <%= form_for(:taxon, :url => admin_taxonomy_url, :html => { :method => :put }) do |f| %>
8
+ <%= render :partial => 'form', :locals => {:f => f} %>
9
+ <div>
10
+ <label>Taxonomy Tree</label><br />
11
+ <div id="taxonomy_tree" class="tree"></div>
12
+ </div>
13
+ <p id="progress" style="display:none;">
14
+ <%= image_tag('spinner.gif', :alt => "Spinner", :style => "vertical-align:bottom") %>
15
+ <%= t('updating') %>..
16
+ </p>
17
+
18
+ <p class="form-buttons">
19
+ <%= f.submit %> <%= link_to "Back to Taxonomies", admin_taxonomies_path %>
20
+ </p>
21
+ <% end %>
22
+
23
+
24
+ <% content_for :head do %>
25
+ <script type="text/javascript">
26
+ var initial = <%= raw @tree.to_json %>;
27
+
28
+ </script>
29
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <h1>Taxonomies</h1>
2
+
3
+ <div id='list-taxonomies'>
4
+ <%= render :partial => 'list' %>
5
+ </div>
6
+
7
+ <%= link_to "New Taxonomy", new_admin_taxonomy_url %>
@@ -0,0 +1,11 @@
1
+
2
+ <h1><%= t("new_taxonomy") %></h1>
3
+
4
+ <%= form_for(:taxonomy, :url => '/admin/taxonomies') do |f| %>
5
+
6
+ <%= render :partial => "form", :locals => { :f => f } %>
7
+
8
+ <p class="form-buttons">
9
+ <%= f.submit %> or <%= link_to "Cancel", admin_taxonomies_url %>
10
+ </p>
11
+ <% end %>