devise_referable 0.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.
Files changed (44) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +81 -0
  5. data/Rakefile +54 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/referrals_controller.rb +12 -0
  8. data/app/models/referral.rb +38 -0
  9. data/devise_referable.gemspec +117 -0
  10. data/init.rb +1 -0
  11. data/lib/devise/hooks/referable.rb +13 -0
  12. data/lib/devise_referable/model.rb +47 -0
  13. data/lib/devise_referable/routes.rb +12 -0
  14. data/lib/devise_referable.rb +12 -0
  15. data/rails/init.rb +1 -0
  16. data/test/integration/referable_test.rb +59 -0
  17. data/test/integration_tests_helper.rb +35 -0
  18. data/test/model_tests_helper.rb +64 -0
  19. data/test/models/referral_test.rb +40 -0
  20. data/test/models_test.rb +31 -0
  21. data/test/rails_app/app/controllers/admins_controller.rb +6 -0
  22. data/test/rails_app/app/controllers/application_controller.rb +10 -0
  23. data/test/rails_app/app/controllers/home_controller.rb +4 -0
  24. data/test/rails_app/app/controllers/users_controller.rb +12 -0
  25. data/test/rails_app/app/helpers/application_helper.rb +3 -0
  26. data/test/rails_app/app/models/blog.rb +3 -0
  27. data/test/rails_app/app/models/user.rb +4 -0
  28. data/test/rails_app/app/views/home/index.html.erb +1 -0
  29. data/test/rails_app/config/boot.rb +110 -0
  30. data/test/rails_app/config/database.yml +22 -0
  31. data/test/rails_app/config/environment.rb +44 -0
  32. data/test/rails_app/config/environments/development.rb +17 -0
  33. data/test/rails_app/config/environments/production.rb +28 -0
  34. data/test/rails_app/config/environments/test.rb +28 -0
  35. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  36. data/test/rails_app/config/initializers/devise.rb +76 -0
  37. data/test/rails_app/config/initializers/inflections.rb +2 -0
  38. data/test/rails_app/config/initializers/new_rails_defaults.rb +21 -0
  39. data/test/rails_app/config/initializers/session_store.rb +15 -0
  40. data/test/rails_app/config/routes.rb +4 -0
  41. data/test/rails_app/vendor/plugins/devise_referable/init.rb +1 -0
  42. data/test/routes_test.rb +21 -0
  43. data/test/test_helper.rb +66 -0
  44. metadata +167 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ test/rails_app/log
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Matt Van Horn, derived from work done by Sergio Cambra
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,81 @@
1
+ = devise_referable
2
+
3
+ It adds support to devise[http://github.com/plataformatec/devise] for tracking
4
+ users that were sent by referrers modeled as other classes in your app.
5
+
6
+ == Installation
7
+
8
+ All gems are on gemcutter, so you need to add gemcutter to your sources if you haven’t yet:
9
+
10
+ sudo gem sources -a http://gemcutter.org/
11
+
12
+ Install devise_referable gem, it should install dependencies (such as devise and warden):
13
+
14
+ sudo gem install devise_referable
15
+
16
+ Configure devise_referable inside your app (and warden and devise if you weren't using them):
17
+
18
+ config.gem 'warden'
19
+ config.gem 'devise'
20
+ config.gem 'devise_referable'
21
+
22
+ == Basic Usage
23
+
24
+ Follow the walkthrough for devise with the following modifications.
25
+
26
+ Create a migration for the referrals table:
27
+
28
+ create_table :referrals, :force => true do |t|
29
+ t.integer :referrer_id
30
+ t.string :referrer_type
31
+ t.integer :recipient_id
32
+ t.string :referral_token
33
+ t.datetime :registered_at
34
+ t.timestamps
35
+ end
36
+
37
+ Add a referrer_token column to your referrer classes.
38
+
39
+ add_column :table_name1, :referrer_token, :string
40
+ add_column :table_name2, :referrer_token, :string
41
+
42
+ Add indexes if you want
43
+ add_index :referrals, :referral_token
44
+ add_index :table_name1, :referrer_token
45
+ add_index :table_name2, :referrer_token
46
+
47
+
48
+ Add :referable to the devise line in your model:
49
+
50
+ class User < ActiveRecord::Base
51
+ devise ..., :referable
52
+ end
53
+
54
+ If you are using devise :all, you can add :referable to config.all in devise initializer:
55
+ Devise.setup do |config|
56
+ ...
57
+ config.all = [..., :referable]
58
+ ...
59
+ end
60
+
61
+ == Model configuration
62
+
63
+ DeviseReferable adds a new configuration option, :referral_types. It should be
64
+ an array of classes which can act as a referrer
65
+
66
+
67
+ == Note on Patches/Pull Requests
68
+
69
+ * Fork the project.
70
+ * Make your feature addition or bug fix.
71
+ * Add tests for it. This is important so I don't break it in a
72
+ future version unintentionally.
73
+ * Commit, do not mess with rakefile, version, or history.
74
+ (if you want to have your own version, that is fine but
75
+ bump version in a commit by itself I can ignore when I pull)
76
+ * Send me a pull request. Bonus points for topic branches.
77
+
78
+ == Copyright
79
+
80
+ Copyright (c) 2010 Matt Van Horn, based on work by {Sergio Cambra}[http://github.com/scambra/devise_invitable].
81
+ See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "devise_referable"
8
+ gem.summary = %Q{An allows referral tracking for devise}
9
+ gem.description = %Q{It tracks the referring entity via cookie, and creates a record when user registers.}
10
+ gem.email = "mattvanhorn@gmail.com"
11
+ gem.homepage = "http://github.com/mattvanhorn/devise_referable"
12
+ gem.authors = ["Matt Van Horn, based on work by Sergio Cambra"]
13
+ gem.add_development_dependency 'mocha'
14
+ gem.add_development_dependency 'webrat'
15
+ gem.add_dependency 'devise', '~> 1.0.0'
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/*_test.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "devise_referable #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,12 @@
1
+ class ReferralsController < ApplicationController
2
+
3
+ def create
4
+ unless user_signed_in?
5
+ @referral = Referral.from_token(params[:referrer_token])
6
+ session[:referral_token] = @referral.referral_token if @referral
7
+ end
8
+ redirect_to "/#{params[:path].join('/')}"
9
+ end
10
+
11
+ end
12
+
@@ -0,0 +1,38 @@
1
+ require 'devise/hooks/referable'
2
+
3
+ class Referral < ActiveRecord::Base
4
+ belongs_to :referrer, :polymorphic => true
5
+ belongs_to :recipient, :class_name => 'User'
6
+
7
+ before_create :generate_token
8
+
9
+ class << self
10
+ def referrer_types
11
+ User.referrer_types
12
+ end
13
+
14
+ def lookup_referrer(token)
15
+ unless token.blank?
16
+ referrer_types.map{ |type| type.to_s.classify.constantize }.each do |klass|
17
+ ref = klass.find_by_referrer_token(token)
18
+ return ref unless ref.nil?
19
+ end
20
+ end
21
+ return nil
22
+ end
23
+
24
+ def from_token(token)
25
+ sender = lookup_referrer(token)
26
+ if sender
27
+ Referral.create do |ref|
28
+ ref.referrer = sender
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def generate_token
35
+ self.referral_token ||= Devise.friendly_token
36
+ end
37
+
38
+ end
@@ -0,0 +1,117 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{devise_referable}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Matt Van Horn, based on work by Sergio Cambra"]
12
+ s.date = %q{2010-03-16}
13
+ s.description = %q{It tracks the referring entity via cookie, and creates a record when user registers.}
14
+ s.email = %q{mattvanhorn@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "app/controllers/referrals_controller.rb",
27
+ "app/models/referral.rb",
28
+ "devise_referable.gemspec",
29
+ "init.rb",
30
+ "lib/devise/hooks/referable.rb",
31
+ "lib/devise_referable.rb",
32
+ "lib/devise_referable/model.rb",
33
+ "lib/devise_referable/routes.rb",
34
+ "rails/init.rb",
35
+ "test/integration/referable_test.rb",
36
+ "test/integration_tests_helper.rb",
37
+ "test/model_tests_helper.rb",
38
+ "test/models/referral_test.rb",
39
+ "test/models_test.rb",
40
+ "test/rails_app/app/controllers/admins_controller.rb",
41
+ "test/rails_app/app/controllers/application_controller.rb",
42
+ "test/rails_app/app/controllers/home_controller.rb",
43
+ "test/rails_app/app/controllers/users_controller.rb",
44
+ "test/rails_app/app/helpers/application_helper.rb",
45
+ "test/rails_app/app/models/blog.rb",
46
+ "test/rails_app/app/models/user.rb",
47
+ "test/rails_app/app/views/home/index.html.erb",
48
+ "test/rails_app/config/boot.rb",
49
+ "test/rails_app/config/database.yml",
50
+ "test/rails_app/config/environment.rb",
51
+ "test/rails_app/config/environments/development.rb",
52
+ "test/rails_app/config/environments/production.rb",
53
+ "test/rails_app/config/environments/test.rb",
54
+ "test/rails_app/config/initializers/backtrace_silencers.rb",
55
+ "test/rails_app/config/initializers/devise.rb",
56
+ "test/rails_app/config/initializers/inflections.rb",
57
+ "test/rails_app/config/initializers/new_rails_defaults.rb",
58
+ "test/rails_app/config/initializers/session_store.rb",
59
+ "test/rails_app/config/routes.rb",
60
+ "test/rails_app/vendor/plugins/devise_referable/init.rb",
61
+ "test/routes_test.rb",
62
+ "test/test_helper.rb"
63
+ ]
64
+ s.homepage = %q{http://github.com/mattvanhorn/devise_referable}
65
+ s.rdoc_options = ["--charset=UTF-8"]
66
+ s.require_paths = ["lib"]
67
+ s.rubygems_version = %q{1.3.6}
68
+ s.summary = %q{An allows referral tracking for devise}
69
+ s.test_files = [
70
+ "test/integration/referable_test.rb",
71
+ "test/integration_tests_helper.rb",
72
+ "test/model_tests_helper.rb",
73
+ "test/models/referral_test.rb",
74
+ "test/models_test.rb",
75
+ "test/rails_app/app/controllers/admins_controller.rb",
76
+ "test/rails_app/app/controllers/application_controller.rb",
77
+ "test/rails_app/app/controllers/home_controller.rb",
78
+ "test/rails_app/app/controllers/users_controller.rb",
79
+ "test/rails_app/app/helpers/application_helper.rb",
80
+ "test/rails_app/app/models/blog.rb",
81
+ "test/rails_app/app/models/user.rb",
82
+ "test/rails_app/config/boot.rb",
83
+ "test/rails_app/config/environment.rb",
84
+ "test/rails_app/config/environments/development.rb",
85
+ "test/rails_app/config/environments/production.rb",
86
+ "test/rails_app/config/environments/test.rb",
87
+ "test/rails_app/config/initializers/backtrace_silencers.rb",
88
+ "test/rails_app/config/initializers/devise.rb",
89
+ "test/rails_app/config/initializers/inflections.rb",
90
+ "test/rails_app/config/initializers/new_rails_defaults.rb",
91
+ "test/rails_app/config/initializers/session_store.rb",
92
+ "test/rails_app/config/routes.rb",
93
+ "test/rails_app/vendor/plugins/devise_referable/init.rb",
94
+ "test/routes_test.rb",
95
+ "test/test_helper.rb"
96
+ ]
97
+
98
+ if s.respond_to? :specification_version then
99
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
100
+ s.specification_version = 3
101
+
102
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
103
+ s.add_development_dependency(%q<mocha>, [">= 0"])
104
+ s.add_development_dependency(%q<webrat>, [">= 0"])
105
+ s.add_runtime_dependency(%q<devise>, ["~> 1.0.0"])
106
+ else
107
+ s.add_dependency(%q<mocha>, [">= 0"])
108
+ s.add_dependency(%q<webrat>, [">= 0"])
109
+ s.add_dependency(%q<devise>, ["~> 1.0.0"])
110
+ end
111
+ else
112
+ s.add_dependency(%q<mocha>, [">= 0"])
113
+ s.add_dependency(%q<webrat>, [">= 0"])
114
+ s.add_dependency(%q<devise>, ["~> 1.0.0"])
115
+ end
116
+ end
117
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'rails/init'
@@ -0,0 +1,13 @@
1
+ # After a user is set, we check to make sure that if they were referred, the
2
+ # referral is updated with the user's id.
3
+ # This will generally happen on registration, but could possibly happen on login
4
+ # in other circumstances where a user was existing in a legacy db for example.
5
+
6
+ Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
7
+ token = warden.env['rack.session'][:referral_token]
8
+ scope = options[:scope]
9
+ if record.respond_to?(:referral) && record.referral.nil? && warden.authenticated?(scope) && token
10
+ record.update_referral(token) if record.respond_to?(:update_referral)
11
+ warden.env['rack.session'][:referral_token] = nil
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ module Devise
2
+ module Models
3
+ # Referable tracks users that arrive at your site via an affiliate link.
4
+ # Currently this is hardcoded as /ref/:referrer_token/path/to/destination
5
+ # TODO: make url configurable
6
+ #
7
+ # Classes that act as referrers are specified in the config, and must
8
+ # have a referrer_token column in the database.
9
+ # TODO: make column name configurable
10
+ #
11
+ # When a visitor arrives at the site via the referral_landing_path, the following things happen:
12
+ # - The referrer is looked up, by doing finds against the referrer_types in order.
13
+ # - If found, a referral record is created with a unique referral_token.
14
+ # - The referral_token is also stored in the session
15
+ # - The visitor is then redirected to the path appended to the referral_landing_path (i.e. /path/to/destination above)
16
+ # - If no path is given, they're redirected to the root path.
17
+ # - If the visitor registers during the session, the referral record is updated with the new user id, and the session token is cleared.
18
+ #
19
+ # Configuration:
20
+ #
21
+ # referrer_types: an array of symbols for classes that can refer users. i.e. [:blog, :customer, :user]
22
+ #
23
+ module Referable
24
+
25
+ def self.included(base)
26
+ base.class_eval do
27
+ has_one :referral, :foreign_key => :recipient_id
28
+ extend ClassMethods
29
+ end
30
+ end
31
+
32
+ def update_referral(token)
33
+ referral = Referral.find_by_referral_token(token)
34
+ if referral
35
+ referral.update_attributes( :recipient_id => self.id,
36
+ :registered_at => self.created_at )
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ module ClassMethods
43
+ Devise::Models.config(self, :referrer_types)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ module DeviseReferable
2
+ module Routes
3
+
4
+ protected
5
+
6
+ def referable(routes, mapping)
7
+ send(:"referral_landing", 'ref/:referrer_token/*path', {:controller => 'referrals', :action => 'create', :conditions => { :method => :get }})
8
+ end
9
+ end
10
+ end
11
+
12
+ ActionController::Routing::RouteSet::Mapper.send :include, DeviseReferable::Routes
@@ -0,0 +1,12 @@
1
+ Devise.module_eval do
2
+ # list of classes that can act as referrer.
3
+ mattr_accessor :referrer_types
4
+ @@referrer_types = []
5
+ end
6
+ Devise.add_module :referable, :controller => :referrals, :model => 'devise_referable/model'
7
+
8
+ module DeviseReferable; end
9
+
10
+ require File.join(File.dirname(__FILE__), '..', 'app', 'models', 'referral')
11
+
12
+ require 'devise_referable/routes'
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'devise_referable'
@@ -0,0 +1,59 @@
1
+ require 'test/test_helper'
2
+ require 'test/integration_tests_helper'
3
+
4
+ class ReferralTest < ActionController::IntegrationTest
5
+
6
+ def setup
7
+ @blog = Blog.create!(:name => 'Referrer', :referrer_token => 'abc123')
8
+ end
9
+
10
+ test 'new users should get referral records' do
11
+ assert_equal 0, Referral.count
12
+ visit referral_landing_path(:referrer_token => 'abc123')
13
+ assert :success
14
+ assert_equal 1, Referral.count
15
+ assert_not_nil session[:referral_token]
16
+
17
+ visit new_user_registration_path
18
+ assert :success
19
+
20
+ fill_in 'email', :with => 'new_user@test.com'
21
+ fill_in 'password', :with => 'new_user123'
22
+ fill_in 'password confirmation', :with => 'new_user123'
23
+ click_button 'Sign up'
24
+
25
+ user = User.last :order => "id"
26
+
27
+ assert user.referral.referrer == @blog
28
+ end
29
+
30
+ test 'existing users should not get referral records' do
31
+ assert_equal 0, Referral.count
32
+
33
+ visit new_user_registration_path
34
+ assert :success
35
+
36
+ fill_in 'email', :with => 'new_user@test.com'
37
+ fill_in 'password', :with => 'new_user123'
38
+ fill_in 'password confirmation', :with => 'new_user123'
39
+ click_button 'Sign up'
40
+ assert :success
41
+
42
+ visit '/ref/abc123'
43
+ assert :success
44
+
45
+ user = User.last :order => "id"
46
+ assert_equal 0, Referral.count
47
+ assert_nil user.referral
48
+ end
49
+
50
+ test 'referral lookup failures should be ignored' do
51
+ assert_equal 0, Referral.count
52
+ visit referral_landing_path(:referrer_token => 'bogus')
53
+ assert :success
54
+
55
+ assert_equal 0, Referral.count
56
+ assert_nil session[:referral_token]
57
+ end
58
+
59
+ end
@@ -0,0 +1,35 @@
1
+ class ActionController::IntegrationTest
2
+
3
+ def warden
4
+ request.env['warden']
5
+ end
6
+
7
+ def sign_in_as_user
8
+ Warden::Proxy.any_instance.stubs(:user).at_least_once.returns(User.new)
9
+ end
10
+
11
+ def create_user(accept_invitation = true)
12
+ user = User.new :email => 'newuser@test.com'
13
+ user.save(false)
14
+ user
15
+ end
16
+
17
+ # Fix assert_redirect_to in integration sessions because they don't take into
18
+ # account Middleware redirects.
19
+ #
20
+ def assert_redirected_to(url)
21
+ assert [301, 302].include?(@integration_session.status),
22
+ "Expected status to be 301 or 302, got #{@integration_session.status}"
23
+
24
+ url = prepend_host(url)
25
+ location = prepend_host(@integration_session.headers["Location"])
26
+ assert_equal url, location
27
+ end
28
+
29
+ protected
30
+
31
+ def prepend_host(url)
32
+ url = "http://#{request.host}#{url}" if url[0] == ?/
33
+ url
34
+ end
35
+ end
@@ -0,0 +1,64 @@
1
+ class ActiveSupport::TestCase
2
+ def setup_mailer
3
+ ActionMailer::Base.deliveries = []
4
+ end
5
+
6
+ def store_translations(locale, translations, &block)
7
+ begin
8
+ I18n.backend.store_translations locale, translations
9
+ yield
10
+ ensure
11
+ I18n.reload!
12
+ end
13
+ end
14
+
15
+ # Helpers for creating new users
16
+ #
17
+ def generate_unique_email
18
+ @@email_count ||= 0
19
+ @@email_count += 1
20
+ "test#{@@email_count}@email.com"
21
+ end
22
+
23
+ def valid_attributes(attributes={})
24
+ { :email => generate_unique_email,
25
+ :password => '123456',
26
+ :password_confirmation => '123456' }.update(attributes)
27
+ end
28
+
29
+ def new_user(attributes={})
30
+ User.new(valid_attributes(attributes))
31
+ end
32
+
33
+ def new_referral(attributes={})
34
+ Referral.new(attributes)
35
+ end
36
+
37
+ def create_user(attributes={})
38
+ User.create!(valid_attributes(attributes))
39
+ end
40
+
41
+ # def create_user_with_invitation(invitation_token, attributes={})
42
+ # user = new_user({:password => nil, :password_confirmation => nil}.update(attributes))
43
+ # user.skip_confirmation!
44
+ # user.invitation_token = invitation_token
45
+ # user.invitation_sent_at = Time.now.utc
46
+ # user.save(false)
47
+ # user
48
+ # end
49
+
50
+ # Execute the block setting the given values and restoring old values after
51
+ # the block is executed.
52
+ def swap(object, new_values)
53
+ old_values = {}
54
+ new_values.each do |key, value|
55
+ old_values[key] = object.send key
56
+ object.send :"#{key}=", value
57
+ end
58
+ yield
59
+ ensure
60
+ old_values.each do |key, value|
61
+ object.send :"#{key}=", value
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,40 @@
1
+ require 'test/test_helper'
2
+ require 'test/model_tests_helper'
3
+
4
+ class ReferableTest < ActiveSupport::TestCase
5
+ def setup
6
+ end
7
+
8
+ test 'should look up referrer' do
9
+ blog = mock()
10
+ Blog.expects(:find_by_referrer_token).with('abc123').returns(blog)
11
+ assert Referral.lookup_referrer('abc123') == blog
12
+ end
13
+
14
+ test 'should return nil if no referrer is found' do
15
+ Blog.expects(:find_by_referrer_token).with('abc123').returns(nil)
16
+ assert_nil Referral.lookup_referrer('abc123')
17
+ end
18
+
19
+ test 'should create referral from token' do
20
+ Blog.expects(:find_by_referrer_token).with('abc123').returns(create_user) # I just need an AR obj here to avoid massive stubbing.
21
+ # Should be a blog not a user.
22
+ result = Referral.from_token('abc123')
23
+ assert result.is_a?( Referral)
24
+ assert_not_nil result.referral_token
25
+ assert_not_nil result.referrer_id
26
+ assert_not_nil result.referrer_type
27
+ assert !result.new_record?
28
+ end
29
+
30
+ test 'should never generate the same referral token for different users' do
31
+ referral_tokens = []
32
+ 10.times do
33
+ ref = new_referral(:referrer_id => 1, :referrer_type => 'Publisher')
34
+ token = ref.generate_token
35
+ assert !referral_tokens.include?(token)
36
+ referral_tokens << token
37
+ end
38
+ end
39
+
40
+ end