Permalink
Browse files

Adds specs and documentation

  • Loading branch information...
1 parent f9e3858 commit b7b0ceb8e026a0b03c8e346886ebe8c729839fef Pascal Ehlert committed Dec 28, 2013
View
25 README.md
@@ -1,24 +1,39 @@
-# Promocode
+# Promocode Generator
-TODO: Write a gem description
+Generates save and unique (when used with AR) codes which can be handed to customers for promotional campaigns.
## Installation
Add this line to your application's Gemfile:
- gem 'promocode'
+ gem 'promocode_generator'
And then execute:
$ bundle
Or install it yourself as:
- $ gem install promocode
+ $ gem install promocode_generator
## Usage
-TODO: Write usage instructions here
+Without Rails:
+
+ Use PromocodeGenerator.generate(length) to produce a promotional code of the desired length.
+
+With Rails:
+
+ In your model, use the promocode_attribute method to automatically generate a promotional code of length 8 in the before_save hook:
+
+ ```ruby
+ class Campaign < ActiveRecord::Base
+ promocode_attribute :code
+ end
+ ```
+
+ Basic uniqueness validation comes by default so that codes are generated until a non-existing code is found in the db. Provide the :reject_if option to customize:
+ `promocode_attribute :code, :reject_if => Proc.new { |code| ModelA.where(:code => code).any? }`
## Contributing
View
4 Rakefile
@@ -1 +1,5 @@
require "bundler/gem_tasks"
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+task default: :spec
View
3 lib/promocode/version.rb
@@ -1,3 +0,0 @@
-module Promocode
- VERSION = "0.0.1"
-end
View
12 lib/promocode_generator.rb
@@ -1,5 +1,11 @@
-require "promocode/version"
+require "promocode_generator/version"
+require "promocode_generator/model_additions"
-module Promocode
- # Your code goes here...
+module PromocodeGenerator
+ # Generates an 8 character random code of uppercase letters and numbers
+ # It explicitly excludes the letters I, L, O and the number 0 to avoid
+ # confusion
+ def self.generate(length = 8)
+ [('A'..'Z').to_a - ['I', 'L', 'O'], ('1'..'9').to_a].flatten.shuffle[0,length].join
+ end
end
View
14 lib/promocode_generator/model_additions.rb
@@ -0,0 +1,14 @@
+module PromocodeGenerator
+ module ModelAdditions
+ def promocode_attribute(attribute, options = {})
+ options[:reject_if] ||= Proc.new { |code| self.where(attribute => code).any? }
+
+ before_save do
+ # Make sure not to generate the same code twice!
+ begin
+ self.code = PromocodeGenerator.generate
+ end while options[:reject_if].call(code)
+ end
+ end
+ end
+end
View
3 lib/promocode_generator/version.rb
@@ -0,0 +1,3 @@
+module PromocodeGenerator
+ VERSION = "0.0.1"
+end
View
1 promocode_generator.gemspec
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake"
spec.add_development_dependency "rspec"
+ spec.add_development_dependency "supermodel"
end
View
40 spec/promocode_generator/model_additions_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+# Dummy reject condition that can be stubbed in the tests below
+module RejectCondition
+ def self.check(code)
+ false
+ end
+end
+
+class Campaign < SuperModel::Base
+ include ActiveModel::Validations::Callbacks
+ extend PromocodeGenerator::ModelAdditions
+ promocode_attribute :code, :reject_if => Proc.new { |code| RejectCondition.check(code) }
+end
+
+describe PromocodeGenerator::ModelAdditions do
+ let(:campaign) { Campaign.new(:name => "foo") }
+
+ context "when the model is saved" do
+ it "generates a code" do
+ expect(PromocodeGenerator).to receive(:generate).once.and_return('ABCDEFG')
+ campaign.save!
+ end
+
+ it "assigns the code to the model" do
+ campaign.save!
+ expect(campaign.code).not_to be_nil
+ end
+ end
+
+ context "when the reject_if block returns false" do
+ before { RejectCondition.stub(:check).and_return(true, false) }
+ after { RejectCondition.unstub(:check) }
+
+ it "generates a new code" do
+ expect(PromocodeGenerator).to receive(:generate).exactly(2).times
+ campaign.save!
+ end
+ end
+end
View
13 spec/promocode_generator_spec.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe PromocodeGenerator do
+ describe ".generate" do
+ it "generates a code of the given length" do
+ expect(PromocodeGenerator.generate(10).length).to eq(10)
+ end
+
+ it "generates a code with default length" do
+ expect(PromocodeGenerator.generate.length).to be > 0
+ end
+ end
+end
View
3 spec/spec_helper.rb
@@ -1 +1,2 @@
-require 'promocode'
+require 'promocode_generator'
+require 'supermodel'

0 comments on commit b7b0ceb

Please sign in to comment.