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.
@@ -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