not-naughty 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +6 -0
- data/Rakefile +1 -1
- data/lib/not_naughty.rb +5 -5
- data/lib/not_naughty/class_methods.rb +78 -0
- data/lib/not_naughty/validation.rb +11 -5
- data/spec/{builder_spec.rb → class_methods_spec.rb} +11 -25
- data/spec/not_naughty_spec.rb +5 -5
- data/spec/spec_helper.rb +1 -0
- data/spec/validation_spec.rb +3 -4
- metadata +4 -4
- data/lib/not_naughty/builder.rb +0 -67
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 0.6.2 (2008-10-31)
|
2
|
+
* NotNaughty::Builder is now NotNaughty::ClassMethods
|
3
|
+
* NotNaughty::Builder::ValidationDelegator is now NotNaughty::ClassMethods::Builder
|
4
|
+
* NotNaughty::ClassMethods::Builder does not inherit from Delegation anymore, so { format :with => /rx/ } works
|
5
|
+
* NotNaughty::Validation loads validations from directories listed in load_paths
|
6
|
+
|
1
7
|
=== 0.6.1 (2008-10-10)
|
2
8
|
* builder/validation cleanups
|
3
9
|
* added gemspecs for github
|
data/Rakefile
CHANGED
data/lib/not_naughty.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'delegate'
|
2
1
|
require 'forwardable'
|
3
2
|
require 'observer'
|
4
3
|
|
@@ -12,19 +11,20 @@ require 'core_extensions'
|
|
12
11
|
module NotNaughty
|
13
12
|
require 'not_naughty/validator'
|
14
13
|
|
15
|
-
require 'not_naughty/
|
14
|
+
require 'not_naughty/class_methods'
|
16
15
|
require 'not_naughty/validation'
|
17
|
-
Validation.add_observer
|
16
|
+
Validation.add_observer ClassMethods
|
18
17
|
|
19
18
|
require 'not_naughty/violation'
|
20
19
|
require 'not_naughty/error_handler'
|
21
20
|
require 'not_naughty/instance_methods'
|
22
21
|
|
23
|
-
# Extended classes get NotNaughty::
|
22
|
+
# Extended classes get NotNaughty::ClassMethods and
|
23
|
+
# NotNaughty::InstanceMethods.
|
24
24
|
def self.extended(base)
|
25
25
|
base.instance_eval do
|
26
26
|
include InstanceMethods
|
27
|
-
extend
|
27
|
+
extend ClassMethods
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module NotNaughty
|
2
|
+
module ClassMethods
|
3
|
+
|
4
|
+
def self.update(validation) # :nodoc:
|
5
|
+
if basename = validation.name[/([^:]+)Validation$/, 1]
|
6
|
+
define_method 'validates_%s_of' % basename.downcase do |*params|
|
7
|
+
validator.add_validation(validation, *params)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# == Syntactic sugar.
|
13
|
+
#
|
14
|
+
# <b>Example:</b>
|
15
|
+
# validates { presence_of :example, :if => :reading? }
|
16
|
+
# # => validate_presence_of :example, :if => :reading?
|
17
|
+
# validates(:name) { presence and length :minimum => 6 }
|
18
|
+
# # => validates_presence_of :name
|
19
|
+
# validates_length_of :name, :minimum => 6
|
20
|
+
# validates(:temp, :if => water?) { value :lt => 100 }
|
21
|
+
# # => validates_value_of :temp, :lt => 100, :if => water?
|
22
|
+
def validates(*params, &block)
|
23
|
+
Builder.new(self, *params).instance_eval(&block)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Allows adding validations the legacy way.
|
27
|
+
def validates_each(*attributes, &block)
|
28
|
+
validator.add_validation(*attributes, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
# With this you get syntactical sugar for all descendants of Validation
|
32
|
+
# see validates for examples.
|
33
|
+
class Builder
|
34
|
+
|
35
|
+
def initialize(klass, *params) # :nodoc:
|
36
|
+
@_vd_obj = klass
|
37
|
+
@_vd_obj_opts = params.extract_options!
|
38
|
+
@_vd_obj_attrs = params
|
39
|
+
|
40
|
+
methods = ClassMethods.instance_methods(false).grep(/^validates_.+_of$/)
|
41
|
+
|
42
|
+
if @_vd_obj_attrs.empty?
|
43
|
+
for method in methods
|
44
|
+
eval <<-EOS
|
45
|
+
def self.#{ method[/^validates_(.+)$/, 1] }(*params)
|
46
|
+
params << @_vd_obj_opts.merge(params.extract_options!)
|
47
|
+
|
48
|
+
begin
|
49
|
+
@_vd_obj.__send__(:#{ method }, *params)
|
50
|
+
rescue Exception
|
51
|
+
$@.delete_if { |s| /^\\(eval\\):/ =~ s }
|
52
|
+
raise
|
53
|
+
end
|
54
|
+
end
|
55
|
+
EOS
|
56
|
+
end
|
57
|
+
else
|
58
|
+
for method in methods
|
59
|
+
eval <<-EOS
|
60
|
+
def self.#{ method[/^validates_(.+)_of$/, 1] }(*args)
|
61
|
+
params = @_vd_obj_attrs.dup
|
62
|
+
params << @_vd_obj_opts.merge(args.extract_options!)
|
63
|
+
|
64
|
+
begin
|
65
|
+
@_vd_obj.__send__(:#{ method }, *params)
|
66
|
+
rescue Exception
|
67
|
+
$@.delete_if { |s| /^\\(eval\\):/ =~ s }
|
68
|
+
raise
|
69
|
+
end
|
70
|
+
end
|
71
|
+
EOS
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -5,14 +5,20 @@ module NotNaughty
|
|
5
5
|
# See new for more information.
|
6
6
|
class Validation
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# Returns array of paths which are scanned for validations by load.
|
9
|
+
def self.load_paths
|
10
|
+
@load_paths
|
11
|
+
end
|
12
|
+
@load_paths = [File.join(%W[#{ File.dirname __FILE__ } validations])]
|
13
|
+
PATTERN = File.join %w[%s ** %s_validation.rb]
|
11
14
|
|
12
|
-
# Loads validations.
|
15
|
+
# Loads validations from load_paths.
|
13
16
|
def self.load(*validations)
|
14
17
|
validations.each do |validation|
|
15
|
-
|
18
|
+
@load_paths.each do |load_path|
|
19
|
+
pattern = PATTERN % [load_path, validation]
|
20
|
+
Dir[pattern].each { |validation_path| require validation_path }
|
21
|
+
end
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "#{ File.dirname(__FILE__) }/spec_helper.rb"
|
2
2
|
|
3
|
-
describe subject::
|
3
|
+
describe subject::ClassMethods do
|
4
4
|
|
5
5
|
before(:each) do
|
6
6
|
@validatable = Class.new(Object) do
|
@@ -10,14 +10,12 @@ describe subject::Builder do
|
|
10
10
|
def validation_state() state end
|
11
11
|
end
|
12
12
|
@validatable.validator = mock 'Validator'
|
13
|
-
@validatable.extend(subject::
|
13
|
+
@validatable.extend(subject::ClassMethods)
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should have a delegator class" do
|
17
|
-
subject::
|
18
|
-
should include('
|
19
|
-
subject::Builder.const_get('ValidationDelegator').
|
20
|
-
should < SimpleDelegator
|
17
|
+
subject::ClassMethods.constants.
|
18
|
+
should include('Builder')
|
21
19
|
end
|
22
20
|
it "should provide the :validates builder method" do
|
23
21
|
@validatable.should respond_to(:validates)
|
@@ -36,9 +34,12 @@ describe subject::Builder do
|
|
36
34
|
end
|
37
35
|
it "should add validation for :firstname and :lastname via :validates" do
|
38
36
|
@validatable.validator.should_receive(:add_validation).
|
39
|
-
with(NotNaughty::PresenceValidation, :firstname, :lastname, {})
|
37
|
+
with(NotNaughty::PresenceValidation, :firstname, :lastname, {})
|
40
38
|
@validatable.validates { presence_of :firstname, :lastname }
|
41
|
-
|
39
|
+
|
40
|
+
@validatable.validator.should_receive(:add_validation).
|
41
|
+
with(NotNaughty::FormatValidation, :firstname, :lastname, :with => /Hello World!/)
|
42
|
+
@validatable.validates(:firstname, :lastname) { format :with => /Hello World!/ }
|
42
43
|
end
|
43
44
|
it "should register validation" do
|
44
45
|
validation = Class.new(subject::Validation) do
|
@@ -54,23 +55,8 @@ describe subject::Builder do
|
|
54
55
|
end
|
55
56
|
it "should build the Validations with :validates_each" do
|
56
57
|
@validatable.validator = mock 'Validator'
|
57
|
-
@validatable.validator.
|
58
|
-
|
59
|
-
with(:a, :b)
|
60
|
-
@validatable.validates_each(:a, :b) {|o, a, v|}
|
61
|
-
|
62
|
-
pending 'expect a block'
|
63
|
-
end
|
64
|
-
it "should support :each in validates block" do
|
65
|
-
@validatable.validator = mock 'Validator'
|
66
|
-
@validatable.validator.
|
67
|
-
should_receive(:add_validation).
|
68
|
-
with(:a, :b, {})
|
69
|
-
@validatable.validates do
|
70
|
-
each(:a, :b) {|o, a, v|}
|
71
|
-
end
|
72
|
-
|
73
|
-
pending 'expect a block'
|
58
|
+
@validatable.validator.should_receive(:add_validation)
|
59
|
+
@validatable.validates_each
|
74
60
|
end
|
75
61
|
it "should raise a NoMethodError is builder method does not exist" do
|
76
62
|
lambda { @validatable.validates() { bunch_of :holy_crap } }.
|
data/spec/not_naughty_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "#{ File.dirname(__FILE__) }/spec_helper.rb"
|
2
2
|
|
3
|
-
module subject::
|
3
|
+
module subject::ClassMethods
|
4
4
|
def self.extended(base) end
|
5
5
|
end
|
6
6
|
module subject::InstanceMethods
|
@@ -12,7 +12,7 @@ describe subject do
|
|
12
12
|
it "should load necessary files" do
|
13
13
|
subject::should be_const_defined(:Validation)
|
14
14
|
subject::should be_const_defined(:Validator)
|
15
|
-
subject::should be_const_defined(:
|
15
|
+
subject::should be_const_defined(:ClassMethods)
|
16
16
|
subject::should be_const_defined(:InstanceMethods)
|
17
17
|
subject::should be_const_defined(:Violation)
|
18
18
|
end
|
@@ -31,7 +31,7 @@ describe subject do
|
|
31
31
|
it "should extend the receiver if validator is defined" do
|
32
32
|
validated = Class.new(Object)
|
33
33
|
|
34
|
-
subject::
|
34
|
+
subject::ClassMethods.should_receive(:extended).with(validated)
|
35
35
|
subject::InstanceMethods.should_receive(:included).with(validated)
|
36
36
|
|
37
37
|
validated.extend subject
|
@@ -74,9 +74,9 @@ describe subject do
|
|
74
74
|
instance.should_receive(:valid?).once.and_return(false)
|
75
75
|
instance.clone.should == false
|
76
76
|
end
|
77
|
-
it "should add
|
77
|
+
it "should add ClassMethods to Validation observers" do
|
78
78
|
subject::Validation.instance_variable_get(:@observer_peers).
|
79
|
-
should include(subject::
|
79
|
+
should include(subject::ClassMethods)
|
80
80
|
end
|
81
81
|
|
82
82
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/validation_spec.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
require "#{ File.dirname
|
1
|
+
require "#{ File.dirname __FILE__ }/spec_helper.rb"
|
2
2
|
|
3
3
|
describe subject::Validation do
|
4
4
|
|
5
5
|
it "should register validations if inherited" do
|
6
|
-
subject::
|
7
|
-
should_receive(:update).
|
6
|
+
subject::ClassMethods.
|
7
|
+
should_receive(:update).once.
|
8
8
|
with Class.new(subject::Validation)
|
9
|
-
pending 'This one kinda sucks...'
|
10
9
|
end
|
11
10
|
it "should build validations with block" do
|
12
11
|
block = proc {|o, a, v|}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: not-naughty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Florian A\xC3\x9Fmann"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-10-
|
12
|
+
date: 2008-10-31 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -36,7 +36,7 @@ files:
|
|
36
36
|
- COPYING
|
37
37
|
- README.rdoc
|
38
38
|
- Rakefile
|
39
|
-
- spec/
|
39
|
+
- spec/class_methods_spec.rb
|
40
40
|
- spec/error_handler_spec.rb
|
41
41
|
- spec/not_naughty_spec.rb
|
42
42
|
- spec/rcov.opts
|
@@ -48,7 +48,7 @@ files:
|
|
48
48
|
- spec/violation_spec.rb
|
49
49
|
- lib/core_extensions.rb
|
50
50
|
- lib/not_naughty
|
51
|
-
- lib/not_naughty/
|
51
|
+
- lib/not_naughty/class_methods.rb
|
52
52
|
- lib/not_naughty/error_handler.rb
|
53
53
|
- lib/not_naughty/instance_methods.rb
|
54
54
|
- lib/not_naughty/validation.rb
|
data/lib/not_naughty/builder.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
module NotNaughty
|
2
|
-
|
3
|
-
# == Builder that builds
|
4
|
-
#
|
5
|
-
# With this you get syntactical sugar for all descendants of Validation, see
|
6
|
-
# validates for examples.
|
7
|
-
module Builder
|
8
|
-
|
9
|
-
# Observer method that creates Validation builder methods.
|
10
|
-
#
|
11
|
-
# A Validation with the class name TestValidation will get the
|
12
|
-
# builder method <tt>validate_test_of</tt> that adds a validation via
|
13
|
-
# add_validation in the current <tt>validator</tt>.
|
14
|
-
def self.update(validation)
|
15
|
-
if basename = validation.name[/([^:]+)Validation$/, 1]
|
16
|
-
define_method 'validates_%s_of' % basename.downcase do |*params|
|
17
|
-
validator.add_validation(validation, *params)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# == Syntactic sugar.
|
23
|
-
#
|
24
|
-
# <b>Example:</b>
|
25
|
-
# validates { presence_of :example, :if => :reading? }
|
26
|
-
# # => validate_presence_of :example, :if => :reading?
|
27
|
-
# validates(:name) { presence and length :minimum => 6 }
|
28
|
-
# # => validates_presence_of :name
|
29
|
-
# validates_length_of :name, :minimum => 6
|
30
|
-
# validates(:temp, :if => water?) { value :lt => 100 }
|
31
|
-
# # => validates_value_of :temp, :lt => 100, :if => water?
|
32
|
-
def validates(*params, &block)
|
33
|
-
ValidationDelegator.new(self, *params).instance_eval(&block)
|
34
|
-
end
|
35
|
-
|
36
|
-
# Allows adding validations the legacy way.
|
37
|
-
def validates_each(*attributes, &block)
|
38
|
-
validator.add_validation(*attributes, &block)
|
39
|
-
end
|
40
|
-
|
41
|
-
class ValidationDelegator < SimpleDelegator #:nodoc:all
|
42
|
-
def initialize(receiver, *params)
|
43
|
-
@_sd_obj_opts = params.extract_options!
|
44
|
-
@_sd_obj_attributes = params
|
45
|
-
|
46
|
-
super receiver
|
47
|
-
end
|
48
|
-
def method_missing(method_sym, *params) #:nodoc:
|
49
|
-
valid = @_sd_obj_opts.merge params.extract_options!
|
50
|
-
valid = Marshal.load Marshal.dump(valid)
|
51
|
-
|
52
|
-
method_sym, params = unless @_sd_obj_attributes.empty?
|
53
|
-
[:"validates_#{ method_sym }_of", @_sd_obj_attributes + [valid]]
|
54
|
-
else
|
55
|
-
[:"validates_#{ method_sym }", params + [valid]]
|
56
|
-
end
|
57
|
-
|
58
|
-
if @_sd_obj.respond_to? method_sym
|
59
|
-
@_sd_obj.send(method_sym, *params); true
|
60
|
-
else
|
61
|
-
raise NoMethodError, "unable to evaluate ´#{method_sym}(#{ params.map {|p|p.inspect} * ','})'"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
end
|