isbn_validation 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -21,9 +21,9 @@ support, please use v0.1.2.
21
21
  ## Example
22
22
 
23
23
  class Book < ActiveRecord::Base
24
- validates_isbn :isbn
25
- validates_isbn :isbn10, :with => isbn10
26
- validates_isbn :isbn13, :with => isbn13
24
+ validates :isbn, :isbn_format => true
25
+ validates :isbn10, :isbn_format => { :with => :isbn10 }
26
+ validates :isbn13, :isbn_format => { :with => :isbn13 }
27
27
  end
28
28
 
29
29
  ------
@@ -6,9 +6,9 @@ require "isbn_validation/version"
6
6
  # but this behavior can be modified using configuration options (as shown below).
7
7
  #
8
8
  # class Book < ActiveRecord::Base
9
- # validates_isbn :isbn
10
- # #validates_isbn :isbn10, :with => :isbn10
11
- # #validates_isbn :isbn13, :with => :isbn13
9
+ # validates :isbn, :isbn_format => true
10
+ # # validates_isbn :isbn10, :isbn_format => { :with => :isbn10 }
11
+ # # validates_isbn :isbn13, :isbn_format => { :with => :isbn13 }
12
12
  # end
13
13
  #
14
14
  # Configuration options:
@@ -23,75 +23,84 @@ require "isbn_validation/version"
23
23
  # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
24
24
  # not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
25
25
  # method, proc or string should return or evaluate to a true or false value.
26
- module Zerosum
27
- module ValidationExtensions
28
- module IsbnValidation
29
- ISBN10_REGEX = /^(?:\d[\ |-]?){9}[\d|X]$/
30
- ISBN13_REGEX = /^(?:\d[\ |-]?){13}$/
26
+ module ValidationExtensions
27
+ module IsbnValidation
28
+ ISBN10_REGEX = /^(?:\d[\ |-]?){9}[\d|X]$/
29
+ ISBN13_REGEX = /^(?:\d[\ |-]?){13}$/
31
30
 
32
- def self.included(base)
33
- base.extend(ClassMethods)
31
+ def self.included(base)
32
+ base.extend(ClassMethods)
33
+ end
34
+
35
+ class IsbnFormatValidator < ActiveModel::EachValidator
36
+ def initialize(options)
37
+ options[:message] ||= "is not a valid ISBN code"
38
+ options[:allow_nil] ||= false
39
+ options[:allow_blank] ||= false
40
+ super(options)
34
41
  end
35
42
 
36
- module ClassMethods
37
- def validates_isbn(*attr_names)
38
- configuration = {
39
- :message => "is not a valid ISBN code"
40
- }
43
+ def validate_each(record, attribute, value)
44
+ valid_isbn = case options[:with]
45
+ when :isbn10
46
+ validate_with_isbn10(value)
47
+ when :isbn13
48
+ validate_with_isbn13(value)
49
+ else
50
+ validate_with_isbn10(value) || validate_with_isbn13(value)
51
+ end
41
52
 
42
- configuration.update(attr_names.extract_options!)
43
- validates_each(attr_names, configuration) do |record, attr_name, value|
44
- valid = case configuration[:with]
45
- when :isbn10
46
- validate_with_isbn10(value)
47
- when :isbn13
48
- validate_with_isbn13(value)
49
- else
50
- validate_with_isbn10(value) || validate_with_isbn13(value)
51
- end
52
- record.errors.add(attr_name, configuration[:message]) unless valid
53
- end
53
+ unless valid_isbn || (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
54
+ record.errors.add(attribute, options[:message])
54
55
  end
56
+ end
55
57
 
56
- def validate_with_isbn10(isbn) #:nodoc:
57
- if (isbn || '').match(ISBN10_REGEX)
58
- isbn_values = isbn.upcase.gsub(/\ |-/, '').split('')
59
- check_digit = isbn_values.pop # last digit is check digit
60
- check_digit = (check_digit == 'X') ? 10 : check_digit.to_i
58
+ private
61
59
 
62
- sum = 0
63
- isbn_values.each_with_index do |value, index|
64
- sum += (index + 1) * value.to_i
65
- end
60
+ def validate_with_isbn10(isbn) #:nodoc:
61
+ if (isbn || '').match(ISBN10_REGEX)
62
+ isbn_values = isbn.upcase.gsub(/\ |-/, '').split('')
63
+ check_digit = isbn_values.pop # last digit is check digit
64
+ check_digit = (check_digit == 'X') ? 10 : check_digit.to_i
66
65
 
67
- (sum % 11) == check_digit
68
- else
69
- false
66
+ sum = 0
67
+ isbn_values.each_with_index do |value, index|
68
+ sum += (index + 1) * value.to_i
70
69
  end
70
+
71
+ (sum % 11) == check_digit
72
+ else
73
+ false
71
74
  end
75
+ end
72
76
 
73
- def validate_with_isbn13(isbn) #:nodoc:
74
- if (isbn || '').match(ISBN13_REGEX)
75
- isbn_values = isbn.upcase.gsub(/\ |-/, '').split('')
76
- check_digit = isbn_values.pop.to_i # last digit is check digit
77
+ def validate_with_isbn13(isbn) #:nodoc:
78
+ if (isbn || '').match(ISBN13_REGEX)
79
+ isbn_values = isbn.upcase.gsub(/\ |-/, '').split('')
80
+ check_digit = isbn_values.pop.to_i # last digit is check digit
77
81
 
78
- sum = 0
79
- isbn_values.each_with_index do |value, index|
80
- multiplier = (index % 2 == 0) ? 1 : 3
81
- sum += multiplier * value.to_i
82
- end
82
+ sum = 0
83
+ isbn_values.each_with_index do |value, index|
84
+ multiplier = (index % 2 == 0) ? 1 : 3
85
+ sum += multiplier * value.to_i
86
+ end
83
87
 
84
- result = (10 - (sum % 10))
85
- result = 0 if result == 10
88
+ result = (10 - (sum % 10))
89
+ result = 0 if result == 10
86
90
 
87
- result == check_digit
88
- else
89
- false
90
- end
91
+ result == check_digit
92
+ else
93
+ false
91
94
  end
92
95
  end
93
96
  end
97
+
98
+ module ClassMethods
99
+ def validates_isbn(*attr_names)
100
+ validates_with IsbnFormatValidator, _merge_attributes(attr_names)
101
+ end
102
+ end
94
103
  end
95
104
  end
96
105
 
97
- ActiveRecord::Base.send(:include, Zerosum::ValidationExtensions::IsbnValidation)
106
+ ActiveRecord::Base.send(:include, ValidationExtensions::IsbnValidation)
@@ -1,3 +1,3 @@
1
1
  module IsbnValidation
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -2,96 +2,119 @@ require File.dirname(__FILE__) + '/test_helper'
2
2
  require File.dirname(__FILE__) + '/models'
3
3
 
4
4
  class IsbnValidationTest < Test::Unit::TestCase
5
- def setup
6
- @book = Book.new
7
- end
8
-
9
5
  def test_isbn10_should_match_regex
10
6
  isbn = '1590599934'
11
- assert isbn.match(Zerosum::ValidationExtensions::IsbnValidation::ISBN10_REGEX)
7
+ assert isbn.match(ValidationExtensions::IsbnValidation::ISBN10_REGEX)
12
8
  end
13
9
 
14
10
  def test_isbn10_should_not_match_regex
15
11
  isbn = 'abc123ab3344'
16
- assert !isbn.match(Zerosum::ValidationExtensions::IsbnValidation::ISBN10_REGEX)
12
+ assert !isbn.match(ValidationExtensions::IsbnValidation::ISBN10_REGEX)
17
13
  end
18
14
 
19
15
  def test_isbn10_with_dashes_and_spaces_should_match_regex
20
16
  isbn = '159-059 9934'
21
- assert isbn.match(Zerosum::ValidationExtensions::IsbnValidation::ISBN10_REGEX)
17
+ assert isbn.match(ValidationExtensions::IsbnValidation::ISBN10_REGEX)
22
18
  end
23
19
 
24
20
  def test_isbn13_should_match_regex
25
21
  isbn = '9781590599938'
26
- assert isbn.match(Zerosum::ValidationExtensions::IsbnValidation::ISBN13_REGEX)
22
+ assert isbn.match(ValidationExtensions::IsbnValidation::ISBN13_REGEX)
27
23
  end
28
24
 
29
25
  def test_isbn13_should_not_match_regex
30
26
  isbn = '9991a9010599938'
31
- assert !isbn.match(Zerosum::ValidationExtensions::IsbnValidation::ISBN13_REGEX)
27
+ assert !isbn.match(ValidationExtensions::IsbnValidation::ISBN13_REGEX)
32
28
  end
33
29
 
34
30
  def test_isbn13_with_dashes_and_spaces_should_match_regex
35
31
  isbn = '978-159059 9938'
36
- assert isbn.match(Zerosum::ValidationExtensions::IsbnValidation::ISBN13_REGEX)
32
+ assert isbn.match(ValidationExtensions::IsbnValidation::ISBN13_REGEX)
33
+ end
34
+
35
+ def test_isbn_should_match_either_isbn10_or_isbn13
36
+ book = Book.new
37
+ book.isbn = 'invalid'
38
+ assert !book.valid?
39
+ book.isbn = '1590599934'
40
+ assert book.valid?
41
+ book.isbn = '9781590599938'
42
+ assert book.valid?
37
43
  end
38
44
 
39
45
  def test_isbn10_should_pass_check_digit_verification
40
- @book.isbn = '159059993-4'
41
- assert @book.valid?
46
+ book = Book10.new
47
+ book.isbn = '159059993-4'
48
+ assert book.valid?
42
49
  end
43
50
 
44
51
  def test_isbn10_should_fail_check_digit_verification
45
- @book.isbn = '159059993-0'
46
- assert !@book.valid?
52
+ book = Book10.new
53
+ book.isbn = '159059993-0'
54
+ assert !book.valid?
47
55
  end
48
56
 
49
57
  def test_isbn10_should_handle_x_character_checksum
50
- @book.isbn = '0-9722051-1-X'
51
- assert @book.valid?
58
+ book = Book10.new
59
+ book.isbn = '0-9722051-1-X'
60
+ assert book.valid?
52
61
  end
53
62
 
54
63
  def test_isbn13_should_pass_check_digit_verification
55
- @book.isbn = '978-1590599938'
56
- assert @book.valid?
64
+ book = Book13.new
65
+ book.isbn = '978-1590599938'
66
+ assert book.valid?
57
67
  end
58
68
 
59
69
  def test_isbn13_should_fail_check_digit_verification
60
- @book.isbn = '978-1590599934'
61
- assert !@book.valid?
70
+ book = Book13.new
71
+ book.isbn = '978-1590599934'
72
+ assert !book.valid?
62
73
  end
63
74
 
64
- def test_isbn_should_be_valid_if_either_isbn10_or_isbn13
65
- @book.isbn = '978-1590599938'
66
- assert @book.valid?
67
- @book.isbn = '1590599934'
68
- assert @book.valid?
75
+ def test_isbn13_with_zero_check_digit_should_validate
76
+ book = Book13.new
77
+ book.isbn = '978-1-60746-006-0'
78
+ assert book.valid?
69
79
  end
70
80
 
71
- def test_isbn_should_validate_only_isbn10
72
- @book = Book10.new
73
- @book.isbn = '978-1590599938'
74
- assert !@book.valid?
75
- @book.isbn = '1590599934'
76
- assert @book.valid?
81
+ def test_isbn_should_be_valid_to_isbn10_by_default
82
+ book = Book.new
83
+ book.isbn = '1590599934'
84
+ assert book.valid?
77
85
  end
78
86
 
79
- def test_isbn_should_validate_only_isbn13
80
- @book = Book13.new
81
- @book.isbn = '1590599934'
82
- assert !@book.valid?
83
- @book.isbn = '978-1590599938'
84
- assert @book.valid?
87
+ def test_should_have_custom_error_message
88
+ book = Book.new
89
+ book.isbn = '978-159059AAAAAA'
90
+ book.valid?
91
+ assert_equal 'is too fantastical!', book.errors[:isbn].first
85
92
  end
86
93
 
87
- def test_should_have_custom_error_message
88
- @book.isbn = '978-159059AAAAAA'
89
- @book.valid?
90
- assert_equal 'is too fantastical!', @book.errors[:isbn].first
94
+ def test_blank_should_not_be_valid_by_default
95
+ book = Book13.new
96
+ book.isbn = ''
97
+ book.valid?
98
+ assert_equal 'is not a valid ISBN code', book.errors[:isbn].first
91
99
  end
92
-
93
- def test_isbn13_with_zero_check_digit_should_validate
94
- @book.isbn = '978-1-60746-006-0'
95
- assert @book.valid?
100
+
101
+ def test_should_have_an_option_to_allow_nil
102
+ book = Book13.new
103
+ book.isbn = nil
104
+ assert book.valid?
105
+ end
106
+
107
+ def test_should_have_an_option_to_allow_blank
108
+ book = Book10.new
109
+ book.isbn = ''
110
+ assert book.valid?
111
+ end
112
+
113
+ def test_should_support_old_syntax
114
+ book = OldBook.new
115
+ book.isbn = ''
116
+ assert !book.valid?
117
+ book.isbn = '1590599934'
118
+ assert book.valid?
96
119
  end
97
120
  end
data/test/models.rb CHANGED
@@ -1,13 +1,18 @@
1
1
  class Book < ActiveRecord::Base
2
- validates_isbn :isbn, :message => 'is too fantastical!'
2
+ validates :isbn, :isbn_format => { :message => 'is too fantastical!' }
3
3
  end
4
4
 
5
5
  class Book10 < ActiveRecord::Base
6
6
  set_table_name 'books'
7
- validates_isbn :isbn, :with => :isbn10
7
+ validates :isbn, :isbn_format => { :with => :isbn10, :allow_blank => true }
8
8
  end
9
9
 
10
10
  class Book13 < ActiveRecord::Base
11
11
  set_table_name 'books'
12
- validates_isbn :isbn, :with => :isbn13
12
+ validates :isbn, :isbn_format => { :with => :isbn13, :allow_nil => true }
13
+ end
14
+
15
+ class OldBook < ActiveRecord::Base
16
+ set_table_name 'books'
17
+ validates_isbn :isbn
13
18
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isbn_validation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -14,7 +14,7 @@ default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
17
- requirement: &2153555480 !ruby/object:Gem::Requirement
17
+ requirement: &2153258500 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,7 +22,18 @@ dependencies:
22
22
  version: '3'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2153555480
25
+ version_requirements: *2153258500
26
+ - !ruby/object:Gem::Dependency
27
+ name: sqlite3
28
+ requirement: &2153258080 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *2153258080
26
37
  description: isbn_validation adds an isbn validation routine to active record models.
27
38
  email: nap@zerosum.org
28
39
  executables: []