isbn_validation 1.0.0 → 1.1.0

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/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: []