find_by_param 0.1.0 → 0.2.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.
- data/lib/find_by_param.rb +65 -50
- data/lib/find_by_param/version.rb +7 -0
- metadata +65 -94
- data/.gitignore +0 -4
- data/MIT-LICENSE +0 -20
- data/README.md +0 -121
- data/Rakefile +0 -45
- data/init.rb +0 -1
- data/install.rb +0 -1
- data/shoulda_macros/find_by_param.rb +0 -34
- data/shoulda_macros/matchers.rb +0 -49
- data/tasks/find_by_param_tasks.rake +0 -4
- data/test/find_by_param_test.rb +0 -156
- data/test/schema.rb +0 -21
- data/test/test_helper.rb +0 -17
- data/uninstall.rb +0 -1
- data/version.yml +0 -4
data/lib/find_by_param.rb
CHANGED
|
@@ -1,57 +1,58 @@
|
|
|
1
1
|
begin
|
|
2
|
-
$KCODE = 'u'
|
|
3
2
|
require 'rubygems'
|
|
4
3
|
require 'active_support'
|
|
5
4
|
rescue LoadError
|
|
6
5
|
end
|
|
6
|
+
|
|
7
7
|
module Railslove
|
|
8
8
|
module Plugins
|
|
9
9
|
module FindByParam
|
|
10
|
-
def self.enable
|
|
10
|
+
def self.enable # :nodoc:
|
|
11
11
|
return if ActiveRecord::Base.kind_of?(self::ClassMethods)
|
|
12
12
|
|
|
13
13
|
ActiveRecord::Base.class_eval do
|
|
14
14
|
class_inheritable_accessor :permalink_options
|
|
15
15
|
self.permalink_options = {:param => :id}
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
#default finders these are overwritten if you use make_permalink in
|
|
18
18
|
# your model
|
|
19
|
-
def self.find_by_param(value,args={})
|
|
19
|
+
def self.find_by_param(value,args={}) # :nodoc:
|
|
20
20
|
find_by_id(value,args)
|
|
21
21
|
end
|
|
22
|
-
def self.find_by_param!(value,args={})
|
|
22
|
+
def self.find_by_param!(value,args={}) # :nodoc:
|
|
23
23
|
find(value,args)
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
ActiveRecord::Base.extend(self::ClassMethods)
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
module ClassMethods
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
|
|
31
|
+
|
|
32
32
|
=begin rdoc
|
|
33
33
|
|
|
34
34
|
This method initializes find_by_param
|
|
35
35
|
|
|
36
36
|
class Post < ActiveRecord::Base
|
|
37
|
-
make_permalink :with => :title, :prepend_id=>true
|
|
37
|
+
make_permalink :with => :title, :prepend_id => true
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
The only required parameter, is <tt>:with</tt>.
|
|
40
|
+
The only required parameter, is <tt>:with</tt>.
|
|
41
41
|
|
|
42
42
|
If you want to use a non URL-save attribute as permalink your model should have a permalink-column to save the escaped permalink value. This field is then used for search.
|
|
43
43
|
|
|
44
|
-
If your you can just say make_permalink :with => :login and you're done.
|
|
44
|
+
If your you can just say make_permalink :with => :login and you're done.
|
|
45
45
|
|
|
46
|
-
You can use for example User.find_by_param(params[:id], args) to find the user by the defined permalink.
|
|
46
|
+
You can use for example User.find_by_param(params[:id], args) to find the user by the defined permalink.
|
|
47
47
|
|
|
48
48
|
== Available options
|
|
49
49
|
|
|
50
50
|
<tt>:with</tt>:: (required) The attribute that should be used as permalink
|
|
51
|
-
<tt>:field</tt>:: The name of your permalink column. make_permalink first checks if there is a column.
|
|
52
|
-
<tt>:prepend_id</tt>:: [true|false] Do you want to prepend the ID to the permalink? for URLs like: posts/123-my-post-title - find_by_param uses the ID column to search.
|
|
53
|
-
<tt>:
|
|
54
|
-
<tt>:
|
|
51
|
+
<tt>:field</tt>:: The name of your permalink column. make_permalink first checks if there is a column, default is 'permalink'.
|
|
52
|
+
<tt>:prepend_id</tt>:: [true|false] Do you want to prepend the ID to the permalink? for URLs like: posts/123-my-post-title - find_by_param uses the ID column to search, default is false.
|
|
53
|
+
<tt>:param_size</tt>:: [Number] Desired maximum size of the permalink, default is 50.
|
|
54
|
+
<tt>:escape</tt>:: [true|false] Do you want to escape the permalink value? (strip chars like öä?&) - actually you must do that, default is true.
|
|
55
|
+
<tt>:validate</tt>:: [true|false] Don't validate the :with field - set this to false if you validate it on your own, default is true.
|
|
55
56
|
<tt>:forbidden</tt>:: [Regexp|String|Array of Strings] Define which values should be forbidden. This is useful when combining user defined values to generate permalinks in combination with restful routing. <b>Make sure, especially in the case of a Regexp argument, that values may become valid by adding or incrementing a trailing integer.</b>
|
|
56
57
|
=end
|
|
57
58
|
def make_permalink(options={})
|
|
@@ -61,7 +62,7 @@ You can use for example User.find_by_param(params[:id], args) to find the user b
|
|
|
61
62
|
options[:prepend_id] ||= false
|
|
62
63
|
options[:param_size] ||= 50
|
|
63
64
|
options[:validate] = true if options[:validate].nil?
|
|
64
|
-
|
|
65
|
+
|
|
65
66
|
# validate if there is something we can use as param. you can overwrite the validate_param_is_not_blank method to customize the validation and the error messge.
|
|
66
67
|
if !options[:prepend_id] || !options[:validate]
|
|
67
68
|
validate :validate_param_is_not_blank
|
|
@@ -74,29 +75,29 @@ You can use for example User.find_by_param(params[:id], args) to find the user b
|
|
|
74
75
|
options[:forbidden_strings] = Array(forbidden).map(&:to_s)
|
|
75
76
|
end
|
|
76
77
|
end
|
|
77
|
-
|
|
78
|
+
|
|
78
79
|
if self.column_names.include?(options[:field].to_s)
|
|
79
80
|
options[:param] = options[:field]
|
|
80
81
|
before_save :save_permalink
|
|
81
82
|
end
|
|
82
|
-
|
|
83
|
+
|
|
83
84
|
self.permalink_options = options
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
extend Railslove::Plugins::FindByParam::SingletonMethods
|
|
86
|
+
include Railslove::Plugins::FindByParam::InstanceMethods
|
|
87
|
+
rescue ActiveRecord::ActiveRecordError
|
|
88
|
+
puts "[find_by_param error] database not available?"
|
|
88
89
|
end
|
|
89
90
|
end
|
|
90
|
-
|
|
91
|
+
|
|
91
92
|
module SingletonMethods
|
|
92
|
-
|
|
93
|
+
|
|
93
94
|
=begin rdoc
|
|
94
95
|
|
|
95
|
-
Search for an object by the defined permalink column. Similar to
|
|
96
|
-
Returns nil if nothing is found
|
|
97
|
-
|
|
96
|
+
Search for an object by the defined permalink column. Similar to
|
|
97
|
+
+find_by_login+. Returns +nil+ if nothing is found. Accepts an options hash as
|
|
98
|
+
second parameter which is passed on to the rails finder.
|
|
98
99
|
=end
|
|
99
|
-
def find_by_param(value,args={})
|
|
100
|
+
def find_by_param(value, args={})
|
|
100
101
|
if permalink_options[:prepend_id]
|
|
101
102
|
param = "id"
|
|
102
103
|
value = value.to_i
|
|
@@ -108,9 +109,11 @@ Accepts an options hash as a second parameter which is passed on to the rails fi
|
|
|
108
109
|
|
|
109
110
|
=begin rdoc
|
|
110
111
|
|
|
111
|
-
Like find_by_param but raises an ActiveRecord::RecordNotFound error
|
|
112
|
+
Like +find_by_param+ but raises an <tt>ActiveRecord::RecordNotFound</tt> error
|
|
113
|
+
if nothing is found - similar to find().
|
|
112
114
|
|
|
113
|
-
Accepts an options hash as
|
|
115
|
+
Accepts an options hash as second parameter which is passed on to the rails
|
|
116
|
+
finder.
|
|
114
117
|
=end
|
|
115
118
|
def find_by_param!(value, args={})
|
|
116
119
|
param = permalink_options[:param]
|
|
@@ -119,25 +122,28 @@ Accepts an options hash as a second parameter which is passed on to the rails fi
|
|
|
119
122
|
obj
|
|
120
123
|
end
|
|
121
124
|
end
|
|
122
|
-
|
|
125
|
+
|
|
123
126
|
module InstanceMethods
|
|
124
127
|
def to_param
|
|
125
128
|
value = self.send(permalink_options[:param]).dup.to_s.downcase rescue ""
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
''.tap do |param|
|
|
130
|
+
if value.blank?
|
|
131
|
+
param << id.to_s
|
|
132
|
+
else
|
|
133
|
+
param << "#{id}-" if permalink_options[:prepend_id]
|
|
134
|
+
param << escape_and_truncate_permalink(value)
|
|
135
|
+
end
|
|
130
136
|
end
|
|
131
137
|
end
|
|
132
|
-
|
|
138
|
+
|
|
133
139
|
protected
|
|
134
|
-
|
|
140
|
+
|
|
135
141
|
def save_permalink
|
|
136
142
|
return unless self.class.column_names.include?(permalink_options[:field].to_s)
|
|
137
143
|
counter = 0
|
|
138
144
|
base_value = escape_and_truncate_permalink(send(permalink_options[:with])).downcase
|
|
139
|
-
permalink_value =
|
|
140
|
-
|
|
145
|
+
permalink_value = base_value.to_s
|
|
146
|
+
|
|
141
147
|
conditions = ["#{self.class.table_name}.#{permalink_options[:field]} = ?", permalink_value]
|
|
142
148
|
unless new_record?
|
|
143
149
|
conditions.first << " and #{self.class.table_name}.#{self.class.primary_key} != ?"
|
|
@@ -145,17 +151,28 @@ Accepts an options hash as a second parameter which is passed on to the rails fi
|
|
|
145
151
|
end
|
|
146
152
|
while is_forbidden?(permalink_value) or
|
|
147
153
|
self.class.count(:all, :conditions => conditions) > 0
|
|
148
|
-
|
|
154
|
+
counter += 1
|
|
155
|
+
permalink_value = "#{base_value}-#{counter}"
|
|
156
|
+
|
|
157
|
+
if permalink_value.size > permalink_options[:param_size]
|
|
158
|
+
length = permalink_options[:param_size] - counter.to_s.size - 2
|
|
159
|
+
truncated_base = base_value[0..length]
|
|
160
|
+
permalink_value = "#{truncated_base}-#{counter}"
|
|
161
|
+
end
|
|
162
|
+
|
|
149
163
|
conditions[1] = permalink_value
|
|
150
164
|
end
|
|
151
165
|
write_attribute(permalink_options[:field], permalink_value)
|
|
152
166
|
true
|
|
153
167
|
end
|
|
154
|
-
|
|
168
|
+
|
|
155
169
|
def validate_param_is_not_blank
|
|
156
|
-
|
|
170
|
+
if self.escape_and_truncate_permalink(self.send(permalink_options[:with])).blank?
|
|
171
|
+
errors.add(permalink_options[:with],
|
|
172
|
+
"must have at least one non special character (a-z 0-9)")
|
|
173
|
+
end
|
|
157
174
|
end
|
|
158
|
-
|
|
175
|
+
|
|
159
176
|
def escape_permalink(value)
|
|
160
177
|
value.to_s.parameterize
|
|
161
178
|
end
|
|
@@ -166,7 +183,7 @@ Accepts an options hash as a second parameter which is passed on to the rails fi
|
|
|
166
183
|
end
|
|
167
184
|
|
|
168
185
|
def is_forbidden_string?(permalink_value)
|
|
169
|
-
permalink_options[:forbidden_strings] &&
|
|
186
|
+
permalink_options[:forbidden_strings] &&
|
|
170
187
|
permalink_options[:forbidden_strings].include?(permalink_value)
|
|
171
188
|
end
|
|
172
189
|
|
|
@@ -175,14 +192,12 @@ Accepts an options hash as a second parameter which is passed on to the rails fi
|
|
|
175
192
|
permalink_options[:forbidden_match] =~ permalink_value
|
|
176
193
|
end
|
|
177
194
|
|
|
178
|
-
|
|
179
|
-
#this escapes and truncates a value.
|
|
180
|
-
#used to escape and truncate permalink value
|
|
181
195
|
def escape_and_truncate_permalink(value)
|
|
182
|
-
self.escape_permalink(value)[0...self.permalink_options[:param_size]]
|
|
196
|
+
p = self.escape_permalink(value)[0...self.permalink_options[:param_size]]
|
|
197
|
+
p.ends_with?('-') ? p.chop : p
|
|
183
198
|
end
|
|
184
199
|
end
|
|
185
|
-
|
|
200
|
+
|
|
186
201
|
end
|
|
187
202
|
end
|
|
188
203
|
end
|
metadata
CHANGED
|
@@ -1,121 +1,92 @@
|
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: find_by_param
|
|
3
|
-
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
prerelease:
|
|
5
6
|
platform: ruby
|
|
6
|
-
authors:
|
|
7
|
+
authors:
|
|
7
8
|
- Michael Bumann
|
|
8
9
|
- Gregor Schmidt
|
|
9
10
|
autorequire:
|
|
10
11
|
bindir: bin
|
|
11
12
|
cert_chain: []
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
dependencies:
|
|
16
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
+
date: 2011-09-05 00:00:00.000000000Z
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
17
16
|
name: activerecord
|
|
17
|
+
requirement: &2157569500 !ruby/object:Gem::Requirement
|
|
18
|
+
none: false
|
|
19
|
+
requirements:
|
|
20
|
+
- - ~>
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: 3.0.3
|
|
18
23
|
type: :runtime
|
|
19
|
-
|
|
20
|
-
version_requirements:
|
|
21
|
-
|
|
22
|
-
- - ">="
|
|
23
|
-
- !ruby/object:Gem::Version
|
|
24
|
-
version: "2.3"
|
|
25
|
-
version:
|
|
26
|
-
- !ruby/object:Gem::Dependency
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: *2157569500
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: activesupport
|
|
28
|
+
requirement: &2157568820 !ruby/object:Gem::Requirement
|
|
29
|
+
none: false
|
|
30
|
+
requirements:
|
|
31
|
+
- - ~>
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 3.0.3
|
|
28
34
|
type: :runtime
|
|
29
|
-
|
|
30
|
-
version_requirements:
|
|
31
|
-
|
|
32
|
-
- - ">="
|
|
33
|
-
- !ruby/object:Gem::Version
|
|
34
|
-
version: "2.3"
|
|
35
|
-
version:
|
|
36
|
-
- !ruby/object:Gem::Dependency
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: *2157568820
|
|
37
|
+
- !ruby/object:Gem::Dependency
|
|
37
38
|
name: sqlite3-ruby
|
|
39
|
+
requirement: &2157568380 !ruby/object:Gem::Requirement
|
|
40
|
+
none: false
|
|
41
|
+
requirements:
|
|
42
|
+
- - ! '>='
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: '0'
|
|
38
45
|
type: :development
|
|
39
|
-
|
|
40
|
-
version_requirements:
|
|
41
|
-
|
|
42
|
-
- - ">="
|
|
43
|
-
- !ruby/object:Gem::Version
|
|
44
|
-
version: "0"
|
|
45
|
-
version:
|
|
46
|
-
- !ruby/object:Gem::Dependency
|
|
47
|
-
name: jeweler
|
|
48
|
-
type: :development
|
|
49
|
-
version_requirement:
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - ">="
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.11.0
|
|
55
|
-
version:
|
|
56
|
-
- !ruby/object:Gem::Dependency
|
|
46
|
+
prerelease: false
|
|
47
|
+
version_requirements: *2157568380
|
|
48
|
+
- !ruby/object:Gem::Dependency
|
|
57
49
|
name: rake
|
|
50
|
+
requirement: &2157567780 !ruby/object:Gem::Requirement
|
|
51
|
+
none: false
|
|
52
|
+
requirements:
|
|
53
|
+
- - ! '>='
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '0'
|
|
58
56
|
type: :development
|
|
59
|
-
|
|
60
|
-
version_requirements:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- !ruby/object:Gem::Version
|
|
64
|
-
version: "0"
|
|
65
|
-
version:
|
|
66
|
-
description: find_by_param is a nice and easy way to handle permalinks and dealing with searching for to_param values
|
|
57
|
+
prerelease: false
|
|
58
|
+
version_requirements: *2157567780
|
|
59
|
+
description: find_by_param is a nice and easy way to handle permalinks and dealing
|
|
60
|
+
with searching for to_param values
|
|
67
61
|
email: michael@railslove.com
|
|
68
62
|
executables: []
|
|
69
|
-
|
|
70
63
|
extensions: []
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
-
|
|
74
|
-
files:
|
|
75
|
-
- .gitignore
|
|
76
|
-
- MIT-LICENSE
|
|
77
|
-
- README.md
|
|
78
|
-
- Rakefile
|
|
79
|
-
- init.rb
|
|
80
|
-
- install.rb
|
|
64
|
+
extra_rdoc_files: []
|
|
65
|
+
files:
|
|
66
|
+
- lib/find_by_param/version.rb
|
|
81
67
|
- lib/find_by_param.rb
|
|
82
|
-
- shoulda_macros/find_by_param.rb
|
|
83
|
-
- shoulda_macros/matchers.rb
|
|
84
|
-
- tasks/find_by_param_tasks.rake
|
|
85
|
-
- test/find_by_param_test.rb
|
|
86
|
-
- test/schema.rb
|
|
87
|
-
- test/test_helper.rb
|
|
88
|
-
- uninstall.rb
|
|
89
|
-
- version.yml
|
|
90
|
-
has_rdoc: true
|
|
91
68
|
homepage: http://github.com/bumi/find_by_param
|
|
92
69
|
licenses: []
|
|
93
|
-
|
|
94
70
|
post_install_message:
|
|
95
|
-
rdoc_options:
|
|
96
|
-
|
|
97
|
-
require_paths:
|
|
71
|
+
rdoc_options: []
|
|
72
|
+
require_paths:
|
|
98
73
|
- lib
|
|
99
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
|
+
none: false
|
|
76
|
+
requirements:
|
|
77
|
+
- - ! '>='
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '0'
|
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ! '>='
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '0'
|
|
111
86
|
requirements: []
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
rubygems_version: 1.3.5
|
|
87
|
+
rubyforge_project: ! '[none]'
|
|
88
|
+
rubygems_version: 1.8.5
|
|
115
89
|
signing_key:
|
|
116
90
|
specification_version: 3
|
|
117
91
|
summary: Rails plugin to handle permalink values
|
|
118
|
-
test_files:
|
|
119
|
-
- test/find_by_param_test.rb
|
|
120
|
-
- test/schema.rb
|
|
121
|
-
- test/test_helper.rb
|
|
92
|
+
test_files: []
|
data/.gitignore
DELETED
data/MIT-LICENSE
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2007 [Michael Bumann - Railslove.com]
|
|
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.
|
data/README.md
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
find_by_param
|
|
2
|
-
=============
|
|
3
|
-
|
|
4
|
-
*find_by_param* helps you dealing with permalinks and finding objects by our
|
|
5
|
-
permalink value
|
|
6
|
-
|
|
7
|
-
class Post < ActiveRecord:Base
|
|
8
|
-
make_permalink :with => :title
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
now you can do
|
|
12
|
-
|
|
13
|
-
Post.find_by_param(...)
|
|
14
|
-
|
|
15
|
-
If you have a permalink-column *find_by_param* saves the permalink there and
|
|
16
|
-
uses that otherwise it just uses the provided attribute.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Installation
|
|
20
|
-
========
|
|
21
|
-
|
|
22
|
-
As gem from gemcutter:
|
|
23
|
-
-------------
|
|
24
|
-
|
|
25
|
-
% gem install find_by_param
|
|
26
|
-
|
|
27
|
-
Building your own
|
|
28
|
-
-------------
|
|
29
|
-
|
|
30
|
-
% rake gemspec
|
|
31
|
-
% rake install
|
|
32
|
-
|
|
33
|
-
As Rails plugin
|
|
34
|
-
-------------
|
|
35
|
-
|
|
36
|
-
% script/plugin install git@github.com:bumi/find_by_param.git
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Examples
|
|
40
|
-
========
|
|
41
|
-
|
|
42
|
-
Configuration
|
|
43
|
-
-------------
|
|
44
|
-
|
|
45
|
-
make_permalink :with => :login
|
|
46
|
-
make_permalink :with => :title, :prepend_id => true
|
|
47
|
-
make_permalink :with => :name, :forbidden => %w(new edit)
|
|
48
|
-
|
|
49
|
-
Client code
|
|
50
|
-
-----------
|
|
51
|
-
|
|
52
|
-
Post.create(:title => "hey ho let's go!").to_param #=> "hey-ho-lets-go"
|
|
53
|
-
# ... to_param is the method Rails calls to create the URL values
|
|
54
|
-
|
|
55
|
-
Post.find_by_param("hey-ho-lets-go") #=> <Post>
|
|
56
|
-
|
|
57
|
-
Post.find_by_param("is-not-there") #=> nil
|
|
58
|
-
Post.find_by_param!("is-not-there") #=> raises ActiveRecord::RecordNotFound
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Basic Documentation
|
|
62
|
-
===================
|
|
63
|
-
|
|
64
|
-
Options for make_permalink
|
|
65
|
-
--------------------------
|
|
66
|
-
|
|
67
|
-
The following options may be used, when configuring the permalink generation
|
|
68
|
-
with `make_permalink`.
|
|
69
|
-
|
|
70
|
-
* `:with` (required)
|
|
71
|
-
|
|
72
|
-
The attribute that should be used as permalink
|
|
73
|
-
|
|
74
|
-
* `:field`
|
|
75
|
-
|
|
76
|
-
The name of your permalink column. make_permalink first checks if there is
|
|
77
|
-
a column.
|
|
78
|
-
|
|
79
|
-
* `:prepend_id => [true|false]`
|
|
80
|
-
|
|
81
|
-
Do you want to prepend the ID to the permalink? for URLs like:
|
|
82
|
-
`posts/123-my-post-title` - *find_by_param* uses the ID column to search.
|
|
83
|
-
|
|
84
|
-
* `:escape => [true|false]`
|
|
85
|
-
|
|
86
|
-
Do you want to escape the permalink value? (strip chars like `öä?&`) -
|
|
87
|
-
actually you must do that
|
|
88
|
-
|
|
89
|
-
* `:forbidden => [Regexp|String|Array of Strings]`
|
|
90
|
-
|
|
91
|
-
Define which values should be forbidden. This is useful when combining user
|
|
92
|
-
defined values to generate permalinks in combination with restful routing.
|
|
93
|
-
**Make sure, especially in the case of a Regexp argument, that values may
|
|
94
|
-
become valid by adding or incrementing a trailing integer.**
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Class methods provided by *find_by_param*
|
|
98
|
-
---------------------------------------
|
|
99
|
-
|
|
100
|
-
The following methods are added as public methods to all classes containing a
|
|
101
|
-
permalink field.
|
|
102
|
-
|
|
103
|
-
* `find_by_param(id)`
|
|
104
|
-
|
|
105
|
-
Look up a value by its permalink value, returns matching instance or
|
|
106
|
-
`nil`, if none is found.
|
|
107
|
-
|
|
108
|
-
* `find_by_param!(id)`
|
|
109
|
-
|
|
110
|
-
Look up a value by its permalink value, returns matching instance or
|
|
111
|
-
raises `ActiveRecord::RecordNotFound`, if none is found.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
Issues
|
|
115
|
-
=======
|
|
116
|
-
|
|
117
|
-
* Alex Sharp (http://github.com/ajsharp) pointed to an issue with STI. Better call make_permalink in every child class and not only in the parent class..
|
|
118
|
-
* write nice docs
|
|
119
|
-
* write nicer tests
|
|
120
|
-
|
|
121
|
-
Copyright (c) 2007 \[Michael Bumann - Railslove.com\], released under the MIT license
|
data/Rakefile
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
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 find_by_param plugin.'
|
|
9
|
-
Rake::TestTask.new(:test) do |t|
|
|
10
|
-
t.libs << 'lib'
|
|
11
|
-
t.pattern = 'test/**/*_test.rb'
|
|
12
|
-
t.verbose = true
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
desc 'Generate documentation for the find_by_param plugin.'
|
|
16
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
17
|
-
rdoc.rdoc_dir = 'rdoc'
|
|
18
|
-
rdoc.title = 'FindByParam'
|
|
19
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
|
20
|
-
rdoc.rdoc_files.include('README')
|
|
21
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
begin
|
|
25
|
-
gem 'jeweler', '>= 0.11.0'
|
|
26
|
-
require 'jeweler'
|
|
27
|
-
Jeweler::Tasks.new do |s|
|
|
28
|
-
s.name = "find_by_param"
|
|
29
|
-
s.summary = "Rails plugin to handle permalink values"
|
|
30
|
-
s.email = "michael@railslove.com"
|
|
31
|
-
s.homepage = "http://github.com/bumi/find_by_param"
|
|
32
|
-
s.description = "find_by_param is a nice and easy way to handle " +
|
|
33
|
-
"permalinks and dealing with searching for to_param values"
|
|
34
|
-
s.authors = ["Michael Bumann", "Gregor Schmidt"]
|
|
35
|
-
s.add_dependency('activerecord', '>= 2.3')
|
|
36
|
-
s.add_dependency('activesupport', '>= 2.3')
|
|
37
|
-
|
|
38
|
-
s.add_development_dependency('sqlite3-ruby')
|
|
39
|
-
s.add_development_dependency('jeweler', '>= 0.11.0')
|
|
40
|
-
s.add_development_dependency('rake')
|
|
41
|
-
end
|
|
42
|
-
rescue LoadError
|
|
43
|
-
puts "Jeweler not available. Install it with: sudo gem install jeweler --version '>= 0.11.0'"
|
|
44
|
-
exit(1)
|
|
45
|
-
end
|
data/init.rb
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
require 'find_by_param'
|
data/install.rb
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
puts IO.read(File.join(File.dirname(__FILE__), 'README'))
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'matchers')
|
|
2
|
-
# this is experimental. My first try to write a shoulda matcher
|
|
3
|
-
module Railslove
|
|
4
|
-
module Plugins
|
|
5
|
-
module FindByParam
|
|
6
|
-
module Shoulda
|
|
7
|
-
include Matchers
|
|
8
|
-
|
|
9
|
-
def should_make_permalink(options = {})
|
|
10
|
-
klass = self.name.gsub(/Test$/, '').constantize
|
|
11
|
-
|
|
12
|
-
options[:field] ||= "permalink"
|
|
13
|
-
options[:param] = options[:with]
|
|
14
|
-
options[:escape] ||= true
|
|
15
|
-
options[:prepend_id] ||= false
|
|
16
|
-
options[:param_size] ||= 50
|
|
17
|
-
options[:validate] ||= true
|
|
18
|
-
if klass.column_names.include?(options[:field].to_s)
|
|
19
|
-
options[:param] = options[:field]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
matcher = validate_find_by_param_options(options)
|
|
23
|
-
|
|
24
|
-
should matcher.description do
|
|
25
|
-
assert_accepts(matcher, klass)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
class Test::Unit::TestCase
|
|
33
|
-
extend Railslove::Plugins::FindByParam::Shoulda
|
|
34
|
-
end
|
data/shoulda_macros/matchers.rb
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# this nesting is actually a bit stupid :)
|
|
2
|
-
module Railslove
|
|
3
|
-
module Plugins
|
|
4
|
-
module FindByParam
|
|
5
|
-
module Shoulda
|
|
6
|
-
module Matchers
|
|
7
|
-
def validate_find_by_param_options(options)
|
|
8
|
-
FindByParamMatcher.new(options)
|
|
9
|
-
end
|
|
10
|
-
class FindByParamMatcher
|
|
11
|
-
def initialize(options)
|
|
12
|
-
@expected_options = options
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def matches?(klass)
|
|
16
|
-
@klass = klass
|
|
17
|
-
valid_permalink_options? && responds_to_find_by_param_class_methods? && responds_to_find_by_param_instance_methods?
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def description
|
|
21
|
-
"have valid find_by_pram_configuration"
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def failure_message
|
|
25
|
-
"invalid find_by_param configuration: expected: #{@expected_options.inspect} got: #{@klass.permalink_options.inspect}"
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
protected
|
|
29
|
-
def valid_permalink_options?
|
|
30
|
-
@expected_options == @klass.permalink_options
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def responds_to_find_by_param_class_methods?
|
|
34
|
-
%w{make_permalink find_by_param find_by_param!}.all? do |method|
|
|
35
|
-
@klass.respond_to?(method)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def responds_to_find_by_param_instance_methods?
|
|
40
|
-
%w{escape_permalink}.all? do |method|
|
|
41
|
-
@klass.new.respond_to?(method)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
data/test/find_by_param_test.rb
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
require(File.join(File.dirname(__FILE__), 'test_helper'))
|
|
2
|
-
|
|
3
|
-
# TODO: make some nice mock objects!!!!!!!!!!!!!!!!!!
|
|
4
|
-
class Post < ActiveRecord::Base; end
|
|
5
|
-
class User < ActiveRecord::Base; end
|
|
6
|
-
class Article < ActiveRecord::Base; end
|
|
7
|
-
class Author < ActiveRecord::Base;
|
|
8
|
-
def full_name
|
|
9
|
-
[first_name, last_name].join(" ")
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# TODO DO BETTER TESTING!!!!
|
|
14
|
-
class FindByParamTest < Test::Unit::TestCase
|
|
15
|
-
|
|
16
|
-
def test_default_should_return_id
|
|
17
|
-
post = Post.create(:title=>"hey ho let's go!")
|
|
18
|
-
assert_equal post.to_param, post.id.to_s
|
|
19
|
-
assert_equal post.permalink, nil
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def test_permalink_should_be_saved
|
|
23
|
-
Post.class_eval "make_permalink :with => :title"
|
|
24
|
-
post = Post.create(:title=>"hey ho let's go!")
|
|
25
|
-
assert_equal "hey-ho-let-s-go", post.to_param
|
|
26
|
-
assert_equal post.permalink, post.to_param
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def test_permalink_should_be_allowed_on_virtual_attributes
|
|
30
|
-
Author.class_eval "make_permalink :with => :full_name"
|
|
31
|
-
author = Author.create(:first_name => "Bugs", :last_name => "Bunny")
|
|
32
|
-
assert_equal author.to_param, "bugs-bunny"
|
|
33
|
-
assert_equal author.permalink, author.to_param
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def test_permalink_should_not_create_forbidden_permalinks_given_one_string
|
|
37
|
-
Author.class_eval "make_permalink :with => :first_name, :forbidden => 'me'"
|
|
38
|
-
author = Author.create(:first_name => "me")
|
|
39
|
-
assert_not_equal author.to_param, "me"
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def test_permalink_should_not_create_forbidden_permalinks_given_mulitple_strings
|
|
43
|
-
Author.class_eval "make_permalink :with => :first_name, :forbidden => %w{you me}"
|
|
44
|
-
author1 = Author.create(:first_name => "me")
|
|
45
|
-
author2 = Author.create(:first_name => "you")
|
|
46
|
-
|
|
47
|
-
assert_not_equal author1.to_param, "me"
|
|
48
|
-
assert_not_equal author2.to_param, "you"
|
|
49
|
-
assert_not_equal author1.to_param, author2.to_param
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def test_permalink_should_not_create_forbidden_permalinks_given_a_regexp
|
|
53
|
-
Author.class_eval 'make_permalink :with => :first_name, :forbidden => /\D$/'
|
|
54
|
-
author1 = Author.create(:first_name => "me")
|
|
55
|
-
author2 = Author.create(:first_name => "you")
|
|
56
|
-
|
|
57
|
-
assert_not_equal author1.to_param, "me"
|
|
58
|
-
assert_not_equal author2.to_param, "you"
|
|
59
|
-
assert_not_equal author1.to_param, author2.to_param
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def test_permalink_should_be_trunkated
|
|
63
|
-
Post.class_eval "make_permalink :with => :title"
|
|
64
|
-
post = Post.create(:title=>"thisoneisaveryveryveryveryveryveryverylonglonglonglongtitlethisoneisaveryveryveryveryveryveryverylonglonglonglongtitle")
|
|
65
|
-
assert_equal "thisoneisaveryveryveryveryveryveryverylonglonglong", post.to_param
|
|
66
|
-
assert_equal post.to_param.size, 50
|
|
67
|
-
assert_equal post.permalink, post.to_param
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def test_permalink_should_be_trunkated_to_custom_size
|
|
71
|
-
Post.class_eval "make_permalink :with => :title, :param_size=>10"
|
|
72
|
-
post = Post.create(:title=>"thisoneisaveryveryveryveryveryveryverylonglonglonglongtitlethisoneisaveryveryveryveryveryveryverylonglonglonglongtitle")
|
|
73
|
-
assert_equal "thisoneisa",post.to_param
|
|
74
|
-
assert_equal post.permalink, post.to_param
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def test_should_search_field_for_to_param_field
|
|
78
|
-
User.class_eval "make_permalink :with => :login"
|
|
79
|
-
user = User.create(:login=>"bumi")
|
|
80
|
-
assert_equal user, User.find_by_param("bumi")
|
|
81
|
-
assert_equal user, User.find_by_param!("bumi")
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def test_should_validate_presence_of_the_field_used_to_create_the_param
|
|
85
|
-
User.class_eval "make_permalink :with => :login"
|
|
86
|
-
user = User.create(:login=>nil)
|
|
87
|
-
assert_equal false, user.valid?
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def test_to_param_should_perpend_id
|
|
91
|
-
Article.class_eval "make_permalink :with => :title, :prepend_id=>true "
|
|
92
|
-
article = Article.create(:title=>"hey ho let's go!")
|
|
93
|
-
assert_equal article.to_param, "#{article.id}-hey-ho-let-s-go"
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def test_should_increment_counter_if_not_unique
|
|
97
|
-
Post.class_eval "make_permalink :with => :title"
|
|
98
|
-
Post.create(:title=>"my awesome title!")
|
|
99
|
-
post = Post.create(:title=>"my awesome title!")
|
|
100
|
-
assert_equal "my-awesome-title-1", post.to_param
|
|
101
|
-
assert_equal post.permalink, post.to_param
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def test_should_record_not_found_error
|
|
105
|
-
assert_raise(ActiveRecord::RecordNotFound) { Post.find_by_param!("isnothere") }
|
|
106
|
-
end
|
|
107
|
-
def test_should_return_nil_if_not_found
|
|
108
|
-
assert_equal nil, Post.find_by_param("isnothere")
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def test_should_strip_special_chars
|
|
112
|
-
assert_equal "+-he-l-l-o-ni-ce-duaode", Post.new.send(:escape_permalink, "+*(he/=&l$l<o !ni^?ce-`duäöde;:@")
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def test_does_not_leak_options
|
|
116
|
-
Post.class_eval "make_permalink :with => :title, :forbidden => 'foo'"
|
|
117
|
-
assert_equal( {:param => "permalink",
|
|
118
|
-
:param_size => 50,
|
|
119
|
-
:field => "permalink",
|
|
120
|
-
:with => :title,
|
|
121
|
-
:prepend_id => false,
|
|
122
|
-
:escape => true,
|
|
123
|
-
:validate => true,
|
|
124
|
-
:forbidden_strings => ["foo"]}, Post.permalink_options)
|
|
125
|
-
|
|
126
|
-
User.class_eval "make_permalink :with => :login, :forbidden => %w{foo bar}"
|
|
127
|
-
assert_equal( {:param => :login,
|
|
128
|
-
:param_size => 50,
|
|
129
|
-
:field => "permalink",
|
|
130
|
-
:with => :login,
|
|
131
|
-
:prepend_id => false,
|
|
132
|
-
:escape => true,
|
|
133
|
-
:validate => true,
|
|
134
|
-
:forbidden_strings => ["foo", "bar"]}, User.permalink_options)
|
|
135
|
-
|
|
136
|
-
Article.class_eval "make_permalink :with => :title, :prepend_id => true, :forbidden => /baz$/"
|
|
137
|
-
assert_equal( {:param => :title,
|
|
138
|
-
:param_size => 50,
|
|
139
|
-
:field => "permalink",
|
|
140
|
-
:with => :title,
|
|
141
|
-
:prepend_id => true,
|
|
142
|
-
:escape => true,
|
|
143
|
-
:validate => true,
|
|
144
|
-
:forbidden_match => /baz$/}, Article.permalink_options)
|
|
145
|
-
|
|
146
|
-
Author.class_eval "make_permalink :with => :full_name, :validate => false"
|
|
147
|
-
assert_equal( {:param => "permalink",
|
|
148
|
-
:param_size => 50,
|
|
149
|
-
:field => "permalink",
|
|
150
|
-
:with => :full_name,
|
|
151
|
-
:prepend_id => false,
|
|
152
|
-
:escape => true,
|
|
153
|
-
:validate => false}, Author.permalink_options)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
end
|
data/test/schema.rb
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
ActiveRecord::Schema.define(:version => 0) do
|
|
2
|
-
|
|
3
|
-
create_table :posts, :force => true do |t|
|
|
4
|
-
t.string :title
|
|
5
|
-
t.string :permalink
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
create_table :articles, :force => true do |t|
|
|
9
|
-
t.string :title
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
create_table :users, :force => true do |t|
|
|
13
|
-
t.string :login
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
create_table :authors, :force => true do |t|
|
|
17
|
-
t.string :first_name
|
|
18
|
-
t.string :last_name
|
|
19
|
-
t.string :permalink
|
|
20
|
-
end
|
|
21
|
-
end
|
data/test/test_helper.rb
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
require 'test/unit'
|
|
2
|
-
require 'rubygems'
|
|
3
|
-
require 'active_record'
|
|
4
|
-
require 'active_support'
|
|
5
|
-
#require 'active_support/multibyte'
|
|
6
|
-
require 'find_by_param'
|
|
7
|
-
class ActiveRecord::Base
|
|
8
|
-
class_inheritable_accessor :permalink_options
|
|
9
|
-
self.permalink_options = {:param => :id}
|
|
10
|
-
end
|
|
11
|
-
ActiveRecord::Base.send(:include, Railslove::Plugins::FindByParam)
|
|
12
|
-
|
|
13
|
-
ActiveRecord::Base.establish_connection({
|
|
14
|
-
'adapter' => 'sqlite3',
|
|
15
|
-
'database' => ':memory:'
|
|
16
|
-
})
|
|
17
|
-
load(File.join(File.dirname(__FILE__), 'schema.rb'))
|
data/uninstall.rb
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Uninstall hook code here
|
data/version.yml
DELETED