Created
April 28, 2011 18:52
-
-
Save derwiki/947017 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/app/controllers/application.rb b/app/controllers/application.rb | |
| index 00e5ce3..3393545 100644 | |
| --- a/app/controllers/application.rb | |
| +++ b/app/controllers/application.rb | |
| @@ -61,6 +61,7 @@ class ApplicationController < ActionController::Base | |
| before_filter :activate_email | |
| before_filter :set_p3p_header | |
| before_filter :set_ua_compatible | |
| + before_filter :track_user | |
| before_filter :redirect_non_www | |
| @@ -174,6 +175,17 @@ class ApplicationController < ActionController::Base | |
| protected | |
| + def track_user | |
| + if viewer.real? && params["track"] | |
| + UserTracking.track!(viewer.id, | |
| + :tags => params["tags"], | |
| + :source_type => params["track_source_type"], | |
| + :source_id => params["track_source_id"]) | |
| + UserTracking.track(viewer.id, "clicked") | |
| + | |
| + end | |
| + end | |
| + | |
| # Use this method if you need someone to be authenticated with Facebook on a | |
| # connect page | |
| def require_fbconnect_auth | |
| diff --git a/app/controllers/earn_controller.rb b/app/controllers/earn_controller.rb | |
| index 0b53dfb..bb8d4fc 100644 | |
| --- a/app/controllers/earn_controller.rb | |
| +++ b/app/controllers/earn_controller.rb | |
| @@ -55,7 +55,7 @@ class EarnController < ApplicationController | |
| # credit came from cause page | |
| funded_by = Cause.find_by_id(cause_id) | |
| if funded_by | |
| - campaign = funded_by.current_fundraising_campaign | |
| + campaign = funded_by.current_fundraising_campaign | |
| end | |
| elsif !campaign_id.blank? | |
| # credit came from campaign page, including Clickforcharity | |
| diff --git a/app/controllers/fb/donations_controller.rb b/app/controllers/fb/donations_controller.rb | |
| index 33af886..329c078 100644 | |
| --- a/app/controllers/fb/donations_controller.rb | |
| +++ b/app/controllers/fb/donations_controller.rb | |
| @@ -339,6 +339,9 @@ class Fb::DonationsController < Fb::ApplicationController | |
| flash[:email] = params[:email] # unnecessary (email on donation object?) | |
| + UserTracking.track(viewer.id, "donated", | |
| + :target => donation) | |
| + | |
| kissmetrics_log_donation(donation) | |
| modesty_log_donation_success | |
| diff --git a/app/models/engagement_credit.rb b/app/models/engagement_credit.rb | |
| index 71a8301..e0b4065 100644 | |
| --- a/app/models/engagement_credit.rb | |
| +++ b/app/models/engagement_credit.rb | |
| @@ -177,7 +177,9 @@ class EngagementCredit < ActiveRecord::Base | |
| ActionCredit.record_earn( user, nil, self ) | |
| end | |
| - | |
| + UserTracking.track(self.user_id, | |
| + "gave a minute", | |
| + :target => self) | |
| end | |
| PROMO_BANNER_NAME = 'socialvibe_alert_banner' | |
| diff --git a/app/models/user_tracking.rb b/app/models/user_tracking.rb | |
| new file mode 100644 | |
| index 0000000..24a8d28 | |
| --- /dev/null | |
| +++ b/app/models/user_tracking.rb | |
| @@ -0,0 +1,63 @@ | |
| +class UserTracking < ActiveRecord::Base | |
| + belongs_to :user | |
| + belongs_to :target, :polymorphic => true | |
| + belongs_to :source, :polymorphic => true | |
| + | |
| + validates_presence_of :user_id | |
| + | |
| + # For activating tracking in outgoing emails | |
| + def self.track_mails(track=true, options = {}) | |
| + if track | |
| + options[:track] = 1 | |
| + ActionMailer::Base.default_url_options.merge!(options) | |
| + else | |
| + ActionMailer::Base.default_url_options.delete(:track) | |
| + end | |
| + end | |
| + | |
| + TRACK_DURATION = 12.hours | |
| + def self.track_source(user_id) | |
| + value = Cacher.get(self.track_key(user_id)) | |
| + end | |
| + def self.tracked?(user_id, value = nil) | |
| + value ||= self.track_source(user_id) | |
| + value && value[:expires] && value[:expires] >= Time.now.to_i | |
| + end | |
| + def self.track!(user_id, options = {}) | |
| + expires_in = options[:expires_in] | |
| + expires_in ||= TRACK_DURATION | |
| + Cacher.set(self.track_key(user_id), Time.now+expires_in) do | |
| + result = {:expires => (Time.now+expires_in).to_i} | |
| + | |
| + [:source_id, :source_type, :tags].each do |key| | |
| + result[key] = options[key] if options[key] | |
| + end | |
| + | |
| + if options[:source] | |
| + result.merge!({:source_type => options[:source].class.name, | |
| + :source_id => options[:source].id}) | |
| + end | |
| + result | |
| + end | |
| + end | |
| + def self.stop_tracking!(user_id) | |
| + Cacher.delete(self.track_key(user_id)) | |
| + end | |
| + | |
| + def self.track(user_id, message, options={}) | |
| + value = self.track_source(user_id) | |
| + return if !self.tracked?(user_id, value) | |
| + | |
| + logger.info("UserTracking.track user_id: #{user_id} message: #{message}") | |
| + options.merge!({:user_id => user_id, | |
| + :source_type => value[:source_type], | |
| + :source_id => value[:source_id], | |
| + :message => message}) | |
| + self.create!(options) | |
| + end | |
| + | |
| + protected | |
| + def self.track_key(user_id) | |
| + "track-user-#{user_id}" | |
| + end | |
| +end | |
| diff --git a/db/migrate/20110426201659_create_user_trackings.rb b/db/migrate/20110426201659_create_user_trackings.rb | |
| new file mode 100644 | |
| index 0000000..565aca2 | |
| --- /dev/null | |
| +++ b/db/migrate/20110426201659_create_user_trackings.rb | |
| @@ -0,0 +1,25 @@ | |
| +class CreateUserTrackings < ActiveRecord::Migration | |
| + def self.up | |
| + create_table :user_trackings do |t| | |
| + t.column :user_id, :integer | |
| + | |
| + t.column :source_id, :integer | |
| + t.column :source_type, :string | |
| + | |
| + t.column :target_id, :integer | |
| + t.column :target_type, :string | |
| + | |
| + t.column :message, :string | |
| + | |
| + t.datetime :created_at | |
| + end | |
| + | |
| + add_index :user_trackings, :user_id | |
| + add_index :user_trackings, [:source_id, :source_type] | |
| + add_index :user_trackings, :target_type | |
| + end | |
| + | |
| + def self.down | |
| + drop_table :user_trackings | |
| + end | |
| +end | |
| diff --git a/db/migrate/20110427184234_user_tracking_tags.rb b/db/migrate/20110427184234_user_tracking_tags.rb | |
| new file mode 100644 | |
| index 0000000..b7aa2ad | |
| --- /dev/null | |
| +++ b/db/migrate/20110427184234_user_tracking_tags.rb | |
| @@ -0,0 +1,9 @@ | |
| +class UserTrackingTags < ActiveRecord::Migration | |
| + def self.up | |
| + add_column :user_trackings, :tags, :string | |
| + end | |
| + | |
| + def self.down | |
| + remove_column :user_trackings, :tags | |
| + end | |
| +end | |
| diff --git a/test/functional/controllers/earn_controller_testspec.rb b/test/functional/controllers/earn_controller_testspec.rb | |
| index 94793f8..df98f34 100644 | |
| --- a/test/functional/controllers/earn_controller_testspec.rb | |
| +++ b/test/functional/controllers/earn_controller_testspec.rb | |
| @@ -67,6 +67,61 @@ context "The earn controller" do | |
| cause.destroy | |
| end | |
| + specify "should track the user" do | |
| + Cacher.cache = CACHE | |
| + | |
| + advertiser = a.EarnAdvertiser.appears | |
| + advertiser.name = "Supersonic" | |
| + advertiser.save | |
| + | |
| + user = a.User.appears | |
| + cause = a.Cause.appears | |
| + | |
| + advertiser = EarnAdvertiser.const_get(advertiser.name).find(advertiser.id) | |
| + | |
| + params = { | |
| + "activity_id" => "11", | |
| + "campaign_id" => cause.current_fundraising_campaign.id.to_s, | |
| + "cause_id" => cause.id.to_s, | |
| + "network_user_id" => user.anonymous_id, | |
| + "partner_key" => advertiser.partner_key, | |
| + "revenue" => "0.077" | |
| + } | |
| + | |
| + sig = advertiser.generate_callback_sig(params) | |
| + params[:sig] = sig | |
| + | |
| + UserTracking.track!(user.id, | |
| + :source_type => "Foo", | |
| + :source_id => 15) | |
| + | |
| + assert_difference("UserTracking.count") do | |
| + assert_difference('EngagementCredit.count') do | |
| + post :credit_callback, params | |
| + end | |
| + end | |
| + | |
| + ec = EngagementCredit.last | |
| + log_entry = EarnCallbackLog.last | |
| + ec.funded_by.should == cause | |
| + ec.campaign.should == cause.current_fundraising_campaign | |
| + log_entry.response_code.should == "200" | |
| + log_entry.network_user_id.should == user.anonymous_id | |
| + assert_response 200 | |
| + | |
| + advertiser.destroy | |
| + user.destroy | |
| + cause.destroy | |
| + | |
| + track = UserTracking.last | |
| + track.target.should == ec | |
| + track.source_id.should == 15 | |
| + track.source_type.should == "Foo" | |
| + track.user_id.should == user.id | |
| + | |
| + Cacher.cache = nil | |
| + end | |
| + | |
| # TODO test that invalid signatures are thrown out | |
| specify "should update tracking counters" do | |
| @@ -80,9 +135,9 @@ context "The earn controller" do | |
| old_value = engagement.send(counter) | |
| post :track_engagement_counter, { | |
| - :advertiser_id => advertiser.id, | |
| - :counter => counter, | |
| - :engagement_id => engagement.engagement_id | |
| + :advertiser_id => advertiser.id, | |
| + :counter => counter, | |
| + :engagement_id => engagement.engagement_id | |
| } | |
| engagement.reload | |
| diff --git a/test/functional/controllers/fb/donations_controller_testspec.rb b/test/functional/controllers/fb/donations_controller_testspec.rb | |
| index f1f133c..c7940c7 100644 | |
| --- a/test/functional/controllers/fb/donations_controller_testspec.rb | |
| +++ b/test/functional/controllers/fb/donations_controller_testspec.rb | |
| @@ -279,6 +279,59 @@ context 'Submitting a donation form' do | |
| :donation => {:beneficiary_id => Beneficiary.find(:first).id}, | |
| :credit_card => {:exp_month => 1} | |
| end | |
| + | |
| + specify "should track the user" do | |
| + Cacher.cache = CACHE | |
| + UserTracking.track!(@cause.creator_id, | |
| + :source_type => "Foo", | |
| + :source_id => 15) | |
| + | |
| + assert_difference('UserTracking.count') do | |
| + post :create, | |
| + :cause_id => @cause.id, | |
| + :donation => {:donor_id => @cause.creator_id, | |
| + :beneficiary_id => Beneficiary.find(:first).id}, | |
| + :email => @cause.creator.email, | |
| + :processor => "NFG", | |
| + :credit_card => {:exp_month => 1} | |
| + end | |
| + | |
| + tracking = UserTracking.last | |
| + | |
| + tracking.user.should == @cause.creator | |
| + tracking.source_id.should == 15 | |
| + tracking.source_type.should == "Foo" | |
| + tracking.target.should == Donation.last | |
| + tracking.message.should == "donated" | |
| + Cacher.cache = nil | |
| + end | |
| + | |
| + specify "should track the user with proper params" do | |
| + Cacher.cache = CACHE | |
| + | |
| + # 2 because we also store when the user shows up the 1st time | |
| + assert_difference('UserTracking.count', 2) do | |
| + post :create, | |
| + :track => 1, | |
| + :track_source_type => "Foo", | |
| + :track_source_id => 15, | |
| + :cause_id => @cause.id, | |
| + :donation => {:donor_id => @cause.creator_id, | |
| + :beneficiary_id => Beneficiary.find(:first).id}, | |
| + :email => @cause.creator.email, | |
| + :processor => "NFG", | |
| + :credit_card => {:exp_month => 1} | |
| + end | |
| + | |
| + tracking = UserTracking.last | |
| + | |
| + tracking.user.should == @cause.creator | |
| + tracking.source_id.should == 15 | |
| + tracking.source_type.should == "Foo" | |
| + tracking.target.should == Donation.last | |
| + tracking.message.should == "donated" | |
| + Cacher.cache = nil | |
| + end | |
| end | |
| context 'Viewing donations/new without cause_id' do | |
| diff --git a/test/functional/models/user_tracking_testspec.rb b/test/functional/models/user_tracking_testspec.rb | |
| new file mode 100644 | |
| index 0000000..2c5e25d | |
| --- /dev/null | |
| +++ b/test/functional/models/user_tracking_testspec.rb | |
| @@ -0,0 +1,105 @@ | |
| +require File.expand_path('../functional_test_helper', File.dirname(__FILE__)) | |
| + | |
| + | |
| +context "UserTracking email parsing" do | |
| + include ActionController::UrlWriter | |
| + setup do | |
| + @cause = a.Cause.exists | |
| + end | |
| + | |
| + it "Should add proper tags in links" do | |
| + view = ActionView::Base.new(ActionController::Base.view_paths, {}) | |
| + | |
| + cause_url(@cause).should == "http://test.host/causes/#{@cause.id}"\ | |
| + "-#{@cause.name.parameterize}" | |
| + UserTracking.track_mails | |
| + cause_url(@cause).should == "http://test.host/causes/#{@cause.id}"\ | |
| + "-#{@cause.name.parameterize}?track=1" | |
| + | |
| + UserTracking.track_mails(true, | |
| + :track_source_id => 14, | |
| + :track_user_type => "Fool") | |
| + cause_url(@cause).should == "http://test.host/causes/48-frofrank-"\ | |
| + "cruthunt-fryfryza-shojestyng?track=1&track_source_id=14&"\ | |
| + "track_user_type=Fool" | |
| + end | |
| +end | |
| + | |
| +context "UserTracking" do | |
| + setup do | |
| + @user = a.User.exists | |
| + Cacher.cache = CACHE | |
| + UserTracking.stop_tracking!(@user.id) | |
| + end | |
| + | |
| + specify "should not track" do | |
| + assert_no_difference('UserTracking.count') do | |
| + UserTracking.track(@user.id, "Tracking something") | |
| + end | |
| + end | |
| + | |
| + specify "should track" do | |
| + UserTracking.track!(@user.id) | |
| + assert_difference('UserTracking.count') do | |
| + UserTracking.track(@user.id, "Tracking something") | |
| + end | |
| + end | |
| + | |
| + specify "should track with source id" do | |
| + UserTracking.track!(@user.id, | |
| + :source_type => "Foo", | |
| + :source_id => 15) | |
| + assert_difference('UserTracking.count') do | |
| + UserTracking.track(@user.id, "Tracking something") | |
| + end | |
| + | |
| + UserTracking.last.source_type.should == "Foo" | |
| + UserTracking.last.source_id.should == 15 | |
| + end | |
| + | |
| + specify "should track with source" do | |
| + UserTracking.track!(@user.id, | |
| + :source => @user) | |
| + assert_difference('UserTracking.count') do | |
| + UserTracking.track(@user.id, "Tracking something") | |
| + end | |
| + | |
| + UserTracking.last.source.should == @user | |
| + end | |
| + | |
| + specify "should track with source and target id" do | |
| + UserTracking.track!(@user.id, | |
| + :source => @user) | |
| + assert_difference('UserTracking.count') do | |
| + UserTracking.track(@user.id, "Tracking something", | |
| + :target_type => @user.class.name, | |
| + :target_id => @user.id) | |
| + end | |
| + | |
| + UserTracking.last.source.should == @user | |
| + UserTracking.last.target.should == @user | |
| + end | |
| + | |
| + specify "should track with source and target" do | |
| + UserTracking.track!(@user.id, | |
| + :source => @user) | |
| + assert_difference('UserTracking.count') do | |
| + UserTracking.track(@user.id, "Tracking something", | |
| + :target => @user) | |
| + end | |
| + | |
| + UserTracking.last.source.should == @user | |
| + UserTracking.last.target.should == @user | |
| + end | |
| + | |
| + specify "should not track after a while" do | |
| + UserTracking.track!(@user.id) | |
| + Time.warp(Time.now+24.hours) do | |
| + assert_no_difference('UserTracking.count') do | |
| + UserTracking.track(@user.id, "Tracking something") | |
| + end | |
| + end | |
| + Time.warp(nil) | |
| + end | |
| +end | |
| + | |
| diff --git a/test/unit/models/earn_engagement_testspec.rb b/test/unit/models/earn_engagement_testspec.rb | |
| index 5bda2d5..1e453a5 100644 | |
| --- a/test/unit/models/earn_engagement_testspec.rb | |
| +++ b/test/unit/models/earn_engagement_testspec.rb | |
| @@ -20,7 +20,7 @@ context "An earn engagement" do | |
| value = @engagement.send(name) | |
| EarnEngagement.increment_tracked_counter(name, | |
| - @engagement.earn_advertiser_id, @engagement.engagement_id) | |
| + @engagement.earn_advertiser_id, @engagement.engagement_id) | |
| @engagement.reload | |
| @engagement.send(name).should == value + 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment