path_finder 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ pkg/**
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [name of plugin creator]
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,44 @@
1
+ h2. PathFinder
2
+
3
+ A Rails plugin which extends ActiveRecord using the decorator pattern to allow self-referential models (eg. acts_as_tree) to maintain a textual path representing itself and its ancestors.
4
+
5
+ h3. Install
6
+
7
+ gem install path_finder
8
+
9
+ h3. Example
10
+
11
+ In association with a catch-all route you can find a record using the URL:
12
+
13
+ Hierarchy -> Generated Path
14
+
15
+ # Categories -> /categories
16
+ ## Books -> /categories/books
17
+ ### Hardback -> /categories/books/hardback
18
+ ### Paperback -> /categories/books/paperback
19
+ ## Websites -> /categories/websites
20
+
21
+ Example URL: http://mywebsite.co.uk/categories/books/hardback
22
+
23
+ _category_controller.rb_
24
+
25
+ def show
26
+ @category = Category.find_by_path(request.path)
27
+ end
28
+
29
+ _category.rb_
30
+
31
+ class Category < ActiveRecord::Base
32
+ acts_as_tree
33
+ path_finder :column => 'path', :uid => 'to_param', :deliminator => '/'
34
+
35
+ def to_param
36
+ permalink
37
+ end
38
+ end
39
+
40
+ h3. Notes
41
+
42
+ The model must respond_to 'children'
43
+
44
+ Copyright (c) 2010 Kris Leech, released under the MIT license
@@ -0,0 +1,38 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the path_finder plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the path_finder plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'PathFinder'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = "path_finder"
29
+ gemspec.summary = "Textual path for self-referential models"
30
+ gemspec.description = "Textual path for self-referential models"
31
+ gemspec.email = "kris.leech@interkonect.com"
32
+ gemspec.homepage = "http://github.com/krisleech/Path-Finder"
33
+ gemspec.authors = ["Kris Leech"]
34
+ end
35
+ rescue LoadError
36
+ puts "Jeweler not available. Install it with: gem install jeweler"
37
+ end
38
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + "/rails/init"
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,148 @@
1
+ # PathFinder
2
+
3
+ # Usage:
4
+ # path_finder :column => 'path', :uid => 'to_param', :deliminator => '/'
5
+
6
+ module PathFinder
7
+
8
+
9
+ def path_finder(options = {})
10
+ raise "Options for path_finder must be a Hash" unless options.is_a? Hash
11
+ options.each do |key, value|
12
+ unless [:column, :uid, :deliminator].include? key
13
+ raise "Unknown option for path_finder: #{key.inspect} => #{value.inspect}."
14
+ end
15
+ end
16
+
17
+ send :include, InstanceMethods
18
+ send :extend, ClassMethods
19
+
20
+ options = {
21
+ :column => 'path',
22
+ :uid => 'to_param',
23
+ :deliminator => '/'
24
+ }.merge(options)
25
+
26
+ # Create class attributes for options and set defaults
27
+ self.cattr_accessor :path_finder_column
28
+ self.path_finder_column = options[:column] #|| 'path'
29
+
30
+ self.cattr_accessor :path_finder_uid
31
+ self.path_finder_uid = options[:uid] #|| 'to_param'
32
+
33
+ self.cattr_accessor :path_finder_deliminator
34
+ self.path_finder_deliminator = options[:deliminator] #|| '/'
35
+
36
+ before_validation_on_create :set_path
37
+ validates_presence_of self.path_finder_column.to_sym
38
+
39
+ if options[:set_depth]
40
+ # add before_save to set depth column
41
+ end
42
+
43
+ end # end path_finder
44
+
45
+
46
+ module ClassMethods
47
+ def path_finder_added?
48
+ true
49
+ end
50
+
51
+ # Recalculate all paths for given collection
52
+ def recreate_paths!(collection = nil)
53
+ raise 'No collection given' unless collection.is_a? Array
54
+ collection.each do |obj|
55
+ obj.recreate_path!
56
+ self.recreate_paths!(obj.children) unless obj.children.empty?
57
+ end
58
+ end
59
+ end
60
+
61
+ module InstanceMethods
62
+ # Note: self is an instance of "ActiveRecord"
63
+
64
+
65
+ # FIXME: private
66
+ # before_validation_on_create
67
+ def set_path
68
+ return unless self.send(self.class.path_finder_column).blank?
69
+ unless self.root?
70
+ self.send(self.class.path_finder_column + '=', [self.parent.send(self.class.path_finder_column), self.send(self.class.path_finder_uid)].join(self.class.path_finder_deliminator).gsub('//', '/'))
71
+ else
72
+ self.send(self.class.path_finder_column + '=', self.send(self.class.path_finder_uid))
73
+ end
74
+ end
75
+
76
+ def path_array
77
+ unless self.send(self.class.path_finder_column).blank?
78
+ self.send(self.class.path_finder_column.split(self.class.path_finder_deliminator))
79
+ else
80
+ if new_record? && parent
81
+ parent.path_array + [self.send(self.class.path_finder_uid)]
82
+ else
83
+ [] # this should not be possible (test required)
84
+ end
85
+ end
86
+ end
87
+
88
+ def leaf?
89
+ children.empty?
90
+ end
91
+
92
+ def node?
93
+ !leaf?
94
+ end
95
+
96
+ def root?
97
+ parent_id.nil?
98
+ end
99
+
100
+ # return a breadcrumb for any attribute
101
+ def path_text(attribute = 'name', join = ' | ')
102
+ ancestors.collect { |item| item.send(attribute) }.join(join)
103
+ end
104
+
105
+ def self_and_descendants
106
+ descendants + [self]
107
+ end
108
+
109
+ def descendants
110
+ children.map(&:descendants).flatten + children
111
+ end
112
+
113
+ def recreate_path!
114
+ set_path
115
+ save!
116
+ end
117
+
118
+ # Call method for ancestors, stop if we get an non-nil answer
119
+ def send_down(*args)
120
+ result = self.send(*args)
121
+ if result.nil? && !self.root?
122
+ result = self.parent.send_down(*args)
123
+ end
124
+ result
125
+ end
126
+
127
+ # Call method on all children
128
+ def send_up(*args)
129
+ return if children.empty?
130
+ children.each do | child |
131
+ child.send_up(*args)
132
+ end
133
+ end
134
+
135
+ # ALTERNATIVE
136
+ # def self_and_descendants
137
+ # self.class.find(:all, :conditions => ['path LIKE ?', self.path + '%'])
138
+ # end
139
+ #
140
+ #
141
+ # def descendants
142
+ # self_and_all_children.reject { |c| c.id == self.id }
143
+ # end
144
+ #
145
+ end
146
+ end
147
+
148
+ ActiveRecord::Base.send :extend, PathFinder
@@ -0,0 +1,53 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{path_finder}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kris Leech"]
12
+ s.date = %q{2010-02-11}
13
+ s.description = %q{Textual path for self-referential models}
14
+ s.email = %q{kris.leech@interkonect.com}
15
+ s.extra_rdoc_files = [
16
+ "README.textile"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "MIT-LICENSE",
21
+ "README.textile",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "init.rb",
25
+ "install.rb",
26
+ "lib/path_finder.rb",
27
+ "path_finder.gemspec",
28
+ "rails/init.rb",
29
+ "tasks/path_finder_tasks.rake",
30
+ "test/path_finder_test.rb",
31
+ "test/test_helper.rb",
32
+ "uninstall.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/krisleech/Path-Finder}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.5}
38
+ s.summary = %q{Textual path for self-referential models}
39
+ s.test_files = [
40
+ "test/path_finder_test.rb",
41
+ "test/test_helper.rb"
42
+ ]
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ else
50
+ end
51
+ else
52
+ end
53
+ end
@@ -0,0 +1 @@
1
+ require 'path_finder'
@@ -0,0 +1,4 @@
1
+ desc ""
2
+ task :path_finder do
3
+ puts 'Hello World!'
4
+ end
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class PathFinderTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: path_finder
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kris Leech
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-11 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Textual path for self-referential models
17
+ email: kris.leech@interkonect.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.textile
24
+ files:
25
+ - .gitignore
26
+ - MIT-LICENSE
27
+ - README.textile
28
+ - Rakefile
29
+ - VERSION
30
+ - init.rb
31
+ - install.rb
32
+ - lib/path_finder.rb
33
+ - path_finder.gemspec
34
+ - rails/init.rb
35
+ - tasks/path_finder_tasks.rake
36
+ - test/path_finder_test.rb
37
+ - test/test_helper.rb
38
+ - uninstall.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/krisleech/Path-Finder
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.5
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Textual path for self-referential models
67
+ test_files:
68
+ - test/path_finder_test.rb
69
+ - test/test_helper.rb