diff --git a/README.md b/README.md index 8503078..2514148 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,19 @@ Or install it yourself as: You can change the number of parts of the generated code by passing an option hash value like: - >> CouponCode.generate(parts: 4) + >> code = CouponCode.generate(parts: 4) => "1K7Q-CTFM-LMTC-DLGP" + >> CouponeCode.validate(code, parts: 4) + => "1K7Q-CTFM-LMTC-DLGP" + +You can also set the default number of parts you are working with so that you don't have to continually send the parts value as an option: + + >> CouponCode.default_parts(5) + => 5 + >> code = CouponCode.generate + => "CNYF-K4AH-L5PF-0RU7-5L0Q" + >> CouponCode.validate(code) + => "CNYF-K4AH-L5PF-0RU7-5L0Q" ## Testing @@ -74,4 +85,4 @@ MIT. See [LICENSE][license] for more details. [node-couponcode]: https://github.com/chilts/node-coupon-code [license]: https://github.com/baxang/coupon-code/blob/master/LICENSE.txt [README-kr]: https://github.com/baxang/coupon-code/blob/master/README-ko.md -[rubygems]: https://rubygems.org/gems/coupon_code \ No newline at end of file +[rubygems]: https://rubygems.org/gems/coupon_code diff --git a/lib/coupon_code.rb b/lib/coupon_code.rb index 537fd1b..409c427 100644 --- a/lib/coupon_code.rb +++ b/lib/coupon_code.rb @@ -3,35 +3,43 @@ require 'digest/sha1' module CouponCode - SYMBOL = '0123456789ABCDEFGHJKLMNPQRTUVWXY' - PARTS = 3 - LENGTH = 4 + SYMBOL = "0123456789ABCDEFGHJKLMNPQRTUVWXY" + LENGTH = 4 + @@parts = 3 - def self.generate(options = { parts: PARTS }) - num_parts = options.delete(:parts) - parts = [] - (1..num_parts).each do |i| - part = '' + def self.generate(options = { parts: @@parts }) + (1..options[:parts]).map do |i| + part = "" (1...LENGTH).each { part << random_symbol } part << checkdigit_alg_1(part, i) - parts << part - end - parts.join('-') + + part + end.join("-") end - def self.validate(orig, num_parts = PARTS) - code = orig.upcase - code.gsub!(/[^0-9A-Z]+/, '') - parts = code.scan(/[0-9A-Z]{#{LENGTH}}/) + def self.validate(orig, options = { parts: @@parts }) + num_parts = options.delete(:parts) + code = orig.upcase.gsub(/[^0-9A-Z]+/, "") + parts = code.scan(/[0-9A-Z]{#{LENGTH}}/) + return if parts.length != num_parts + parts.each_with_index do |part, i| data = part[0...(LENGTH - 1)] check = part[-1] + return if check != checkdigit_alg_1(data, i + 1) end - parts.join('-') + + parts.join("-") end + def self.default_parts(parts) + @@parts = parts + end + + private + def self.checkdigit_alg_1(orig, check) orig.split('').each_with_index do |c, _| k = SYMBOL.index(c) diff --git a/lib/coupon_code/version.rb b/lib/coupon_code/version.rb index c6e6668..e3ce04b 100644 --- a/lib/coupon_code/version.rb +++ b/lib/coupon_code/version.rb @@ -1,3 +1,3 @@ module CouponCode - VERSION = '0.0.1' + VERSION = "0.1.0" end diff --git a/test/coupon_code_test.rb b/test/coupon_code_test.rb index 67686c7..0cb94d0 100644 --- a/test/coupon_code_test.rb +++ b/test/coupon_code_test.rb @@ -40,23 +40,23 @@ def generate(*args) end it 'should fail to validate invalid code.' do - CouponCode.validate('').must_equal(nil) + CouponCode.validate("").must_equal(nil) end it 'should accept a valid code.' do - CouponCode.validate('1K7Q-CTFM-LMTC').wont_be_nil + CouponCode.validate("1K7Q-CTFM-LMTC").wont_be_nil end it 'should reject a short code.' do - CouponCode.validate('1K7Q-CTFM').must_be_nil + CouponCode.validate("1K7Q-CTFM").must_be_nil end it 'should accept a short code with correct parts.' do - CouponCode.validate('1K7Q-CTFM', 2).wont_be_nil + CouponCode.validate("1K7Q-CTFM", parts: 2).wont_be_nil end it 'should reject a short code with wrong parts.' do - CouponCode.validate('CTFM-1K7Q', 2).must_be_nil + CouponCode.validate("CTFM-1K7Q", parts: 2).must_be_nil end it 'should fix and validate a lowercase code.' do @@ -76,23 +76,33 @@ def generate(*args) end it 'should valid code-pretest.' do - CouponCode.validate('1K7Q', 1).wont_be_nil - CouponCode.validate('1K7C', 1).must_be_nil + CouponCode.validate("1K7Q", parts: 1).wont_be_nil + CouponCode.validate("1K7C", parts: 1).must_be_nil - CouponCode.validate('1K7Q-CTFM', 2).wont_be_nil - CouponCode.validate('1K7Q-CTFW', 2).must_be_nil + CouponCode.validate("1K7Q-CTFM", parts: 2).wont_be_nil + CouponCode.validate('1K7Q-CTFW', parts: 2).must_be_nil - CouponCode.validate('1K7Q-CTFM-LMTC', 3).wont_be_nil - CouponCode.validate('1K7Q-CTFM-LMT1', 3).must_be_nil + CouponCode.validate("1K7Q-CTFM-LMTC", parts: 3).wont_be_nil + CouponCode.validate("1K7Q-CTFM-LMT1", parts: 3).must_be_nil - CouponCode.validate('7YQH-1FU7-E1HX-0BG9', 4).wont_be_nil - CouponCode.validate('7YQH-1FU7-E1HX-0BGP', 4).must_be_nil + CouponCode.validate("7YQH-1FU7-E1HX-0BG9", parts: 4).wont_be_nil + CouponCode.validate("7YQH-1FU7-E1HX-0BGP", parts: 4).must_be_nil - CouponCode.validate('YENH-UPJK-PTE0-20U6-QYME', 5).wont_be_nil - CouponCode.validate('YENH-UPJK-PTE0-20U6-QYMT', 5).must_be_nil + CouponCode.validate("YENH-UPJK-PTE0-20U6-QYME", parts: 5).wont_be_nil + CouponCode.validate("YENH-UPJK-PTE0-20U6-QYMT", parts: 5).must_be_nil - CouponCode.validate('YENH-UPJK-PTE0-20U6-QYME-RBK1', 6).wont_be_nil - CouponCode.validate('YENH-UPJK-PTE0-20U6-QYME-RBK2', 6).must_be_nil + CouponCode.validate("YENH-UPJK-PTE0-20U6-QYME-RBK1", parts: 6).wont_be_nil + CouponCode.validate("YENH-UPJK-PTE0-20U6-QYME-RBK2", parts: 6).must_be_nil + end + + it "should allow a default part length to be set" do + CouponCode.default_parts(5) + + code = CouponCode.generate + code.split("-").length.must_equal 5 + CouponCode.validate(code).must_equal code + + CouponCode.default_parts(3) # Set it back for the rest of the tests end end end