public
Fork of halorgium/mephisto
Description: A mirror of the mephisto code-base
Homepage: http://mephistoblog.com/
Clone URL: git://github.com/technoweenie/mephisto.git
Click here to lend your support to: mephisto and make a donation at www.pledgie.com !
update permalink_fu plugin
technoweenie (author)
Sat Feb 02 15:30:22 -0800 2008
commit  86d5a4d33d898d3e4e1532af853587a7c4616147
tree    1af702ee651fb6b41dc53c686599fcec9e5e9230
parent  4d74fcfad278355a5d380c61231bca9409596f36
...
1
2
 
3
...
 
1
2
3
0
@@ -1 +1 @@
0
-ActiveRecord::Base.send :extend, PermalinkFu
0
\ No newline at end of file
0
+ActiveRecord::Base.send :include, PermalinkFu
0
\ No newline at end of file
...
1
 
2
3
4
5
6
 
7
8
 
9
10
11
...
13
14
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
 
35
36
37
38
39
 
40
...
1
2
3
4
5
6
 
7
8
 
9
10
11
12
...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
86
87
88
89
90
 
91
92
0
@@ -1,11 +1,12 @@
0
 require 'iconv'
0
+require 'digest/sha1'
0
 module PermalinkFu
0
   class << self
0
     attr_accessor :translation_to
0
     attr_accessor :translation_from
0
-
0
+
0
     def escape(str)
0
- s = Iconv.iconv(translation_to, translation_from, str).to_s
0
+ s = Iconv.iconv(translation_to + '//IGNORE', translation_from, str).to_s
0
       s.gsub!(/\W+/, ' ') # all non-word chars to spaces
0
       s.strip! # ohh la la
0
       s.downcase! #
0
@@ -13,27 +14,78 @@ module PermalinkFu
0
       s
0
     end
0
   end
0
+
0
+ def self.included(base)
0
+ base.extend ClassMethods
0
+ class << base
0
+ attr_accessor :permalink_options
0
+ attr_accessor :permalink_attributes
0
+ attr_accessor :permalink_field
0
+ end
0
+ end
0
+
0
+ module ClassMethods
0
+ # Specifies the given field(s) as a permalink, meaning it is passed through PermalinkFu.escape and set to the permalink_field. This
0
+ # is done
0
+ #
0
+ # class Foo < ActiveRecord::Base
0
+ # # stores permalink form of #title to the #permalink attribute
0
+ # has_permalink :title
0
+ #
0
+ # # stores a permalink form of "#{category}-#{title}" to the #permalink attribute
0
+ #
0
+ # has_permalink [:category, :title]
0
+ #
0
+ # # stores permalink form of #title to the #category_permalink attribute
0
+ # has_permalink [:category, :title], :category_permalink
0
+ #
0
+ # # add a scope
0
+ # has_permalink :title, :scope => :blog_id
0
+ #
0
+ # # add a scope and specify the permalink field name
0
+ # has_permalink :title, :slug, :scope => :blog_id
0
+ # end
0
+ #
0
+ def has_permalink(attr_names = [], permalink_field = nil, options = {})
0
+ if permalink_field.is_a?(Hash)
0
+ options = permalink_field
0
+ permalink_field = nil
0
+ end
0
+ self.permalink_attributes = Array(attr_names)
0
+ self.permalink_field = permalink_field || :permalink
0
+ self.permalink_options = options
0
+ before_validation :create_unique_permalink
0
+ evaluate_attribute_method permalink_field, "def #{self.permalink_field}=(new_value);write_attribute(:#{self.permalink_field}, PermalinkFu.escape(new_value));end", "#{self.permalink_field}="
0
+ end
0
+ end
0
+
0
+protected
0
+ def create_unique_permalink
0
+ if send(self.class.permalink_field).to_s.empty?
0
+ send("#{self.class.permalink_field}=", create_permalink_for(self.class.permalink_attributes))
0
+ end
0
+ base = send(self.class.permalink_field)
0
+ counter = 1
0
+ # oh how i wish i could use a hash for conditions
0
+ conditions = ["#{self.class.permalink_field} = ?", base]
0
+ unless new_record?
0
+ conditions.first << " and id != ?"
0
+ conditions << id
0
+ end
0
+ if self.class.permalink_options[:scope]
0
+ conditions.first << " and #{self.class.permalink_options[:scope]} = ?"
0
+ conditions << send(self.class.permalink_options[:scope])
0
+ end
0
+ while self.class.exists?(conditions)
0
+ conditions[1] = "#{base}-#{counter += 1}"
0
+ send("#{self.class.permalink_field}=", conditions[1])
0
+ end
0
+ end
0
 
0
- # Specifies the given field(s) as a permalink, meaning it is passed through PermalinkFu.escape and set to the permalink_field. This
0
- # is done
0
- #
0
- # class Foo < ActiveRecord::Base
0
- # # stores permalink form of #title to the #permalink attribute
0
- # has_permalink :title
0
- #
0
- # # stores a permalink form of "#{category}-#{title}" to the #permalink attribute
0
- #
0
- # has_permalink [:category, :title]
0
- #
0
- # # stores permalink form of #title to the #category_permalink attribute
0
- # has_permalink [:category, :title], :category_permalink
0
- # end
0
- #
0
- def has_permalink(attr_names = [], permalink_field = nil)
0
- permalink_field ||= 'permalink'
0
- before_validation { |record| record.send("#{permalink_field}=", Array(attr_names).collect { |attr_name| PermalinkFu.escape(record.send(attr_name).to_s) }.join('-')) if record.send(permalink_field).to_s.empty? }
0
+ def create_permalink_for(attr_names)
0
+ attr_names.collect { |attr_name| send(attr_name).to_s } * " "
0
   end
0
 end
0
 
0
 PermalinkFu.translation_to = 'ascii//translit'
0
-PermalinkFu.translation_from = 'utf-8'
0
+PermalinkFu.translation_from = 'utf-8'
0
\ No newline at end of file
...
1
2
3
4
5
 
 
 
6
7
 
 
 
 
 
 
 
8
9
10
 
 
11
12
13
14
15
 
 
16
17
18
19
 
 
 
 
 
 
20
21
22
23
24
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
27
28
 
 
 
 
 
 
29
30
31
32
 
33
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
37
38
...
40
41
42
43
 
 
44
45
46
...
68
69
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
...
1
2
3
 
 
4
5
6
7
 
8
9
10
11
12
13
14
15
 
 
16
17
18
19
 
 
 
20
21
22
23
 
 
24
25
26
27
28
29
30
 
 
 
 
 
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 
 
47
48
49
50
51
52
53
54
55
 
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
99
100
101
 
102
103
104
105
106
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
0
@@ -1,38 +1,97 @@
0
 require 'test/unit'
0
 require File.join(File.dirname(__FILE__), '../lib/permalink_fu')
0
 
0
-class MockModel
0
- extend PermalinkFu
0
+class BaseModel
0
+ include PermalinkFu
0
+ attr_accessor :id
0
   attr_accessor :title
0
- attr_accessor :permalink
0
+ attr_accessor :extra
0
+ attr_reader :permalink
0
+ attr_accessor :foo
0
+
0
+ class << self
0
+ attr_accessor :validation
0
+ end
0
   
0
- def self.before_validation(&block)
0
- @@validation = block
0
+ def self.generated_methods
0
+ @generated_methods ||= []
0
   end
0
   
0
- def validate
0
- @@validation.call self
0
- permalink
0
+ def self.primary_key
0
+ :id
0
   end
0
   
0
- has_permalink :title
0
-end
0
+ def self.logger
0
+ nil
0
+ end
0
+
0
+ # ripped from AR
0
+ def self.evaluate_attribute_method(attr_name, method_definition, method_name=attr_name)
0
 
0
-class MockModelExtra
0
- extend PermalinkFu
0
- attr_accessor :title
0
- attr_accessor :extra
0
- attr_accessor :permalink
0
+ unless method_name.to_s == primary_key.to_s
0
+ generated_methods << method_name
0
+ end
0
+
0
+ begin
0
+ class_eval(method_definition, __FILE__, __LINE__)
0
+ rescue SyntaxError => err
0
+ generated_methods.delete(attr_name)
0
+ if logger
0
+ logger.warn "Exception occurred during reader method compilation."
0
+ logger.warn "Maybe #{attr_name} is not a valid Ruby identifier?"
0
+ logger.warn "#{err.message}"
0
+ end
0
+ end
0
+ end
0
 
0
- def self.before_validation(&block)
0
- @@validation = block
0
+ def self.exists?(*args)
0
+ false
0
+ end
0
+
0
+ def self.before_validation(method)
0
+ self.validation = method
0
   end
0
 
0
   def validate
0
- @@validation.call self
0
+ send self.class.validation
0
     permalink
0
   end
0
+
0
+ def new_record?
0
+ @id.nil?
0
+ end
0
+
0
+ def write_attribute(key, value)
0
+ instance_variable_set "@#{key}", value
0
+ end
0
+end
0
+
0
+class MockModel < BaseModel
0
+ def self.exists?(conditions)
0
+ if conditions[1] == 'foo' || conditions[1] == 'bar' ||
0
+ (conditions[1] == 'bar-2' && conditions[2] != 2)
0
+ true
0
+ else
0
+ false
0
+ end
0
+ end
0
 
0
+ has_permalink :title
0
+end
0
+
0
+class ScopedModel < BaseModel
0
+ def self.exists?(conditions)
0
+ if conditions[1] == 'foo' && conditions[2] != 5
0
+ true
0
+ else
0
+ false
0
+ end
0
+ end
0
+
0
+ has_permalink :title, :scope => :foo
0
+end
0
+
0
+class MockModelExtra < BaseModel
0
   has_permalink [:title, :extra]
0
 end
0
 
0
@@ -40,7 +99,8 @@ class PermalinkFuTest < Test::Unit::TestCase
0
   @@samples = {
0
     'This IS a Tripped out title!!.!1 (well/ not really)' => 'this-is-a-tripped-out-title-1-well-not-really',
0
     '////// meph1sto r0x ! \\\\\\' => 'meph1sto-r0x',
0
- 'āčēģīķļņū' => 'acegiklnu'
0
+ 'āčēģīķļņū' => 'acegiklnu',
0
+ '中文測試 chinese text' => 'chinese-text'
0
   }
0
 
0
   @@extra = { 'some-)()()-ExtRa!/// .data==?> to \/\/test' => 'some-extra-data-to-test' }
0
@@ -68,4 +128,35 @@ class PermalinkFuTest < Test::Unit::TestCase
0
       end
0
     end
0
   end
0
+
0
+ def test_should_create_unique_permalink
0
+ @m = MockModel.new
0
+ @m.permalink = 'foo'
0
+ @m.validate
0
+ assert_equal 'foo-2', @m.permalink
0
+
0
+ @m.permalink = 'bar'
0
+ @m.validate
0
+ assert_equal 'bar-3', @m.permalink
0
+ end
0
+
0
+ def test_should_not_check_itself_for_unique_permalink
0
+ @m = MockModel.new
0
+ @m.id = 2
0
+ @m.permalink = 'bar-2'
0
+ @m.validate
0
+ assert_equal 'bar-2', @m.permalink
0
+ end
0
+
0
+ def test_should_create_unique_scoped_permalink
0
+ @m = ScopedModel.new
0
+ @m.permalink = 'foo'
0
+ @m.validate
0
+ assert_equal 'foo-2', @m.permalink
0
+
0
+ @m.foo = 5
0
+ @m.permalink = 'foo'
0
+ @m.validate
0
+ assert_equal 'foo', @m.permalink
0
+ end
0
 end

Comments

    No one has commented yet.