path_finder 1.0.0

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.
@@ -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