not-naughty 0.6.1 → 0.6.2

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.
@@ -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
@@ -9,7 +9,7 @@ include FileUtils
9
9
  # Configuration
10
10
  ##############################################################################
11
11
  NAME = "not-naughty"
12
- VERS = "0.6.1"
12
+ VERS = "0.6.2"
13
13
  CLEAN.include %w[ pkg doc coverage ]
14
14
  RDOC_OPTS = [
15
15
  "--quiet",
@@ -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/builder'
14
+ require 'not_naughty/class_methods'
16
15
  require 'not_naughty/validation'
17
- Validation.add_observer Builder
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::Builder and NotNaughty::InstanceMethods.
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 Builder
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
- BASEDIR = File.dirname __FILE__
9
- # Loader pattern
10
- PATTERN = File.join BASEDIR, %w[validations ** %s_validation.rb]
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
- Dir.glob(PATTERN % validation).each { |path| require path }
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::Builder do
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::Builder)
13
+ @validatable.extend(subject::ClassMethods)
14
14
  end
15
15
 
16
16
  it "should have a delegator class" do
17
- subject::Builder.constants.
18
- should include('ValidationDelegator')
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, {}).twice
37
+ with(NotNaughty::PresenceValidation, :firstname, :lastname, {})
40
38
  @validatable.validates { presence_of :firstname, :lastname }
41
- @validatable.validates(:firstname, :lastname) { presence :name }
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
- should_receive(:add_validation).
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 } }.
@@ -1,6 +1,6 @@
1
1
  require "#{ File.dirname(__FILE__) }/spec_helper.rb"
2
2
 
3
- module subject::Builder
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(:Builder)
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::Builder.should_receive(:extended).with(validated)
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 Builder to Validation observers" do
77
+ it "should add ClassMethods to Validation observers" do
78
78
  subject::Validation.instance_variable_get(:@observer_peers).
79
- should include(subject::Builder)
79
+ should include(subject::ClassMethods)
80
80
  end
81
81
 
82
82
  end
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  require 'spec'
3
3
 
4
4
  require "#{ File.dirname __FILE__ }/../lib/not_naughty.rb"
5
+ NotNaughty::Validation.load 'format', 'presence'
5
6
 
6
7
  def subject() ::NotNaughty end
7
8
  def h(something)
@@ -1,12 +1,11 @@
1
- require "#{ File.dirname(__FILE__) }/spec_helper.rb"
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::Builder.
7
- should_receive(:update).any_number_of_times.
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.1
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-10 00:00:00 +02:00
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/builder_spec.rb
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/builder.rb
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
@@ -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