sift 1.0.5

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.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ **.swp
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sift.gemspec
4
+ gemspec
data/HISTORY ADDED
@@ -0,0 +1,3 @@
1
+
2
+ === 1.0 2012-05-02
3
+ * Initial release
@@ -0,0 +1,41 @@
1
+ = Sift Science Ruby bindings
2
+
3
+ == Installation
4
+
5
+ If you want to build the gem from source:
6
+
7
+ $ gem build sift.gemspec
8
+
9
+ Alternatively, you can install the gem from Rubyforge:
10
+
11
+ $ gem install sift
12
+
13
+ == Requirements
14
+
15
+ * Ruby 1.8.7 or above. (Ruby 1.8.6 might work if you load ActiveSupport.)
16
+ * HTTParty, 0.8.3 or greater
17
+
18
+ For development only:
19
+ * bundler
20
+ * rspec, 2.9 or greater
21
+ * fakeweb, 1.3 or greater
22
+
23
+ == Building
24
+
25
+ Building and publishing the gem is captured by the following steps:
26
+
27
+ $ gem build sift.gemspec
28
+ $ gem push sift-<current version>.gem
29
+
30
+ $ bundle
31
+ $ rake -T
32
+ $ rake build
33
+ $ rake install
34
+ $ rake release
35
+
36
+ == Testing
37
+
38
+ To run the various tests use the rake command as follows:
39
+
40
+ $ rake spec:unit
41
+ $ rake spec:integration
@@ -0,0 +1,14 @@
1
+ begin
2
+ require "bundler/gem_tasks"
3
+ Bundler::GemHelper.install_tasks
4
+ rescue LoadError => e
5
+ warn "It is recommended that you use bundler during development: gem install bundler"
6
+ end
7
+
8
+ require "rspec/core/rake_task"
9
+
10
+ desc "Run tests"
11
+ RSpec::Core::RakeTask.new(:spec)
12
+
13
+ task :default => :spec
14
+ task :test => :spec
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # A simple example of how to use the API.
4
+
5
+ require 'rubygems'
6
+ require 'sift'
7
+ require 'multi_json'
8
+
9
+ api_key = "" # TODO: Set your API key here
10
+
11
+ class MyLogger
12
+ def warn(e)
13
+ puts "[WARN] " + e.to_s
14
+ end
15
+
16
+ def error(e)
17
+ puts "[ERROR] " + e.to_s
18
+ end
19
+
20
+ def fatal(e)
21
+ puts "[FATAL] " + e.to_s
22
+ end
23
+
24
+ def info(e)
25
+ puts "[INFO] " + e.to_s
26
+ end
27
+ end
28
+
29
+ Sift.logger = MyLogger.new
30
+
31
+ client = Sift::Client.new(api_key)
32
+ event = "my_custom_event"
33
+ properties = {
34
+ "my_custom_field1" => "my custom value 1",
35
+ "my_custom_field2" => "my custom value 2",
36
+ "$user_id" => "3",
37
+ "$time" => Time.now.to_i,
38
+ }
39
+
40
+ response = client.track(event, properties)
41
+ if response.nil?
42
+ puts 'Error: there was an HTTP error calling through the API'
43
+ else
44
+ puts 'Successfully sent request; was ok? : ' + response.ok?.to_s
45
+ puts 'API error message : ' + response.api_error_message.to_s
46
+ puts 'API status code : ' + response.api_status.to_s
47
+ puts 'HTTP status code : ' + response.http_status_code.to_s
48
+ puts 'original request : ' + response.original_request.to_s
49
+ end
50
+
@@ -0,0 +1,33 @@
1
+ require "sift/version"
2
+ require "sift/client"
3
+
4
+ module Sift
5
+
6
+ # Returns the path for the current API version
7
+ def self.current_rest_api_path
8
+ "/v202/events"
9
+ end
10
+
11
+ # Sets the Output logger to use within the client. This can be left uninitializaed
12
+ # but is useful for debugging.
13
+ def self.logger=(logger)
14
+ @logger = logger
15
+ end
16
+
17
+ def self.info(msg)
18
+ @logger.info(msg) if @logger
19
+ end
20
+
21
+ def self.warn(msg)
22
+ @logger.warn(msg) if @logger
23
+ end
24
+
25
+ def self.error(msg)
26
+ @logger.error(msg) if @logger
27
+ end
28
+
29
+ def self.fatal(msg)
30
+ @logger.fatal(msg) if @logger
31
+ end
32
+
33
+ end
@@ -0,0 +1,108 @@
1
+ require 'httparty'
2
+ require 'multi_json'
3
+
4
+ module Sift
5
+
6
+ # Represents the payload returned from a call through the track API
7
+ #
8
+ class Response
9
+ attr_reader :json
10
+ attr_reader :http_status_code
11
+ attr_reader :api_status
12
+ attr_reader :api_error_message
13
+ attr_reader :original_request
14
+
15
+ # Constructor
16
+ #
17
+ # == Parameters:
18
+ # http_response
19
+ # The HTTP body text returned from the API call. The body is expected to be
20
+ # a JSON object that can be decoded into status, message and request
21
+ # sections.
22
+ #
23
+ def initialize(http_response, http_response_code)
24
+ @json = MultiJson.load(http_response)
25
+ @original_request = MultiJson.load(@json["request"].to_s) if @json["request"]
26
+ @http_status_code = http_response_code
27
+ @api_status = @json["status"].to_i
28
+ @api_error_message = @json["error_message"].to_s
29
+ end
30
+
31
+ # Helper method returns true if and only if the response from the API call was
32
+ # successful
33
+ #
34
+ # == Returns:
35
+ # true on success; false otherwise
36
+ def ok?
37
+ 0 == @api_status.to_i
38
+ end
39
+ end
40
+
41
+ # This class wraps accesses through the API
42
+ #
43
+ class Client
44
+ API_ENDPOINT = "https://api.siftscience.com"
45
+ API_TIMEOUT = 2
46
+
47
+ include HTTParty
48
+ base_uri API_ENDPOINT
49
+ default_timeout API_TIMEOUT
50
+
51
+ # Constructor
52
+ #
53
+ # == Parameters:
54
+ # api_key
55
+ # The Sift Science API key associated with your customer account. This parameter
56
+ # cannot be nil or blank.
57
+ # path
58
+ # The path to the event API, e.g., "/v201/events"
59
+ #
60
+ def initialize(api_key, path = Sift.current_rest_api_path)
61
+ @api_key = api_key.to_s
62
+ @path = path
63
+ raise(RuntimeError, "api_key is required") if @api_key.nil? || @api_key.empty?
64
+ end
65
+
66
+ # Tracks an event and associated properties through the Sift Science API. This call
67
+ # is blocking.
68
+ #
69
+ # == Parameters:
70
+ # event
71
+ # The name of the event to send. This can be either a reserved event name, like
72
+ # $transaction or $label or a custom event name (that does not start with a $).
73
+ # This parameter must be specified.
74
+ #
75
+ # properties
76
+ # A hash of name-value pairs that specify the event-specific attributes to track.
77
+ # This parameter must be specified.
78
+ #
79
+ # timeout
80
+ # The number of seconds to wait before failing the request. By default this is
81
+ # configured to 2 seconds (see above). This parameter is optional.
82
+ #
83
+ # == Returns:
84
+ # In the case of an HTTP error (timeout, broken connection, etc.), this
85
+ # method returns nil; otherwise, a Response object is returned and captures
86
+ # the status message and status code. In general, you can ignore the returned
87
+ # result, though.
88
+ #
89
+ def track(event, properties = {}, timeout = nil)
90
+
91
+ raise(RuntimeError, "event must be a string") if event.nil? || event.to_s.empty?
92
+ raise(RuntimeError, "properties cannot be empty") if properties.empty?
93
+
94
+ options = {
95
+ :body => MultiJson.dump(properties.merge({"$type" => event,
96
+ "$api_key" => @api_key})),
97
+ }
98
+ options.merge!(:timeout => timeout) unless timeout.nil?
99
+ begin
100
+ response = self.class.post(@path, options)
101
+ Response.new(response.body, response.code)
102
+ rescue StandardError => e
103
+ Sift.warn("Failed to track event: " + e.to_s)
104
+ Sift.warn(e.backtrace)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,3 @@
1
+ module Sift
2
+ VERSION = "1.0.5"
3
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "sift/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sift"
7
+ s.version = Sift::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Fred Sadaghiani"]
10
+ s.email = ["freds@siftscience.com"]
11
+ s.homepage = "http://siftscience.com"
12
+ s.summary = %q{Sift Science Ruby API Gem}
13
+ s.description = %q{Sift Science Ruby API. Please see http://siftscience.com for more details.}
14
+
15
+ s.rubyforge_project = "sift"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ # Gems that must be intalled for sift to compile and build
23
+ s.add_development_dependency "rspec", "~> 2.9.0"
24
+ s.add_development_dependency "fakeweb", "~> 1.3.0"
25
+
26
+ # Gems that must be intalled for sift to work
27
+ s.add_dependency "httparty", ">= 0.8.3"
28
+ s.add_dependency "multi_json", ">= 1.3.4"
29
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+
3
+ describe Sift do
4
+
5
+
6
+
7
+ end
@@ -0,0 +1,10 @@
1
+
2
+ require "bundler/setup"
3
+ require "sift"
4
+ require "fakeweb"
5
+
6
+ # Setup Fakeweb
7
+ FakeWeb.allow_net_connect = false
8
+
9
+ RSpec.configure do |config|
10
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+
3
+ describe Sift::Client do
4
+
5
+ def valid_transaction_properties
6
+ {
7
+ :$buyer_user_id => "123456",
8
+ :$seller_user_id => "654321",
9
+ :$amount => 1253200,
10
+ :$currency_code => "USD",
11
+ :$time => Time.now.to_i,
12
+ :$transaction_id => "my_transaction_id",
13
+ :$billing_name => "Mike Snow",
14
+ :$billing_bin => "411111",
15
+ :$billing_last4 => "1111",
16
+ :$billing_address1 => "123 Main St.",
17
+ :$billing_city => "San Francisco",
18
+ :$billing_region => "CA",
19
+ :$billing_country => "US",
20
+ :$billing_zip => "94131",
21
+ :$buyer_email => "mike@example.com"
22
+ }
23
+ end
24
+
25
+ def fully_qualified_api_endpoint
26
+ Sift::Client::API_ENDPOINT + Sift.current_rest_api_path
27
+ end
28
+
29
+ it "Cannot instantiate client with nil or blank api key" do
30
+ lambda { Sift::Client.new(nil) }.should raise_error
31
+ lambda { Sift::Client.new("") }.should raise_error
32
+ end
33
+
34
+ it "Track call must specify an event name" do
35
+ lambda { Sift::Client.new("foo").track(nil) }.should raise_error
36
+ lambda { Sift::Client.new("foo").track("") }.should raise_error
37
+ end
38
+
39
+ it "Must specify an event name" do
40
+ lambda { Sift::Client.new("foo").track(nil) }.should raise_error
41
+ lambda { Sift::Client.new("foo").track("") }.should raise_error
42
+ end
43
+
44
+ it "Must specify properties" do
45
+ event = "custom_event_name"
46
+ lambda { Sift::Client.new("foo").track(event) }.should raise_error
47
+ end
48
+
49
+ it "Doesn't raise an exception on Net/HTTP errors" do
50
+
51
+ FakeWeb.register_uri(:post, fully_qualified_api_endpoint,
52
+ :body => nil, :exception => Net::HTTPError)
53
+
54
+ api_key = "foobar"
55
+ event = "$transaction"
56
+ properties = valid_transaction_properties
57
+
58
+ # This method should just return false -- the track call failed because
59
+ # of an HTTP error
60
+ Sift::Client.new(api_key).track(event, properties).should eq(nil)
61
+ end
62
+
63
+ it "Successfuly handles an event and returns OK" do
64
+
65
+ response_json = { :status => 0, :error_message => "OK" }
66
+
67
+ FakeWeb.register_uri(:post, fully_qualified_api_endpoint,
68
+ :body => MultiJson.dump(response_json),
69
+ :status => [Net::HTTPOK, "OK"],
70
+ :content_type => "text/json")
71
+
72
+ api_key = "foobar"
73
+ event = "$transaction"
74
+ properties = valid_transaction_properties
75
+
76
+ response = Sift::Client.new(api_key).track(event, properties)
77
+ response.ok?.should eq(true)
78
+ response.api_status.should eq(0)
79
+ response.api_error_message.should eq("OK")
80
+ end
81
+
82
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+
3
+ describe Sift do
4
+
5
+
6
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sift
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.5
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Fred Sadaghiani
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-02 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70093902351140 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.9.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70093902351140
25
+ - !ruby/object:Gem::Dependency
26
+ name: fakeweb
27
+ requirement: &70093902438840 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 1.3.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70093902438840
36
+ - !ruby/object:Gem::Dependency
37
+ name: httparty
38
+ requirement: &70093902565360 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 0.8.3
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70093902565360
47
+ - !ruby/object:Gem::Dependency
48
+ name: multi_json
49
+ requirement: &70093902656720 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.4
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70093902656720
58
+ description: Sift Science Ruby API. Please see http://siftscience.com for more details.
59
+ email:
60
+ - freds@siftscience.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - HISTORY
68
+ - README.rdoc
69
+ - Rakefile
70
+ - examples/simple.rb
71
+ - lib/sift.rb
72
+ - lib/sift/client.rb
73
+ - lib/sift/version.rb
74
+ - sift.gemspec
75
+ - spec/integration/sift_spec.rb
76
+ - spec/spec_helper.rb
77
+ - spec/unit/client_spec.rb
78
+ - spec/unit/sift_spec.rb
79
+ homepage: http://siftscience.com
80
+ licenses: []
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project: sift
99
+ rubygems_version: 1.8.10
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Sift Science Ruby API Gem
103
+ test_files:
104
+ - spec/integration/sift_spec.rb
105
+ - spec/spec_helper.rb
106
+ - spec/unit/client_spec.rb
107
+ - spec/unit/sift_spec.rb