fraternity 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 368f6c901620e8bfbcbc5629d415e279065d4256
4
+ data.tar.gz: 69c4ce243b0eced4e297b46209a9ae4928bfb555
5
+ SHA512:
6
+ metadata.gz: 369a256c3764c6f2b86730b79d06c913221cee6663ea948f537f17f889bc4babfde4a9f9ed28f1142935e9030e1c5d65a9fab55659e3e1a4884e612bf8aa0dd0
7
+ data.tar.gz: cf7db18d627e19eafe6c19b93d0025c6977605891ab975825adeab378277bc978ee4d9dac4bbe8e3a604b4a077f482ad9b83e951f076e09933e980706470504c
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ repo_token: 0434oPH5AmyPXuVPweKtCWtPXgI5ytvyN
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /coverage
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.2.0
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '2.2.0'
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem 'rspec'
9
+ gem 'coveralls'
10
+ gem 'sqlite3'
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,62 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fraternity (0.0.1)
5
+ lotus-model
6
+ lotus-validations
7
+ rake
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ coveralls (0.7.2)
13
+ multi_json (~> 1.3)
14
+ rest-client (= 1.6.7)
15
+ simplecov (>= 0.7)
16
+ term-ansicolor (= 1.2.2)
17
+ thor (= 0.18.1)
18
+ diff-lcs (1.2.5)
19
+ docile (1.1.5)
20
+ lotus-model (0.2.1)
21
+ lotus-utils (~> 0.3, >= 0.3.2)
22
+ sequel (~> 4.9)
23
+ lotus-utils (0.3.3)
24
+ lotus-validations (0.2.3)
25
+ lotus-utils (~> 0.3, >= 0.3.3)
26
+ mime-types (2.4.3)
27
+ multi_json (1.10.1)
28
+ rake (10.4.2)
29
+ rest-client (1.6.7)
30
+ mime-types (>= 1.16)
31
+ rspec (3.1.0)
32
+ rspec-core (~> 3.1.0)
33
+ rspec-expectations (~> 3.1.0)
34
+ rspec-mocks (~> 3.1.0)
35
+ rspec-core (3.1.7)
36
+ rspec-support (~> 3.1.0)
37
+ rspec-expectations (3.1.2)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.1.0)
40
+ rspec-mocks (3.1.3)
41
+ rspec-support (~> 3.1.0)
42
+ rspec-support (3.1.2)
43
+ sequel (4.18.0)
44
+ simplecov (0.9.1)
45
+ docile (~> 1.1.0)
46
+ multi_json (~> 1.0)
47
+ simplecov-html (~> 0.8.0)
48
+ simplecov-html (0.8.0)
49
+ sqlite3 (1.3.10)
50
+ term-ansicolor (1.2.2)
51
+ tins (~> 0.8)
52
+ thor (0.18.1)
53
+ tins (0.13.2)
54
+
55
+ PLATFORMS
56
+ ruby
57
+
58
+ DEPENDENCIES
59
+ coveralls
60
+ fraternity!
61
+ rspec
62
+ sqlite3
data/README.md ADDED
@@ -0,0 +1,145 @@
1
+ Fraternity
2
+ ==========
3
+
4
+ [ ![Codeship Status for brilliantfantastic/fraternity](https://codeship.com/projects/3fe0d950-80a4-0132-9038-321707412590/status?branch=master)](https://codeship.com/projects/57522)
5
+ [![Coverage Status](https://coveralls.io/repos/brilliantfantastic/fraternity/badge.svg)](https://coveralls.io/r/brilliantfantastic/fraternity)
6
+ [![Code Climate](https://codeclimate.com/github/brilliantfantastic/fraternity/badges/gpa.svg)](https://codeclimate.com/github/brilliantfantastic/fraternity)
7
+
8
+ ## DESCRIPTION
9
+
10
+ An easier way to rush for a beta.
11
+
12
+ A gem allows you to collect and store (using only [the Lotus framework](http://lotusrb.com) as of now) a list of pledges who would like access to your beta. You can send out bids to those pledges and allow them to gain access to your beta.
13
+
14
+ ## INSTALLATION
15
+
16
+ Add this line to your Gemfile:
17
+
18
+ ```
19
+ gem 'fraternity'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ ```
25
+ bundle install
26
+ ```
27
+
28
+ Or install it yourself:
29
+
30
+ ```
31
+ gem install fraternity
32
+ ```
33
+
34
+ Create the database table needed:
35
+
36
+ ```
37
+ bundle exec rake fraternity:install DESTINATION="db/migrate"
38
+ ```
39
+
40
+ The above will create the following table.
41
+
42
+ ```
43
+ create_table :pledges do |t|
44
+ t.primary_key :id
45
+ String :token
46
+ String :email
47
+ String :first_name
48
+ String :last_name
49
+ Integer :initiation_number
50
+ DateTime :invited_at
51
+ DateTime :accepted_at
52
+ end
53
+ ```
54
+
55
+ ## USAGE
56
+
57
+ If you are unfamiliar with the terminology, you can read up at [http://www.unlv.edu/getinvolved/greek-definitions](http://www.unlv.edu/getinvolved/greek-definitions).
58
+
59
+ ### Configuring
60
+
61
+ In order to use your Fraternity, you have to configure it before you use it.
62
+
63
+ ```
64
+ Fraternity.configure do |config|
65
+ configure.database_url = ENV["DATABASE_URL"]
66
+ configure.send_invite = lambda do |pledge|
67
+ BetaMailer.invite_email(pledge).deliver
68
+ end
69
+ end
70
+ ```
71
+
72
+ ### Pledging
73
+
74
+ To sign up pledges, you first need to rush. Collect email addresses (and any additional information) to get in line for membership at the frat house.
75
+
76
+ ```
77
+ params = { email: "jeremy.piven@example.com" } # Optional attributes you want to save such as first_name, last_name, etc.
78
+ pledge = Fraternity.rush! params
79
+ ```
80
+
81
+ The above saves the information to the pledges database and creates a token for a `Pledge`
82
+
83
+ ### Moving up the initiation line
84
+
85
+ **Coming soon**
86
+
87
+ ### Inviting a new pledge
88
+
89
+ Send out email invitations to the next set of pledges based on their initiation number. A quota is specified for the number you want to invite.
90
+
91
+ ```
92
+ invited = Fraternity.bid! quota
93
+ ```
94
+
95
+ The above saves the date/time of the invite to all the invited pledges and returns an array of the invited.
96
+
97
+ The above will also call the `send_invite` proc that you have set up in the configuration. You are responsible for sending the invite to the pledge any way you like.
98
+
99
+ Find out if a pledge has been invited
100
+
101
+ ```
102
+ Fraternity::Pledge.find(123).invited?
103
+ ```
104
+
105
+ Resend an invite
106
+
107
+ ```
108
+ Fraternity::Pledge.find(123).bid!
109
+ ```
110
+
111
+ ### Accepting a pledge
112
+
113
+ Check to see if a pledge is ready to be crossed into a full time member (invited and not crossed)
114
+
115
+ ```
116
+ Fraternity::Pledge.find(token).ready?
117
+ ```
118
+
119
+ Check to see if a pledge has been crossed into a full member
120
+
121
+ ```
122
+ Fraternity::Pledge.find(token).crossed?
123
+ ```
124
+
125
+ Convert the pledge into a full member (accept the invitation).
126
+
127
+ ```
128
+ Fraternity::Pledge.cross! token
129
+ ```
130
+
131
+ ## CONTRIBUTING
132
+
133
+ 1. Clone the repository `git clone https://github.com/brilliantfantastic/fraternity`
134
+ 1. Create a feature branch `git checkout -b my-awesome-feature`
135
+ 1. Codez!
136
+ 1. Commit your changes (small commits please)
137
+ 1. Push your new branch `git push origin my-awesome-feature`
138
+ 1. Create a pull request `hub pull-request -b brilliantfantastic:master -h brilliantfantastic:my-awesome-feature`
139
+
140
+ ## RELEASING A NEW GEM
141
+
142
+ 1. Bump the VERSION in `lib/fraternity/version.rb`
143
+ 1. Commit changes and push to GitHub
144
+ 1. run `bundle exec rake build`
145
+ 1. run `bundle exec rake release`
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ begin
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task default: :spec
7
+ rescue LoadError
8
+ end
9
+
10
+ require 'coveralls/rake/task'
11
+ Coveralls::RakeTask.new
12
+
13
+ namespace :fraternity do
14
+ task :install do
15
+ # read the migration
16
+ base_file_name = "create_pledges.rb"
17
+ template = File.join File.dirname(__FILE__), "lib/generators/fraternity/templates/migration", base_file_name
18
+ contents = File.open(template) { |f| f.read }
19
+
20
+ # create the migration
21
+ destination = ENV["DESTINATION"] || "."
22
+ unless File.directory?(destination)
23
+ FileUtils.mkdir_p destination
24
+ end
25
+ timestamp = Time.now.to_i
26
+ destination_file = File.join destination, "#{timestamp}_#{base_file_name}"
27
+ File.open(destination_file, 'w') { |f| f.write(contents) }
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fraternity/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fraternity"
8
+ spec.version = Fraternity::VERSION
9
+
10
+ spec.authors = ["Jamie Wright"]
11
+ spec.email = ["jamie@brilliantfantastic.com"]
12
+
13
+ spec.summary = "An easier way to rush for a beta"
14
+ spec.description = %q{
15
+ Collect and store a list of pledges who would like access to your beta. You can send out bids to those
16
+ pledges and allow them to gain access to your beta.
17
+ }
18
+
19
+ spec.homepage = "http://github.com/brilliantfantastic/fraternity"
20
+ spec.license = "MIT"
21
+
22
+ spec.files = `git ls-files`.split($/)
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency "rake"
27
+ spec.add_dependency "lotus-model"
28
+ spec.add_dependency "lotus-validations"
29
+ end
@@ -0,0 +1,14 @@
1
+ module Fraternity
2
+ class Bidder
3
+ def initialize(pledge)
4
+ @pledge = pledge
5
+ end
6
+
7
+ def bid!
8
+ @pledge.invite!
9
+ Repositories::PledgeRepository.persist @pledge
10
+ Fraternity.configuration.send_invite.call @pledge
11
+ @pledge
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module Fraternity
2
+ class Configuration
3
+ attr_accessor :database_url, :send_invite
4
+
5
+ def initialize
6
+ @send_invite = lambda { |pledge| pledge }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Fraternity
2
+ class PerpError < StandardError; end
3
+ end
@@ -0,0 +1,45 @@
1
+ require "lotus/validations"
2
+
3
+ module Fraternity
4
+ class Pledge
5
+ include Lotus::Validations
6
+
7
+ attr_accessor :id, :email, :first_name, :last_name, :token, :initiation_number, :invited_at, :accepted_at
8
+
9
+ validates :email, presence: true, format: /[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4}/
10
+ validates :token, presence: true
11
+ validates :initiation_number, presence: true
12
+
13
+ def initialize(attributes={})
14
+
15
+ @id, @email, @first_name, @last_name, @token, @initiation_number, @invited_at, @accepted_at =
16
+ attributes.values_at :id, :email, :first_name, :last_name, :token, :initiation_number, :invited_at, :accepted_at
17
+ end
18
+
19
+ def bid!
20
+ Bidder.new(self).bid!
21
+ end
22
+
23
+ def invite!
24
+ self.invited_at = DateTime.now
25
+ end
26
+
27
+ def invited?
28
+ !self.invited_at.nil?
29
+ end
30
+
31
+ def cross!(token)
32
+ raise Fraternity::PerpError if !invited?
33
+ raise Fraternity::TokenMismatchError.new(self.token, token) if token != self.token
34
+ self.accepted_at = DateTime.now
35
+ end
36
+
37
+ def crossed?
38
+ !self.accepted_at.nil?
39
+ end
40
+
41
+ def ready?
42
+ self.invited? && !self.crossed?
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ require 'lotus/repository'
2
+
3
+ module Fraternity
4
+ module Repositories
5
+ class PledgeRepository
6
+ include Lotus::Repository
7
+
8
+ def self.find_by_id(id)
9
+ query do
10
+ where(id: id)
11
+ end.first
12
+ end
13
+
14
+ def self.find_by_token(token)
15
+ query do
16
+ where(token: token)
17
+ end.first
18
+ end
19
+
20
+ def self.oldest_uninvited_by_initiation_number(limit=8)
21
+ query do
22
+ where(invited_at: nil).
23
+ order(:initiation_number)
24
+ end.limit(limit)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ require "lotus/model/mapper"
2
+ require "lotus/model/adapters/sql_adapter"
3
+ require_relative "repositories/pledge_repository"
4
+
5
+ module Fraternity
6
+ module Repositories
7
+ @@mapping = Lotus::Model::Mapper.new do
8
+ collection :pledges do
9
+ entity Fraternity::Pledge
10
+ repository PledgeRepository
11
+
12
+ attribute :id, Integer
13
+ attribute :email, String
14
+ attribute :first_name, String
15
+ attribute :last_name, String
16
+ attribute :token, String
17
+ attribute :initiation_number, Integer
18
+ attribute :invited_at, DateTime
19
+ attribute :accepted_at, DateTime
20
+ end
21
+ end
22
+
23
+ def self.mapping
24
+ @@mapping
25
+ end
26
+
27
+ def self.initiation!(database_url)
28
+ adapter = Lotus::Model::Adapters::SqlAdapter.new(mapping, database_url)
29
+ PledgeRepository.adapter = adapter
30
+ mapping.load!
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ require 'securerandom'
2
+
3
+ module Fraternity
4
+ class TemporaryToken
5
+ def self.generate_random_token
6
+ SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Fraternity
2
+ class TokenMismatchError < StandardError
3
+ def initialize(expected_token, actual_token)
4
+ super "Expected token #{expected_token}, but was #{actual_token}"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Fraternity
2
+ VERSION = "0.0.1"
3
+ end
data/lib/fraternity.rb ADDED
@@ -0,0 +1,42 @@
1
+ require "fraternity/version"
2
+ require "fraternity/bidder"
3
+ require "fraternity/configuration"
4
+ require "fraternity/perp_error"
5
+ require "fraternity/pledge"
6
+ require "fraternity/repositories"
7
+ require "fraternity/temporary_token"
8
+ require "fraternity/token_mismatch_error"
9
+
10
+ module Fraternity
11
+ def self.configuration
12
+ @configuration ||= Fraternity::Configuration.new
13
+ end
14
+
15
+ def self.configure(initiate=true)
16
+ yield configuration if block_given?
17
+ Repositories.initiation! configuration.database_url if initiate
18
+ end
19
+
20
+ def self.rush(params={})
21
+ params[:token] ||= TemporaryToken.generate_random_token
22
+ params[:initiation_number] ||= Time.now.to_i
23
+ Fraternity::Pledge.new params
24
+ end
25
+
26
+ def self.rush!(params)
27
+ Repositories::PledgeRepository.create self.rush(params)
28
+ end
29
+
30
+ def self.bid!(quota)
31
+ Repositories::PledgeRepository.oldest_uninvited_by_initiation_number(quota).collect do |pledge|
32
+ pledge.bid!
33
+ end
34
+ end
35
+
36
+ def self.find(identifier)
37
+ if identifier.is_a? Integer
38
+ return Repositories::PledgeRepository.find_by_id identifier
39
+ end
40
+ Repositories::PledgeRepository.find_by_token identifier
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ Sequel.migration do
2
+ change do
3
+ create_table :pledges do
4
+ primary_key :id
5
+ String :token
6
+ String :email
7
+ String :first_name
8
+ String :last_name
9
+ Integer :initiation_number
10
+ DateTime :invited_at
11
+ DateTime :accepted_at
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ describe Fraternity::Configuration do
2
+ it "has a default send_invite proc" do
3
+ configuration = Fraternity::Configuration.new
4
+ expect { configuration.send_invite.call(nil) }.to_not raise_error
5
+ end
6
+ end
@@ -0,0 +1,105 @@
1
+ describe Fraternity::Pledge do
2
+ describe "validations" do
3
+ it "requires an email address" do
4
+ pledge = Fraternity::Pledge.new
5
+ expect(pledge).to_not be_valid
6
+ expect(pledge.errors.for(:email).first.validation).to eq :presence
7
+ end
8
+
9
+ it "requires a valid email address" do
10
+ pledge = Fraternity::Pledge.new email: "blah@test"
11
+ expect(pledge).to_not be_valid
12
+ expect(pledge.errors.for(:email).first.validation).to eq :format
13
+ end
14
+
15
+ it "requires a token" do
16
+ pledge = Fraternity::Pledge.new email: "jimmy@example.com", token: ""
17
+ expect(pledge).to_not be_valid
18
+ expect(pledge.errors.for(:token).first.validation).to eq :presence
19
+ end
20
+
21
+ it "requires an initiation number" do
22
+ pledge = Fraternity::Pledge.new email: "jimmy@example.com", token: "123456", initiation_number: ""
23
+ expect(pledge).to_not be_valid
24
+ expect(pledge.errors.for(:initiation_number).first.validation).to eq :presence
25
+ end
26
+ end
27
+
28
+ describe "#invited?" do
29
+ it "is not invited if the date and time when they were invited is not set" do
30
+ pledge = Fraternity::Pledge.new
31
+ expect(pledge).to_not be_invited
32
+ end
33
+
34
+ it "is invited if the date and time when they were invited is set" do
35
+ pledge = Fraternity::Pledge.new invited_at: DateTime.now
36
+ expect(pledge).to be_invited
37
+ end
38
+ end
39
+
40
+ describe "#invite!" do
41
+ it "sets the date and time of when the pledge was invited to the current date and time" do
42
+ pledge = Fraternity::Pledge.new
43
+ pledge.invite!
44
+ expect(pledge).to be_invited
45
+ end
46
+ end
47
+
48
+ describe "#crossed?" do
49
+ it "is not crossed if they have not accepted the invitation" do
50
+ pledge = Fraternity::Pledge.new
51
+ expect(pledge).to_not be_crossed
52
+ end
53
+
54
+ it "is crossed if they have accepted the invitation" do
55
+ pledge = Fraternity::Pledge.new accepted_at: DateTime.now
56
+ expect(pledge).to be_crossed
57
+ end
58
+ end
59
+
60
+ describe "#cross!" do
61
+ it "sets the date and time of when the pledge has accepted the invite to the current date and time" do
62
+ token = "12345"
63
+ pledge = Fraternity::Pledge.new token: token, invited_at: DateTime.now
64
+ pledge.cross! token
65
+ expect(pledge).to be_crossed
66
+ end
67
+
68
+ it "does not cross over if the token does not match" do
69
+ pledge = Fraternity::Pledge.new token: "12345", invited_at: DateTime.now
70
+ expect { pledge.cross! "blah" }.to raise_error Fraternity::TokenMismatchError
71
+ end
72
+
73
+ it "does not cross over if the pledge was not invited" do
74
+ token = "12345"
75
+ pledge = Fraternity::Pledge.new token: token
76
+ expect { pledge.cross! token }.to raise_error Fraternity::PerpError
77
+ end
78
+ end
79
+
80
+ describe "#bid!" do
81
+ it "updates the date and time they were invited" do
82
+ pledge = Fraternity::Pledge.new id: 123, token: "12345", email: "jimmy@example.com", invited_at: DateTime.new(2015, 1, 18)
83
+ allow(Fraternity::Repositories::PledgeRepository).to receive(:persist).and_return pledge
84
+ pledge.bid!
85
+ expect(((DateTime.now - pledge.invited_at) * 24 * 60 * 60).to_i).to be < 1
86
+ end
87
+ end
88
+
89
+ describe "#ready?" do
90
+ it "returns true if the pledge is invited but not yet crossed" do
91
+ pledge = Fraternity::Pledge.new token: "1234", invited_at: DateTime.now
92
+ expect(pledge).to be_ready
93
+ end
94
+
95
+ it "is not ready if they have not been invited" do
96
+ pledge = Fraternity::Pledge.new token: "1234"
97
+ expect(pledge).to_not be_ready
98
+ end
99
+
100
+ it "is not ready if they have crossed" do
101
+ pledge = Fraternity::Pledge.new token: "1234", invited_at: DateTime.now, accepted_at: DateTime.now
102
+ expect(pledge).to_not be_ready
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,56 @@
1
+ describe Fraternity::Repositories::PledgeRepository do
2
+ before { load_repositories! }
3
+
4
+ describe ".find_by_token" do
5
+ let(:token) { "YUSGH764" }
6
+ let(:pledge) { Fraternity::Repositories::PledgeRepository.create(Fraternity::Pledge.new(email: "jimmy@example.com", token: token, initiation_number: Time.now.to_i)) }
7
+
8
+ it "returns the first pledge with the token" do
9
+ pledge
10
+ actual = Fraternity::Repositories::PledgeRepository.find_by_token token
11
+ expect(actual.id).to eq pledge.id
12
+ end
13
+
14
+ it "returns nil if the pledge does not exist" do
15
+ actual = Fraternity::Repositories::PledgeRepository.find_by_token "blah"
16
+ expect(actual).to be_nil
17
+ end
18
+ end
19
+
20
+ describe ".find_by_id" do
21
+ let(:pledge) { Fraternity::Repositories::PledgeRepository.create(Fraternity::Pledge.new(email: "jimmy@example.com", token: "12345", initiation_number: Time.now.to_i)) }
22
+
23
+ it "returns the first pledge with the id" do
24
+ pledge
25
+ actual = Fraternity::Repositories::PledgeRepository.find_by_id pledge.id
26
+ expect(actual.id).to eq pledge.id
27
+ end
28
+
29
+ it "returns nil if the pledge does not exist" do
30
+ actual = Fraternity::Repositories::PledgeRepository.find_by_id 123
31
+ expect(actual).to be_nil
32
+ end
33
+ end
34
+
35
+ describe ".oldest_univited_by_initiation_number" do
36
+ let(:four_days_ago) { Time.now.to_i - 24 * 60 * 60 * 4 }
37
+ let(:six_days_ago) { Time.now.to_i - 24 * 60 * 60 * 6 }
38
+ let(:ten_days_ago) { Time.now.to_i - 24 * 60 * 60 * 10 }
39
+
40
+ let(:oldest_pledge) { Fraternity::Repositories::PledgeRepository.create(Fraternity::Pledge.new(email: "jimmy@example.com", token: "1234", initiation_number: ten_days_ago)) }
41
+ let(:middle_pledge) { Fraternity::Repositories::PledgeRepository.create(Fraternity::Pledge.new(email: "robert@example.com", token: "5678", initiation_number: six_days_ago)) }
42
+ let(:newest_pledge) { Fraternity::Repositories::PledgeRepository.create(Fraternity::Pledge.new(email: "john@example.com", token: "9123", initiation_number: four_days_ago)) }
43
+
44
+ before { [middle_pledge, newest_pledge, oldest_pledge] } # place in database in this order
45
+
46
+ it "returns the oldest pledges based on their initiation number" do
47
+ pledges = Fraternity::Repositories::PledgeRepository.oldest_uninvited_by_initiation_number
48
+ expect(pledges.map(&:email)).to eq ["jimmy@example.com", "robert@example.com", "john@example.com"]
49
+ end
50
+
51
+ it "returns a limited number of pledges" do
52
+ pledges = Fraternity::Repositories::PledgeRepository.oldest_uninvited_by_initiation_number(2)
53
+ expect(pledges.map(&:email)).to eq ["jimmy@example.com", "robert@example.com"]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,8 @@
1
+ describe Fraternity::Repositories do
2
+ describe ".initiation!" do
3
+ it "sets the adapters for the repositories to a SQL adapter" do
4
+ Fraternity::Repositories.initiation! "sqlite://blah.db"
5
+ expect(Fraternity::Repositories::PledgeRepository.instance_variable_get("@adapter")).to be_instance_of Lotus::Model::Adapters::SqlAdapter
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ describe Fraternity::TemporaryToken do
2
+ describe ".generate_random_token" do
3
+ it "generates a unique random token" do
4
+ tokens = []
5
+ 50.times { tokens << Fraternity::TemporaryToken.generate_random_token }
6
+ expect(tokens.uniq.length).to eq 50
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ describe Fraternity::TokenMismatchError do
2
+ it "describes the mismatched tokens" do
3
+ expected = "1234"
4
+ actual = "5678"
5
+ error = Fraternity::TokenMismatchError.new expected, actual
6
+ (expect(error.message)).to eq "Expected token #{expected}, but was #{actual}"
7
+ end
8
+ end
@@ -0,0 +1,99 @@
1
+ describe Fraternity do
2
+ describe ".bid!" do
3
+ let(:pledge) { Fraternity::Repositories::PledgeRepository.create(Fraternity::Pledge.new(email: "jimmy@example.com", token: "1234", initiation_number: Time.now.to_i)) }
4
+
5
+ before do
6
+ load_repositories!
7
+ pledge
8
+ end
9
+
10
+ it "invites the uninvited" do
11
+ pledges = Fraternity.bid! 5
12
+ expect(pledges.to_a[0].id).to eq pledge.id
13
+ expect(pledges.to_a[0]).to be_invited
14
+ end
15
+
16
+ it "sends the invite" do
17
+ sent_invite = false
18
+ Fraternity.configure(false) do |c|
19
+ c.send_invite = lambda do |pledge|
20
+ sent_invite = true
21
+ end
22
+ end
23
+ pledges = Fraternity.bid! 5
24
+ expect(sent_invite).to be true
25
+ end
26
+ end
27
+
28
+ describe ".configure" do
29
+ it "yields an instance of configuration" do
30
+ Fraternity.configure(false) do |config|
31
+ expect(config).to eq Fraternity.configuration
32
+ end
33
+ end
34
+ end
35
+
36
+ describe ".find" do
37
+ let(:token) { "HJDKSYS6782W" }
38
+ let(:pledge) { Fraternity::Pledge.new id: 123, token: token, email: "jimmy@example.com" }
39
+
40
+ it "returns a pledge based on their token" do
41
+ allow(Fraternity::Repositories::PledgeRepository).to receive(:find_by_token).and_return pledge
42
+ actual = Fraternity.find token
43
+ expect(actual.id).to eq pledge.id
44
+ end
45
+
46
+ it "returns a pledge based on their id" do
47
+ allow(Fraternity::Repositories::PledgeRepository).to receive(:find_by_id).and_return pledge
48
+ actual = Fraternity.find pledge.id
49
+ expect(actual.id).to eq pledge.id
50
+ end
51
+ end
52
+
53
+ describe ".rush" do
54
+ it "rushes with parameters that describe the pledge" do
55
+ expect { Fraternity.rush email: "blah" }.to_not raise_error
56
+ end
57
+
58
+ it "creates a new pledge with the specified parameters" do
59
+ pledge = Fraternity.rush email: "jimmy@example.com"
60
+ expect(pledge.email).to eq "jimmy@example.com"
61
+ end
62
+
63
+ it "populates a token for the pledge to use for joining" do
64
+ pledge = Fraternity.rush
65
+ expect(pledge.token).to_not be_empty
66
+ end
67
+
68
+ it "uses the provided token if there is one" do
69
+ pledge = Fraternity.rush token: "blah"
70
+ expect(pledge.token).to eq "blah"
71
+ end
72
+
73
+ it "creates an initiation number" do
74
+ pledge = Fraternity.rush
75
+ expect(pledge.initiation_number).to_not be_nil
76
+ initiated_at = Time.at pledge.initiation_number
77
+ expect((Time.now - initiated_at).to_i).to be < 1
78
+ end
79
+
80
+ it "uses the provided initiation number if there is one" do
81
+ pledge = Fraternity.rush initiation_number: 12345
82
+ expect(pledge.initiation_number).to eq 12345
83
+ end
84
+ end
85
+
86
+ describe ".rush!" do
87
+ before { load_repositories! }
88
+
89
+ it "creates a new pledge with the specified parameters" do
90
+ pledge = Fraternity.rush! email: "jimmy@example.com"
91
+ expect(pledge.email).to eq "jimmy@example.com"
92
+ end
93
+
94
+ it "saves the new pledge to the database" do
95
+ pledge = Fraternity.rush! email: "jimmy@example.com"
96
+ expect(pledge.id).to_not be_nil
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,29 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require "fraternity"
5
+
6
+ ROOT = File.expand_path('../../', __FILE__)
7
+ Dir[File.join(ROOT, 'spec', 'support', '**/*.rb')].each { |f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.expect_with :rspec do |expectations|
11
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
12
+ end
13
+
14
+ config.mock_with :rspec do |mocks|
15
+ mocks.verify_partial_doubles = true
16
+ end
17
+
18
+ config.filter_run :focus
19
+ config.run_all_when_everything_filtered = true
20
+
21
+ if config.files_to_run.one?
22
+ config.default_formatter = 'doc'
23
+ end
24
+
25
+ config.profile_examples = 10
26
+
27
+ config.order = :random
28
+ Kernel.srand config.seed
29
+ end
@@ -0,0 +1,6 @@
1
+ def load_repositories!
2
+ require "lotus/model/adapters/memory_adapter"
3
+ mapping = Fraternity::Repositories.mapping
4
+ Fraternity::Repositories::PledgeRepository.adapter = Lotus::Model::Adapters::MemoryAdapter.new mapping
5
+ mapping.load!
6
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fraternity
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jamie Wright
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: lotus-model
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: lotus-validations
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: "\n Collect and store a list of pledges who would
56
+ like access to your beta. You can send out bids to those\n pledges
57
+ and allow them to gain access to your beta.\n "
58
+ email:
59
+ - jamie@brilliantfantastic.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".coveralls.yml"
65
+ - ".gitignore"
66
+ - ".rspec"
67
+ - ".ruby-version"
68
+ - Gemfile
69
+ - Gemfile.lock
70
+ - README.md
71
+ - Rakefile
72
+ - fraternity.gemspec
73
+ - lib/fraternity.rb
74
+ - lib/fraternity/bidder.rb
75
+ - lib/fraternity/configuration.rb
76
+ - lib/fraternity/perp_error.rb
77
+ - lib/fraternity/pledge.rb
78
+ - lib/fraternity/repositories.rb
79
+ - lib/fraternity/repositories/pledge_repository.rb
80
+ - lib/fraternity/temporary_token.rb
81
+ - lib/fraternity/token_mismatch_error.rb
82
+ - lib/fraternity/version.rb
83
+ - lib/generators/fraternity/templates/migration/create_pledges.rb
84
+ - spec/fraternity/configuration_spec.rb
85
+ - spec/fraternity/pledge_spec.rb
86
+ - spec/fraternity/repositories/pledge_repository_spec.rb
87
+ - spec/fraternity/repositories_spec.rb
88
+ - spec/fraternity/temporary_token_spec.rb
89
+ - spec/fraternity/token_mismatch_error_spec.rb
90
+ - spec/fraternity_spec.rb
91
+ - spec/spec_helper.rb
92
+ - spec/support/repository_helper.rb
93
+ homepage: http://github.com/brilliantfantastic/fraternity
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.4.5
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: An easier way to rush for a beta
117
+ test_files:
118
+ - spec/fraternity/configuration_spec.rb
119
+ - spec/fraternity/pledge_spec.rb
120
+ - spec/fraternity/repositories/pledge_repository_spec.rb
121
+ - spec/fraternity/repositories_spec.rb
122
+ - spec/fraternity/temporary_token_spec.rb
123
+ - spec/fraternity/token_mismatch_error_spec.rb
124
+ - spec/fraternity_spec.rb
125
+ - spec/spec_helper.rb
126
+ - spec/support/repository_helper.rb