I would look to implement a structure with separate implementations for the three cases:
- IBAN13
- IBAN10
- Neither of the above
You can provide that with something along these lines, in which IBAN#new
is overridden to detect the number of integers provided, and to initialise the correct object to process it.
The real trick here is to provide the Invalid
module, which responds to everything that you expect the Thirteen
and Ten
objects to respond to, in an implementation similar to a Nil Object pattern – in this case an Invalid Object.
I've omitted the implementation of the #valid?
etc classes, but would point you to the Lisbn gem in which we have implemented an extremely fast algorithm https://github.com/ragalie/lisbn/blob/master/lib/lisbn/lisbn.rb#L111. Benchmarked against Enumerable-based methods, which often look quite elegant, this algorithm is incredibly fast – 40x faster than the same logic implemented in some ISBN gems.
Here's a code outline:
module IBAN
def self.new(string)
numeric = string.gsub(/[^0-9]/,"")
case numeric.size
when 13
then Thirteen.new(string)
when 10
then Ten.new(string)
else
Invalid
end
end
class Thirteen
def initialize(number)
@number = number
end
def checksum
# TODO
end
def valid?
# TODO
end
attr_reader :number
end
class Ten
def initialize(number)
@number = number
end
def checksum
# TODO
end
def valid?
# TODO
end
attr_reader :number
end
module Invalid
def self.valid?
false
end
def self.checksum
nil
end
end
end
ps. You might prefer to implement Invalid
as a singleton instead of as a module.
...
else
Invalid.instance
end
...
class Invalid
include Singleton
def valid?
false
end
def checksum
nil
end
end
end
I would look to implement a structure with separate implementations for the three cases:
- IBAN13
- IBAN10
- Neither of the above
You can provide that with something along these lines, in which IBAN#new
is overridden to detect the number of integers provided, and to initialise the correct object to process it.
The real trick here is to provide the Invalid
module, which responds to everything that you expect the Thirteen
and Ten
objects to respond to, in an implementation similar to a Nil Object pattern – in this case an Invalid Object.
I've omitted the implementation of the #valid?
etc classes, but would point you to the Lisbn gem in which we have implemented an extremely fast algorithm https://github.com/ragalie/lisbn/blob/master/lib/lisbn/lisbn.rb#L111. Benchmarked against Enumerable-based methods, which often look quite elegant, this algorithm is incredibly fast – 40x faster than the same logic implemented in some ISBN gems.
Here's a code outline:
module IBAN
def self.new(string)
numeric = string.gsub(/[^0-9]/,"")
case numeric.size
when 13
then Thirteen.new(string)
when 10
then Ten.new(string)
else
Invalid
end
end
class Thirteen
def initialize(number)
@number = number
end
def checksum
# TODO
end
def valid?
# TODO
end
attr_reader :number
end
class Ten
def initialize(number)
@number = number
end
def checksum
# TODO
end
def valid?
# TODO
end
attr_reader :number
end
module Invalid
def self.valid?
false
end
def self.checksum
nil
end
end
end
ps. You might prefer to implement Invalid
as a singleton instead of as a module.
I would look to implement a structure with separate implementations for the three cases:
- IBAN13
- IBAN10
- Neither of the above
You can provide that with something along these lines, in which IBAN#new
is overridden to detect the number of integers provided, and to initialise the correct object to process it.
The real trick here is to provide the Invalid
module, which responds to everything that you expect the Thirteen
and Ten
objects to respond to, in an implementation similar to a Nil Object pattern – in this case an Invalid Object.
I've omitted the implementation of the #valid?
etc classes, but would point you to the Lisbn gem in which we have implemented an extremely fast algorithm https://github.com/ragalie/lisbn/blob/master/lib/lisbn/lisbn.rb#L111. Benchmarked against Enumerable-based methods, which often look quite elegant, this algorithm is incredibly fast – 40x faster than the same logic implemented in some ISBN gems.
Here's a code outline:
module IBAN
def self.new(string)
numeric = string.gsub(/[^0-9]/,"")
case numeric.size
when 13
then Thirteen.new(string)
when 10
then Ten.new(string)
else
Invalid
end
end
class Thirteen
def initialize(number)
@number = number
end
def checksum
# TODO
end
def valid?
# TODO
end
attr_reader :number
end
class Ten
def initialize(number)
@number = number
end
def checksum
# TODO
end
def valid?
# TODO
end
attr_reader :number
end
module Invalid
def self.valid?
false
end
def self.checksum
nil
end
end
end
ps. You might prefer to implement Invalid
as a singleton instead of as a module.
...
else
Invalid.instance
end
...
class Invalid
include Singleton
def valid?
false
end
def checksum
nil
end
end
end
I would look to implement a structure with separate implementations for the three cases:
- IBAN13
- IBAN10
- Neither of the above
You can provide that with something along these lines, in which IBAN#new
is overridden to detect the number of integers provided, and to initialise the correct object to process it.
The real trick here is to provide the Invalid
module, which responds to everything that you expect the Thirteen
and Ten
objects to respond to, in an implementation similar to a Nil Object pattern – in this case an Invalid Object.
I've omitted the implementation of the #valid?
etc classes, but would point you to the Lisbn gem in which we have implemented an extremely fast algorithm https://github.com/ragalie/lisbn/blob/master/lib/lisbn/lisbn.rb#L111. Benchmarked against Enumerable-based methods, which often look quite elegant, this algorithm is incredibly fast – 40x faster than the same logic implemented in some ISBN gems.
Here's a code outline:
module IBAN
def self.new(string)
numeric = string.gsub(/[^0-9]/,"")
case numeric.size
when 13
then Thirteen.new(string)
when 10
then Ten.new(string)
else
Invalid
end
end
class Thirteen
def initialize(number)
@number = number
end
def checksum
# TODO
end
def valid?
# TODO
end
attr_reader :number
end
class Ten
def initialize(number)
@number = number
end
def checksum
# TODO
end
def valid?
# TODO
end
attr_reader :number
end
module Invalid
def self.valid?
false
end
def self.checksum
nil
end
end
end
ps. You might prefer to implement Invalid
as a singleton instead of as a module.