rd_find_by_param 0.1.0 → 0.1.1
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 +34 -145
- data/lib/find_by_param/version.rb +1 -1
- metadata +4 -4
data/lib/find_by_param.rb
CHANGED
|
@@ -1,123 +1,52 @@
|
|
|
1
1
|
begin
|
|
2
|
-
|
|
3
|
-
require 'rubygems'
|
|
4
|
-
require 'active_support'
|
|
2
|
+
require "active_support/multibyte"
|
|
5
3
|
rescue LoadError
|
|
4
|
+
require "rubygems"
|
|
5
|
+
require "active_support/multibyte"
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
module Railslove
|
|
9
9
|
module Plugins
|
|
10
10
|
module FindByParam
|
|
11
|
-
def self.enable # :nodoc:
|
|
12
|
-
return if ActiveRecord::Base.kind_of?(self::ClassMethods)
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
self.permalink_options = {:param => :id}
|
|
17
|
-
|
|
18
|
-
#default finders these are overwritten if you use make_permalink in
|
|
19
|
-
# your model
|
|
20
|
-
def self.find_by_param(value,args={}) # :nodoc:
|
|
21
|
-
find_by_id(value,args)
|
|
22
|
-
end
|
|
23
|
-
def self.find_by_param!(value,args={}) # :nodoc:
|
|
24
|
-
find(value,args)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
ActiveRecord::Base.extend(self::ClassMethods)
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.extend(ClassMethods)
|
|
28
14
|
end
|
|
29
15
|
|
|
30
16
|
module ClassMethods
|
|
31
17
|
|
|
32
|
-
|
|
33
|
-
=begin rdoc
|
|
34
|
-
|
|
35
|
-
This method initializes find_by_param
|
|
36
|
-
|
|
37
|
-
class Post < ActiveRecord::Base
|
|
38
|
-
make_permalink :with => :title, :prepend_id => true
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
The only required parameter, is <tt>:with</tt>.
|
|
42
|
-
|
|
43
|
-
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.
|
|
44
|
-
|
|
45
|
-
If your you can just say make_permalink :with => :login and you're done.
|
|
46
|
-
|
|
47
|
-
You can use for example User.find_by_param(params[:id], args) to find the user by the defined permalink.
|
|
48
|
-
|
|
49
|
-
== Available options
|
|
50
|
-
|
|
51
|
-
<tt>:with</tt>:: (required) The attribute that should be used as permalink
|
|
52
|
-
<tt>:field</tt>:: The name of your permalink column. make_permalink first checks if there is a column, default is 'permalink'.
|
|
53
|
-
<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.
|
|
54
|
-
<tt>:param_size</tt>:: [Number] Desired maximum size of the permalink, default is 50.
|
|
55
|
-
<tt>:escape</tt>:: [true|false] Do you want to escape the permalink value? (strip chars like öä?&) - actually you must do that, default is true.
|
|
56
|
-
<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.
|
|
57
|
-
<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>
|
|
58
|
-
=end
|
|
59
18
|
def make_permalink(options={})
|
|
60
19
|
options[:field] ||= "permalink"
|
|
61
|
-
options[:param] = options[:with] # :with => :login - but if we have a spcific permalink column we need to set :param to the name of that column
|
|
62
|
-
options[:escape] ||= true
|
|
63
|
-
options[:prepend_id] ||= false
|
|
64
|
-
options[:param_size] ||= 50
|
|
65
|
-
options[:validate] = true if options[:validate].nil?
|
|
66
|
-
|
|
67
|
-
# 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.
|
|
68
|
-
if !options[:prepend_id] || !options[:validate]
|
|
69
|
-
validate :validate_param_is_not_blank
|
|
70
|
-
end
|
|
71
20
|
|
|
72
|
-
|
|
73
|
-
if forbidden.is_a? Regexp
|
|
74
|
-
options[:forbidden_match] = forbidden
|
|
75
|
-
else
|
|
76
|
-
options[:forbidden_strings] = Array(forbidden).map(&:to_s)
|
|
77
|
-
end
|
|
78
|
-
end
|
|
21
|
+
self.send(:validates_uniqueness_of, options[:field])
|
|
79
22
|
|
|
80
23
|
if self.column_names.include?(options[:field].to_s)
|
|
81
24
|
options[:param] = options[:field]
|
|
82
|
-
|
|
25
|
+
before_validation(:on => :create){ save_permalink }
|
|
83
26
|
end
|
|
84
27
|
|
|
85
28
|
self.permalink_options = options
|
|
86
29
|
extend Railslove::Plugins::FindByParam::SingletonMethods
|
|
87
30
|
include Railslove::Plugins::FindByParam::InstanceMethods
|
|
88
|
-
rescue
|
|
89
|
-
|
|
31
|
+
rescue
|
|
32
|
+
# Database is not available (not a problem if we're running rake db:create or rake db:bootstrap)
|
|
90
33
|
end
|
|
91
34
|
end
|
|
92
35
|
|
|
93
36
|
module SingletonMethods
|
|
94
37
|
|
|
95
|
-
=
|
|
96
|
-
|
|
97
|
-
Search for an object by the defined permalink column. Similar to
|
|
98
|
-
+find_by_login+. Returns +nil+ if nothing is found. Accepts an options hash as
|
|
99
|
-
second parameter which is passed on to the rails finder.
|
|
100
|
-
=end
|
|
101
|
-
def find_by_param(value, args={})
|
|
38
|
+
def find_by_param(value,args={})
|
|
102
39
|
if permalink_options[:prepend_id]
|
|
103
40
|
param = "id"
|
|
104
41
|
value = value.to_i
|
|
105
42
|
else
|
|
106
|
-
param = permalink_options[:
|
|
43
|
+
param = permalink_options[:field]
|
|
107
44
|
end
|
|
108
45
|
self.send("find_by_#{param}".to_sym, value, args)
|
|
109
46
|
end
|
|
110
47
|
|
|
111
|
-
=begin rdoc
|
|
112
|
-
|
|
113
|
-
Like +find_by_param+ but raises an <tt>ActiveRecord::RecordNotFound</tt> error
|
|
114
|
-
if nothing is found - similar to find().
|
|
115
|
-
|
|
116
|
-
Accepts an options hash as second parameter which is passed on to the rails
|
|
117
|
-
finder.
|
|
118
|
-
=end
|
|
119
48
|
def find_by_param!(value, args={})
|
|
120
|
-
param = permalink_options[:
|
|
49
|
+
param = permalink_options[:field]
|
|
121
50
|
obj = find_by_param(value, args)
|
|
122
51
|
raise ::ActiveRecord::RecordNotFound unless obj
|
|
123
52
|
obj
|
|
@@ -125,77 +54,25 @@ finder.
|
|
|
125
54
|
end
|
|
126
55
|
|
|
127
56
|
module InstanceMethods
|
|
128
|
-
def to_param
|
|
129
|
-
value = self.send(permalink_options[:param]).dup.to_s.downcase rescue ""
|
|
130
|
-
''.tap do |param|
|
|
131
|
-
if value.blank?
|
|
132
|
-
param << id.to_s
|
|
133
|
-
else
|
|
134
|
-
param << "#{id}-" if permalink_options[:prepend_id]
|
|
135
|
-
param << escape_and_truncate_permalink(value)
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
57
|
|
|
140
58
|
protected
|
|
141
|
-
|
|
142
59
|
def save_permalink
|
|
143
60
|
return unless self.class.column_names.include?(permalink_options[:field].to_s)
|
|
61
|
+
return if !changed?
|
|
62
|
+
|
|
63
|
+
base_value = to_param
|
|
64
|
+
permalink_value = base_value
|
|
144
65
|
counter = 0
|
|
145
|
-
base_value = escape_and_truncate_permalink(send(permalink_options[:with])).downcase
|
|
146
|
-
permalink_value = base_value.to_s
|
|
147
66
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
conditions << self.send(self.class.primary_key.to_sym)
|
|
152
|
-
end
|
|
153
|
-
while is_forbidden?(permalink_value) or
|
|
154
|
-
self.class.count(:all, :conditions => conditions) > 0
|
|
67
|
+
begin
|
|
68
|
+
permalink_value = base_value + ((counter == 0) ? "" : "-#{counter}")
|
|
69
|
+
query = self.class.send("where", "#{permalink_options[:field]} = ?", permalink_value)
|
|
155
70
|
counter += 1
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if permalink_value.size > permalink_options[:param_size]
|
|
159
|
-
length = permalink_options[:param_size] - counter.to_s.size - 2
|
|
160
|
-
truncated_base = base_value[0..length]
|
|
161
|
-
permalink_value = "#{truncated_base}-#{counter}"
|
|
162
|
-
end
|
|
71
|
+
end while query.limit(1).present?
|
|
163
72
|
|
|
164
|
-
conditions[1] = permalink_value
|
|
165
|
-
end
|
|
166
73
|
write_attribute(permalink_options[:field], permalink_value)
|
|
167
74
|
true
|
|
168
|
-
end
|
|
169
75
|
|
|
170
|
-
def validate_param_is_not_blank
|
|
171
|
-
if self.escape_and_truncate_permalink(self.send(permalink_options[:with])).blank?
|
|
172
|
-
errors.add(permalink_options[:with],
|
|
173
|
-
"must have at least one non special character (a-z 0-9)")
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def escape_permalink(value)
|
|
178
|
-
value.to_s.parameterize
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def is_forbidden?(permalink_value)
|
|
182
|
-
is_forbidden_string?(permalink_value) ||
|
|
183
|
-
matches_forbidden_regexp?(permalink_value)
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def is_forbidden_string?(permalink_value)
|
|
187
|
-
permalink_options[:forbidden_strings] &&
|
|
188
|
-
permalink_options[:forbidden_strings].include?(permalink_value)
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
def matches_forbidden_regexp?(permalink_value)
|
|
192
|
-
permalink_options[:forbidden_match] &&
|
|
193
|
-
permalink_options[:forbidden_match] =~ permalink_value
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
def escape_and_truncate_permalink(value)
|
|
197
|
-
p = self.escape_permalink(value)[0...self.permalink_options[:param_size]]
|
|
198
|
-
p.ends_with?('-') ? p.chop : p
|
|
199
76
|
end
|
|
200
77
|
end
|
|
201
78
|
|
|
@@ -203,6 +80,18 @@ finder.
|
|
|
203
80
|
end
|
|
204
81
|
end
|
|
205
82
|
|
|
206
|
-
|
|
207
|
-
|
|
83
|
+
class ActiveRecord::Base
|
|
84
|
+
class_attribute :permalink_options
|
|
85
|
+
self.permalink_options = {:param => :id}
|
|
86
|
+
|
|
87
|
+
#default finders these are overwritten if you use make_permalink in your model
|
|
88
|
+
def self.find_by_param(value,args={})
|
|
89
|
+
find_by_id(value,args)
|
|
90
|
+
end
|
|
91
|
+
def self.find_by_param!(value,args={})
|
|
92
|
+
find(value,args)
|
|
93
|
+
end
|
|
94
|
+
|
|
208
95
|
end
|
|
96
|
+
ActiveRecord::Base.send(:include, Railslove::Plugins::FindByParam)
|
|
97
|
+
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rd_find_by_param
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 25
|
|
5
5
|
prerelease: false
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 1
|
|
9
|
-
-
|
|
10
|
-
version: 0.1.
|
|
9
|
+
- 1
|
|
10
|
+
version: 0.1.1
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Michael Bumann
|
|
@@ -16,7 +16,7 @@ autorequire:
|
|
|
16
16
|
bindir: bin
|
|
17
17
|
cert_chain: []
|
|
18
18
|
|
|
19
|
-
date: 2011-03-
|
|
19
|
+
date: 2011-03-25 00:00:00 -04:00
|
|
20
20
|
default_executable:
|
|
21
21
|
dependencies:
|
|
22
22
|
- !ruby/object:Gem::Dependency
|