bellmyer-validates_blacklist 0.1.1 → 0.1.3
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/MIT-LICENSE +20 -0
- data/README +1 -1
- data/Rakefile +23 -0
- data/generators/blacklists/blacklists_generator.rb +11 -0
- data/generators/blacklists/templates/blacklist.yml +14 -0
- data/init.rb +2 -0
- data/lib/bellmyer/validates_blacklist.rb +68 -0
- data/test/config/blacklists/friend_with_attribute_message_blacklist.yml +11 -0
- data/test/config/blacklists/friend_with_blacklist_blacklist.yml +20 -0
- data/test/config/blacklists/friend_with_blank_blacklist_blacklist.yml +1 -0
- data/test/config/blacklists/friend_with_custom_message_blacklist.yml +11 -0
- data/test/test_helper.rb +6 -0
- data/test/validates_blacklist_test.rb +178 -0
- data/validates_blacklist.gemspec +15 -5
- metadata +24 -4
- data/lib/active_record/validates/blacklist.rb +0 -27
- data/lib/bellmyer-validates_blacklist.rb +0 -2
- data/test/blacklist_test.rb +0 -332
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [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.
|
data/README
CHANGED
@@ -120,7 +120,7 @@ The only limits are your imagination, and my forethought. You can even specify
|
|
120
120
|
the error message that is generated:
|
121
121
|
|
122
122
|
email:
|
123
|
-
- [
|
123
|
+
- [stinky_pete@aol.com, cannot be greasy pete from biology]
|
124
124
|
|
125
125
|
age:
|
126
126
|
- [>25, cannot be a pervert]
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
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 validates_blacklist 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 validates_blacklist plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'ValidatesBlacklist'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class BlacklistsGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
m.directory 'config/blacklists'
|
5
|
+
|
6
|
+
Dir["#{RAILS_ROOT}/app/models/*.rb"].each do |file|
|
7
|
+
m.file 'blacklist.yml', "config/blacklists/#{File.basename(file, '.rb')}_blacklist.yml", :collision => :skip
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Bellmyer
|
2
|
+
module ValidatesBlacklist
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
def validates_blacklist(options = {})
|
6
|
+
options.reverse_merge!(
|
7
|
+
:message => 'is not allowed.',
|
8
|
+
:attributes => {}
|
9
|
+
)
|
10
|
+
|
11
|
+
unless included_modules.include? InstanceMethods
|
12
|
+
class_inheritable_accessor :options
|
13
|
+
class_inheritable_accessor :model
|
14
|
+
|
15
|
+
extend ClassMethods
|
16
|
+
include InstanceMethods
|
17
|
+
|
18
|
+
validate :model_blacklists
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
self.options = options
|
23
|
+
self.model = self.to_s.underscore
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
def blacklist
|
28
|
+
puts "blacklisted!"
|
29
|
+
end
|
30
|
+
|
31
|
+
def unblacklist
|
32
|
+
puts "Removed from blacklist."
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module InstanceMethods
|
37
|
+
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def model_blacklists
|
42
|
+
blacklist = "#{RAILS_ROOT}/config/blacklists/#{self.class.to_s.underscore}_blacklist.yml"
|
43
|
+
|
44
|
+
# Load blacklist #
|
45
|
+
if attributes = File.open(blacklist){|f| YAML::load(f)}
|
46
|
+
# Cycle through attributes #
|
47
|
+
attributes.each do |attribute, stops|
|
48
|
+
attribute = attribute.to_sym
|
49
|
+
|
50
|
+
stops.each do |stop|
|
51
|
+
stop_name = stop.is_a?(Array) ? stop.first : stop
|
52
|
+
stop_message = stop.is_a?(Array) ? stop.last : self.options[:attributes][attribute] || self.options[:message]
|
53
|
+
|
54
|
+
# regexp #
|
55
|
+
if !self.send(attribute).nil? && stop_name =~ /^\//
|
56
|
+
errors.add(attribute, stop_message) if eval("self.#{attribute} =~ #{stop_name}")
|
57
|
+
elsif !self.send(attribute).nil? && stop_name =~ /^(\<|\>|!|=)/
|
58
|
+
errors.add(attribute, stop_message) if eval("self.#{attribute} #{stop_name}")
|
59
|
+
else
|
60
|
+
errors.add(attribute, stop_message) if self.send(attribute).to_s == stop_name
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
name:
|
2
|
+
- Stinky Pete
|
3
|
+
- /Pete/
|
4
|
+
- [Vanessa, is not allowed after ditching my b-day party]
|
5
|
+
- ['=~ /smurf/i', is not allowed to be a smurf!]
|
6
|
+
|
7
|
+
email:
|
8
|
+
- stinky_pete@gmail.com
|
9
|
+
- [/@aol\.com$/, is banned until they stop sending me CD\'s]
|
10
|
+
|
11
|
+
age:
|
12
|
+
- [< 14, is too young to party.]
|
13
|
+
- ['> 25', is too old and pervy!]
|
14
|
+
|
15
|
+
net_worth:
|
16
|
+
- ['<= 50_000', is too poor.]
|
17
|
+
- ['>= 150_000', is too rich.]
|
18
|
+
|
19
|
+
school:
|
20
|
+
- ['!~ /Valley/', is not Valley High School!]
|
@@ -0,0 +1 @@
|
|
1
|
+
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'active_record'
|
4
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
5
|
+
require File.dirname(__FILE__) + '/../init'
|
6
|
+
|
7
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
|
8
|
+
|
9
|
+
# AR keeps printing annoying schema statements
|
10
|
+
$stdout = StringIO.new
|
11
|
+
|
12
|
+
RAILS_ROOT = File.dirname(__FILE__)
|
13
|
+
|
14
|
+
def setup_db
|
15
|
+
ActiveRecord::Schema.define(:version => 1) do
|
16
|
+
create_table :friends do |t|
|
17
|
+
t.string :name
|
18
|
+
t.string :email
|
19
|
+
t.integer :age
|
20
|
+
t.integer :net_worth
|
21
|
+
t.string :school
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def teardown_db
|
27
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
28
|
+
ActiveRecord::Base.connection.drop_table(table)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Friend < ActiveRecord::Base
|
33
|
+
end
|
34
|
+
|
35
|
+
class FriendWithBlacklist < Friend
|
36
|
+
validates_blacklist
|
37
|
+
end
|
38
|
+
|
39
|
+
class FriendWithBlacklistTest < Test::Unit::TestCase
|
40
|
+
def setup
|
41
|
+
setup_db
|
42
|
+
end
|
43
|
+
|
44
|
+
def teardown
|
45
|
+
teardown_db
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_should_fail_validation_on_exact_string_match
|
49
|
+
friend = FriendWithBlacklist.new(:name => 'Stinky Pete')
|
50
|
+
assert !friend.valid?
|
51
|
+
assert friend.errors.invalid?(:name)
|
52
|
+
assert friend.errors.on(:name).include?("is not allowed.")
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_should_fail_validation_on_regexp_match
|
56
|
+
friend = FriendWithBlacklist.new(:name => 'Handsome Pete')
|
57
|
+
assert !friend.valid?
|
58
|
+
assert friend.errors.invalid?(:name)
|
59
|
+
assert friend.errors.on(:name).include?("is not allowed.")
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_should_fail_validation_on_custom_message
|
63
|
+
friend = FriendWithBlacklist.new(:name => 'Vanessa')
|
64
|
+
assert !friend.valid?
|
65
|
+
assert friend.errors.invalid?(:name)
|
66
|
+
assert friend.errors.on(:name).include?("is not allowed after ditching my b-day party")
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_should_fail_validation_on_less_than_match
|
70
|
+
friend = FriendWithBlacklist.new(:age => 12)
|
71
|
+
assert !friend.valid?
|
72
|
+
assert friend.errors.invalid?(:age)
|
73
|
+
assert friend.errors.on(:age).include?("is too young to party.")
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_should_fail_validation_on_greater_than_match
|
77
|
+
friend = FriendWithBlacklist.new(:age => 55)
|
78
|
+
assert !friend.valid?
|
79
|
+
assert friend.errors.invalid?(:age)
|
80
|
+
assert friend.errors.on(:age).include?("is too old and pervy!")
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_should_fail_validation_on_greater_than_or_equal_match
|
84
|
+
friend = FriendWithBlacklist.new(:net_worth => 150_000)
|
85
|
+
assert !friend.valid?
|
86
|
+
assert friend.errors.invalid?(:net_worth)
|
87
|
+
assert friend.errors.on(:net_worth).include?('is too rich.')
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_should_fail_validation_on_less_than_or_equal_match
|
91
|
+
friend = FriendWithBlacklist.new(:net_worth => 50_000)
|
92
|
+
assert !friend.valid?
|
93
|
+
assert friend.errors.invalid?(:net_worth)
|
94
|
+
assert friend.errors.on(:net_worth).include?('is too poor.')
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_should_fail_validation_on_explicit_nonregexp
|
98
|
+
friend = FriendWithBlacklist.new(:school => 'Mouthbreather Academy')
|
99
|
+
assert !friend.valid?
|
100
|
+
assert friend.errors.invalid?(:school)
|
101
|
+
assert friend.errors.on(:school).include?("is not Valley High School!")
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_should_fail_validation_on_explicit_regexp
|
105
|
+
friend = FriendWithBlacklist.new(:name => 'Papa Smurf')
|
106
|
+
assert !friend.valid?
|
107
|
+
assert friend.errors.invalid?(:name)
|
108
|
+
assert friend.errors.on(:name).include?("is not allowed to be a smurf!")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class FriendWithCustomMessage < Friend
|
113
|
+
validates_blacklist :message => "has left the building."
|
114
|
+
end
|
115
|
+
|
116
|
+
class FriendWithCustomMessageTest < Test::Unit::TestCase
|
117
|
+
def setup
|
118
|
+
setup_db
|
119
|
+
end
|
120
|
+
|
121
|
+
def teardown
|
122
|
+
teardown_db
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_global_custom_message_fails_validation_on_exact_string_match
|
126
|
+
friend = FriendWithCustomMessage.new(:name => 'Stinky Pete')
|
127
|
+
assert !friend.valid?
|
128
|
+
assert friend.errors.invalid?(:name)
|
129
|
+
assert friend.errors.on(:name).include?("has left the building.")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class FriendWithAttributeMessage < Friend
|
134
|
+
validates_blacklist :message => "has left the building.", :attributes => {:email => 'looks spammy'}
|
135
|
+
end
|
136
|
+
|
137
|
+
class FriendWithAttributeMessageTest < Test::Unit::TestCase
|
138
|
+
def setup
|
139
|
+
setup_db
|
140
|
+
end
|
141
|
+
|
142
|
+
def teardown
|
143
|
+
teardown_db
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_attribute_message_fails_validation_on_exact_string_match_with_global_message
|
147
|
+
friend = FriendWithAttributeMessage.new(:name => 'Stinky Pete')
|
148
|
+
assert !friend.valid?
|
149
|
+
assert friend.errors.invalid?(:name)
|
150
|
+
assert friend.errors.on(:name).include?("has left the building.")
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_attribute_message_fails_validation_on_exact_string_match_with_attrib_message
|
154
|
+
friend = FriendWithAttributeMessage.new(:email => 'stinky_pete@gmail.com')
|
155
|
+
assert !friend.valid?
|
156
|
+
assert friend.errors.invalid?(:email)
|
157
|
+
assert friend.errors.on(:email).include?('looks spammy')
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class FriendWithBlankBlacklist < Friend
|
162
|
+
validates_blacklist
|
163
|
+
end
|
164
|
+
|
165
|
+
class FriendWithBlankBlacklistTest < Test::Unit::TestCase
|
166
|
+
def setup
|
167
|
+
setup_db
|
168
|
+
end
|
169
|
+
|
170
|
+
def teardown
|
171
|
+
teardown_db
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_should_not_fail
|
175
|
+
friend = FriendWithBlankBlacklist.new(:name => 'Stinky Pete')
|
176
|
+
assert friend.valid?
|
177
|
+
end
|
178
|
+
end
|
data/validates_blacklist.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'validates_blacklist'
|
3
|
-
s.version = '0.1.
|
3
|
+
s.version = '0.1.3'
|
4
4
|
s.date = '2009-08-26'
|
5
5
|
|
6
6
|
s.summary = "Allows models to be validated against yaml-based blacklists"
|
@@ -15,14 +15,24 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.extra_rdoc_files = ["README"]
|
16
16
|
|
17
17
|
s.add_dependency 'rails', ['>= 2.1']
|
18
|
+
s.add_dependency 'yaml'
|
18
19
|
|
19
20
|
s.files = [
|
21
|
+
"init.rb",
|
22
|
+
"MIT-LICENSE",
|
23
|
+
"Rakefile",
|
20
24
|
"README",
|
21
25
|
"validates_blacklist.gemspec",
|
22
|
-
"
|
23
|
-
"
|
26
|
+
"generators/blacklists/templates/blacklist.yml",
|
27
|
+
"generators/blacklists/blacklists_generator.rb",
|
28
|
+
"lib/bellmyer/validates_blacklist.rb",
|
29
|
+
"test/config/blacklists/friend_with_attribute_message_blacklist.yml",
|
30
|
+
"test/config/blacklists/friend_with_blacklist_blacklist.yml",
|
31
|
+
"test/config/blacklists/friend_with_blank_blacklist_blacklist.yml",
|
32
|
+
"test/config/blacklists/friend_with_custom_message_blacklist.yml",
|
33
|
+
"test/test_helper.rb",
|
34
|
+
"test/validates_blacklist_test.rb"
|
24
35
|
]
|
25
36
|
|
26
|
-
s.test_files = ["test/
|
27
|
-
|
37
|
+
s.test_files = ["test/validates_blacklist_test.rb"]
|
28
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bellmyer-validates_blacklist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jaime Bellmyer
|
@@ -22,6 +22,16 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: "2.1"
|
24
24
|
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: yaml
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
25
35
|
description: ""
|
26
36
|
email: ruby@bellmyer.com
|
27
37
|
executables: []
|
@@ -31,10 +41,20 @@ extensions: []
|
|
31
41
|
extra_rdoc_files:
|
32
42
|
- README
|
33
43
|
files:
|
44
|
+
- init.rb
|
45
|
+
- MIT-LICENSE
|
46
|
+
- Rakefile
|
34
47
|
- README
|
35
48
|
- validates_blacklist.gemspec
|
36
|
-
-
|
37
|
-
-
|
49
|
+
- generators/blacklists/templates/blacklist.yml
|
50
|
+
- generators/blacklists/blacklists_generator.rb
|
51
|
+
- lib/bellmyer/validates_blacklist.rb
|
52
|
+
- test/config/blacklists/friend_with_attribute_message_blacklist.yml
|
53
|
+
- test/config/blacklists/friend_with_blacklist_blacklist.yml
|
54
|
+
- test/config/blacklists/friend_with_blank_blacklist_blacklist.yml
|
55
|
+
- test/config/blacklists/friend_with_custom_message_blacklist.yml
|
56
|
+
- test/test_helper.rb
|
57
|
+
- test/validates_blacklist_test.rb
|
38
58
|
has_rdoc: true
|
39
59
|
homepage: http://github.com/bellmyer/validates_blacklist
|
40
60
|
licenses:
|
@@ -64,4 +84,4 @@ signing_key:
|
|
64
84
|
specification_version: 2
|
65
85
|
summary: Allows models to be validated against yaml-based blacklists
|
66
86
|
test_files:
|
67
|
-
- test/
|
87
|
+
- test/validates_blacklist_test.rb
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Validates #:nodoc:
|
3
|
-
module Blacklist #:nodoc:
|
4
|
-
def self.included(base)
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
end
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
validates_blacklist(options = {})
|
10
|
-
options.reverse_merge!(:message => 'is not allowed')
|
11
|
-
|
12
|
-
include ActiveRecord::Validates::Blacklist::InstanceMethods
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
module InstanceMethods
|
17
|
-
def blacklist(attribute, value, message = nil)
|
18
|
-
puts "blacklisted!"
|
19
|
-
end
|
20
|
-
|
21
|
-
def unblacklist(attribute, value)
|
22
|
-
puts "unblacklisted!"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
data/test/blacklist_test.rb
DELETED
@@ -1,332 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
gem 'activerecord', '>= 1.15.4.7794'
|
5
|
-
require 'active_record'
|
6
|
-
|
7
|
-
require "#{File.dirname(__FILE__)}/../init"
|
8
|
-
|
9
|
-
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
|
10
|
-
|
11
|
-
def setup_db
|
12
|
-
ActiveRecord::Schema.define(:version => 1) do
|
13
|
-
create_table :mixins do |t|
|
14
|
-
t.column :pos, :integer
|
15
|
-
t.column :parent_id, :integer
|
16
|
-
t.column :created_at, :datetime
|
17
|
-
t.column :updated_at, :datetime
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def teardown_db
|
23
|
-
ActiveRecord::Base.connection.tables.each do |table|
|
24
|
-
ActiveRecord::Base.connection.drop_table(table)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class Mixin < ActiveRecord::Base
|
29
|
-
end
|
30
|
-
|
31
|
-
class ListMixin < Mixin
|
32
|
-
acts_as_list :column => "pos", :scope => :parent
|
33
|
-
|
34
|
-
def self.table_name() "mixins" end
|
35
|
-
end
|
36
|
-
|
37
|
-
class ListMixinSub1 < ListMixin
|
38
|
-
end
|
39
|
-
|
40
|
-
class ListMixinSub2 < ListMixin
|
41
|
-
end
|
42
|
-
|
43
|
-
class ListWithStringScopeMixin < ActiveRecord::Base
|
44
|
-
acts_as_list :column => "pos", :scope => 'parent_id = #{parent_id}'
|
45
|
-
|
46
|
-
def self.table_name() "mixins" end
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
class ListTest < Test::Unit::TestCase
|
51
|
-
|
52
|
-
def setup
|
53
|
-
setup_db
|
54
|
-
(1..4).each { |counter| ListMixin.create! :pos => counter, :parent_id => 5 }
|
55
|
-
end
|
56
|
-
|
57
|
-
def teardown
|
58
|
-
teardown_db
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_reordering
|
62
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
63
|
-
|
64
|
-
ListMixin.find(2).move_lower
|
65
|
-
assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
66
|
-
|
67
|
-
ListMixin.find(2).move_higher
|
68
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
69
|
-
|
70
|
-
ListMixin.find(1).move_to_bottom
|
71
|
-
assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
72
|
-
|
73
|
-
ListMixin.find(1).move_to_top
|
74
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
75
|
-
|
76
|
-
ListMixin.find(2).move_to_bottom
|
77
|
-
assert_equal [1, 3, 4, 2], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
78
|
-
|
79
|
-
ListMixin.find(4).move_to_top
|
80
|
-
assert_equal [4, 1, 3, 2], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_move_to_bottom_with_next_to_last_item
|
84
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
85
|
-
ListMixin.find(3).move_to_bottom
|
86
|
-
assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_next_prev
|
90
|
-
assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
|
91
|
-
assert_nil ListMixin.find(1).higher_item
|
92
|
-
assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
|
93
|
-
assert_nil ListMixin.find(4).lower_item
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_injection
|
97
|
-
item = ListMixin.new(:parent_id => 1)
|
98
|
-
assert_equal "parent_id = 1", item.scope_condition
|
99
|
-
assert_equal "pos", item.position_column
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_insert
|
103
|
-
new = ListMixin.create(:parent_id => 20)
|
104
|
-
assert_equal 1, new.pos
|
105
|
-
assert new.first?
|
106
|
-
assert new.last?
|
107
|
-
|
108
|
-
new = ListMixin.create(:parent_id => 20)
|
109
|
-
assert_equal 2, new.pos
|
110
|
-
assert !new.first?
|
111
|
-
assert new.last?
|
112
|
-
|
113
|
-
new = ListMixin.create(:parent_id => 20)
|
114
|
-
assert_equal 3, new.pos
|
115
|
-
assert !new.first?
|
116
|
-
assert new.last?
|
117
|
-
|
118
|
-
new = ListMixin.create(:parent_id => 0)
|
119
|
-
assert_equal 1, new.pos
|
120
|
-
assert new.first?
|
121
|
-
assert new.last?
|
122
|
-
end
|
123
|
-
|
124
|
-
def test_insert_at
|
125
|
-
new = ListMixin.create(:parent_id => 20)
|
126
|
-
assert_equal 1, new.pos
|
127
|
-
|
128
|
-
new = ListMixin.create(:parent_id => 20)
|
129
|
-
assert_equal 2, new.pos
|
130
|
-
|
131
|
-
new = ListMixin.create(:parent_id => 20)
|
132
|
-
assert_equal 3, new.pos
|
133
|
-
|
134
|
-
new4 = ListMixin.create(:parent_id => 20)
|
135
|
-
assert_equal 4, new4.pos
|
136
|
-
|
137
|
-
new4.insert_at(3)
|
138
|
-
assert_equal 3, new4.pos
|
139
|
-
|
140
|
-
new.reload
|
141
|
-
assert_equal 4, new.pos
|
142
|
-
|
143
|
-
new.insert_at(2)
|
144
|
-
assert_equal 2, new.pos
|
145
|
-
|
146
|
-
new4.reload
|
147
|
-
assert_equal 4, new4.pos
|
148
|
-
|
149
|
-
new5 = ListMixin.create(:parent_id => 20)
|
150
|
-
assert_equal 5, new5.pos
|
151
|
-
|
152
|
-
new5.insert_at(1)
|
153
|
-
assert_equal 1, new5.pos
|
154
|
-
|
155
|
-
new4.reload
|
156
|
-
assert_equal 5, new4.pos
|
157
|
-
end
|
158
|
-
|
159
|
-
def test_delete_middle
|
160
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
161
|
-
|
162
|
-
ListMixin.find(2).destroy
|
163
|
-
|
164
|
-
assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
165
|
-
|
166
|
-
assert_equal 1, ListMixin.find(1).pos
|
167
|
-
assert_equal 2, ListMixin.find(3).pos
|
168
|
-
assert_equal 3, ListMixin.find(4).pos
|
169
|
-
|
170
|
-
ListMixin.find(1).destroy
|
171
|
-
|
172
|
-
assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
173
|
-
|
174
|
-
assert_equal 1, ListMixin.find(3).pos
|
175
|
-
assert_equal 2, ListMixin.find(4).pos
|
176
|
-
end
|
177
|
-
|
178
|
-
def test_with_string_based_scope
|
179
|
-
new = ListWithStringScopeMixin.create(:parent_id => 500)
|
180
|
-
assert_equal 1, new.pos
|
181
|
-
assert new.first?
|
182
|
-
assert new.last?
|
183
|
-
end
|
184
|
-
|
185
|
-
def test_nil_scope
|
186
|
-
new1, new2, new3 = ListMixin.create, ListMixin.create, ListMixin.create
|
187
|
-
new2.move_higher
|
188
|
-
assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
|
189
|
-
end
|
190
|
-
|
191
|
-
|
192
|
-
def test_remove_from_list_should_then_fail_in_list?
|
193
|
-
assert_equal true, ListMixin.find(1).in_list?
|
194
|
-
ListMixin.find(1).remove_from_list
|
195
|
-
assert_equal false, ListMixin.find(1).in_list?
|
196
|
-
end
|
197
|
-
|
198
|
-
def test_remove_from_list_should_set_position_to_nil
|
199
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
200
|
-
|
201
|
-
ListMixin.find(2).remove_from_list
|
202
|
-
|
203
|
-
assert_equal [2, 1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
204
|
-
|
205
|
-
assert_equal 1, ListMixin.find(1).pos
|
206
|
-
assert_equal nil, ListMixin.find(2).pos
|
207
|
-
assert_equal 2, ListMixin.find(3).pos
|
208
|
-
assert_equal 3, ListMixin.find(4).pos
|
209
|
-
end
|
210
|
-
|
211
|
-
def test_remove_before_destroy_does_not_shift_lower_items_twice
|
212
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
213
|
-
|
214
|
-
ListMixin.find(2).remove_from_list
|
215
|
-
ListMixin.find(2).destroy
|
216
|
-
|
217
|
-
assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
218
|
-
|
219
|
-
assert_equal 1, ListMixin.find(1).pos
|
220
|
-
assert_equal 2, ListMixin.find(3).pos
|
221
|
-
assert_equal 3, ListMixin.find(4).pos
|
222
|
-
end
|
223
|
-
|
224
|
-
end
|
225
|
-
|
226
|
-
class ListSubTest < Test::Unit::TestCase
|
227
|
-
|
228
|
-
def setup
|
229
|
-
setup_db
|
230
|
-
(1..4).each { |i| ((i % 2 == 1) ? ListMixinSub1 : ListMixinSub2).create! :pos => i, :parent_id => 5000 }
|
231
|
-
end
|
232
|
-
|
233
|
-
def teardown
|
234
|
-
teardown_db
|
235
|
-
end
|
236
|
-
|
237
|
-
def test_reordering
|
238
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
239
|
-
|
240
|
-
ListMixin.find(2).move_lower
|
241
|
-
assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
242
|
-
|
243
|
-
ListMixin.find(2).move_higher
|
244
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
245
|
-
|
246
|
-
ListMixin.find(1).move_to_bottom
|
247
|
-
assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
248
|
-
|
249
|
-
ListMixin.find(1).move_to_top
|
250
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
251
|
-
|
252
|
-
ListMixin.find(2).move_to_bottom
|
253
|
-
assert_equal [1, 3, 4, 2], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
254
|
-
|
255
|
-
ListMixin.find(4).move_to_top
|
256
|
-
assert_equal [4, 1, 3, 2], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
257
|
-
end
|
258
|
-
|
259
|
-
def test_move_to_bottom_with_next_to_last_item
|
260
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
261
|
-
ListMixin.find(3).move_to_bottom
|
262
|
-
assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
263
|
-
end
|
264
|
-
|
265
|
-
def test_next_prev
|
266
|
-
assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
|
267
|
-
assert_nil ListMixin.find(1).higher_item
|
268
|
-
assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
|
269
|
-
assert_nil ListMixin.find(4).lower_item
|
270
|
-
end
|
271
|
-
|
272
|
-
def test_injection
|
273
|
-
item = ListMixin.new("parent_id"=>1)
|
274
|
-
assert_equal "parent_id = 1", item.scope_condition
|
275
|
-
assert_equal "pos", item.position_column
|
276
|
-
end
|
277
|
-
|
278
|
-
def test_insert_at
|
279
|
-
new = ListMixin.create("parent_id" => 20)
|
280
|
-
assert_equal 1, new.pos
|
281
|
-
|
282
|
-
new = ListMixinSub1.create("parent_id" => 20)
|
283
|
-
assert_equal 2, new.pos
|
284
|
-
|
285
|
-
new = ListMixinSub2.create("parent_id" => 20)
|
286
|
-
assert_equal 3, new.pos
|
287
|
-
|
288
|
-
new4 = ListMixin.create("parent_id" => 20)
|
289
|
-
assert_equal 4, new4.pos
|
290
|
-
|
291
|
-
new4.insert_at(3)
|
292
|
-
assert_equal 3, new4.pos
|
293
|
-
|
294
|
-
new.reload
|
295
|
-
assert_equal 4, new.pos
|
296
|
-
|
297
|
-
new.insert_at(2)
|
298
|
-
assert_equal 2, new.pos
|
299
|
-
|
300
|
-
new4.reload
|
301
|
-
assert_equal 4, new4.pos
|
302
|
-
|
303
|
-
new5 = ListMixinSub1.create("parent_id" => 20)
|
304
|
-
assert_equal 5, new5.pos
|
305
|
-
|
306
|
-
new5.insert_at(1)
|
307
|
-
assert_equal 1, new5.pos
|
308
|
-
|
309
|
-
new4.reload
|
310
|
-
assert_equal 5, new4.pos
|
311
|
-
end
|
312
|
-
|
313
|
-
def test_delete_middle
|
314
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
315
|
-
|
316
|
-
ListMixin.find(2).destroy
|
317
|
-
|
318
|
-
assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
319
|
-
|
320
|
-
assert_equal 1, ListMixin.find(1).pos
|
321
|
-
assert_equal 2, ListMixin.find(3).pos
|
322
|
-
assert_equal 3, ListMixin.find(4).pos
|
323
|
-
|
324
|
-
ListMixin.find(1).destroy
|
325
|
-
|
326
|
-
assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
327
|
-
|
328
|
-
assert_equal 1, ListMixin.find(3).pos
|
329
|
-
assert_equal 2, ListMixin.find(4).pos
|
330
|
-
end
|
331
|
-
|
332
|
-
end
|