saas_pulse-ruby 0.1.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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Jonah Honeyman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
20
+
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ saas\_pulse-ruby
2
+ ================
3
+
4
+ A simple API wrapper for integrating your rails application with [SaaSPulse](http://www.saaspulse.com).
5
+
6
+ Installation
7
+ ------------
8
+
9
+ `gem install saas_pulse-ruby`
10
+
11
+ Usage
12
+ -----
13
+
14
+ First, build your client with your API id:
15
+
16
+ SaasPulse.srv_id "YOUR_ID_GOES_HERE"
17
+
18
+ You can then interact with `SaasPulse.client` to do your bidding:
19
+
20
+ SaasPulse.client.track({
21
+ :organization => "Current organization",
22
+ :user => "Current user",
23
+ :activity => "Current activity",
24
+ :module => "Current module"
25
+ })
26
+
27
+ There is also the option for integration with different ruby frameworks.
28
+
29
+ ### Rails
30
+
31
+ class ApplicationController < ActionController::Base
32
+ include SaasPulse::Adapters::Rails
33
+
34
+ #...
35
+ end
36
+
37
+ That will build your tracking code based around a couple of sane defaults. By default it will set the current module to `params[:controller]` and activity to `params[:action]`. If you wish to override the defaults you can do so in your controllers:
38
+
39
+ class MyController < ApplictationController
40
+ sp_default :activity, "Whatever you want here"
41
+ # You may also send a Proc object as the value so that it is
42
+ # evaluated in the context of the current controller. For example:
43
+ sp_default :user, proc { method_to_determine_current_user }
44
+ end
45
+
46
+ To track different actions, you must now tell SaasPulse which actions you would like to track:
47
+
48
+ class MyController < ApplictationController
49
+ track :index
50
+ track :show, "Override default activity text here"
51
+ track :edit, :user => "override other defaults in a hash"
52
+ track :destroy, :if => proc { params[:my_boolean] } # Use conditionals to only run tracking based on the eval'd code in the Proc object
53
+ end
54
+
55
+ ### Rolling your own adapter
56
+
57
+ There are currently adapters for rails and merb, but it is simple to write your own adapter
58
+
59
+ module MySPAdapter
60
+ extend SaasPulse::Adapters::Base
61
+
62
+ register_adapter :my_adapter
63
+ hook_method :before_hook # Hook method name that will be called before or after each action
64
+ action_finder :action_name # Method that determines the current action being hit
65
+
66
+ # You can set defaults from here that will be set on the controller class
67
+ # that includes your adapter and all of its subclasses
68
+ sp_default :activity, proc {action_name}
69
+ sp_default :module, proc {controller_name}
70
+ end
71
+
72
+ TODO
73
+ ----
74
+
75
+ * Adapter tests
76
+ * JS client integration
@@ -0,0 +1,9 @@
1
+ module SaasPulse
2
+ class << self; attr_accessor :adapter end
3
+
4
+ class Adapter
5
+ attr_accessor :name, :hook, :action_finder
6
+ end
7
+ end
8
+
9
+
@@ -0,0 +1,41 @@
1
+ module SaasPulse
2
+ module Adapters
3
+ module Base
4
+ def self.extended(base)
5
+ base.instance_variable_set :@__current_adapter__, SaasPulse::Adapter.new
6
+ end
7
+
8
+ private
9
+
10
+ def included(klass)
11
+ SaasPulse.adapter = adapter
12
+ klass.send(:include, SaasPulse::Resource) unless klass.include?(SaasPulse::Resource)
13
+ (@defaults || []).each do |e|
14
+ klass.sp_default *e
15
+ end
16
+ end
17
+
18
+ def sp_default(k, v)
19
+ @defaults ||= []
20
+ @defaults << [k,v]
21
+ end
22
+
23
+ def register_adapter(name)
24
+ adapter.name = name
25
+ end
26
+
27
+ def hook_method(name)
28
+ adapter.hook = name
29
+ end
30
+
31
+ def action_finder(name)
32
+ adapter.action_finder = name
33
+ end
34
+
35
+ def adapter
36
+ @__current_adapter__
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,15 @@
1
+ module SaasPulse
2
+ module Adapters
3
+ module Merb
4
+ extend SaasPulse::Adapters::Base
5
+
6
+ register_adapter :merb
7
+ hook_method :after
8
+ action_finder :action_name
9
+
10
+ sp_default :activity, proc { action_name }
11
+ sp_default :module, proc { controller_name }
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,15 @@
1
+ module SaasPulse
2
+ module Adapters
3
+ module Rails
4
+ extend SaasPulse::Adapters::Base
5
+
6
+ register_adapter :rails
7
+ hook_method :after_filter
8
+ action_finder :action_name
9
+
10
+ sp_default :activity, proc { action_name }
11
+ sp_default :module, proc { controller_name }
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,60 @@
1
+ module SaasPulse
2
+ class InvalidParamError < StandardError; end
3
+
4
+ class ArgParser
5
+ class <<self
6
+ attr_reader :named_args
7
+
8
+ def parse(args)
9
+ new.tap do |parser|
10
+ args.each do |arg, val|
11
+ param = registered_args[arg]
12
+ raise InvalidParamError, "'#{arg}' does not map to a valid param" unless param
13
+
14
+ parser[param] = val
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def parses_arg(name, *aliases)
22
+ register_named_arg! name
23
+ attr_reader name
24
+
25
+ aliases.unshift(name).each do |argname|
26
+ registered_args[argname] = name
27
+ end
28
+ end
29
+
30
+ def registered_args
31
+ @__registered_args__ ||= {}
32
+ end
33
+
34
+ def register_named_arg!(name)
35
+ @named_args ||= []
36
+ @named_args << name
37
+ end
38
+ end
39
+
40
+ parses_arg :sdr_a, :a, :act, :activity
41
+ parses_arg :sdr_o, :o, :org, :organization
42
+ parses_arg :sdr_m, :m, :mod, :module
43
+ parses_arg :sdr_u, :u, :user
44
+
45
+ def to_params
46
+ ArgParser.named_args.map do |arg|
47
+ [arg, CGI.escape(self[arg].to_s)].join("=")
48
+ end.join("&")
49
+ end
50
+
51
+ def [](arg)
52
+ instance_variable_get :"@#{arg}"
53
+ end
54
+
55
+ def []=(arg, val)
56
+ instance_variable_set :"@#{arg}", val
57
+ end
58
+ end
59
+ end
60
+
@@ -0,0 +1,47 @@
1
+ module SaasPulse
2
+ BASE_URI = "http://sdr.saaspulse.com/pixel.gif/?sdr_s=".freeze unless self.const_defined?(:BASE_URI)
3
+
4
+ class NoClientError < StandardError; end
5
+
6
+ class << self
7
+ attr_reader :client
8
+
9
+ def track(data)
10
+ raise NoClientError, "You must set the current client first" unless client
11
+ client.track(data)
12
+ end
13
+
14
+ def srv_id(srv_id)
15
+ @client = Client.new(srv_id)
16
+ end
17
+
18
+ def on?
19
+ !!@on
20
+ end
21
+
22
+ def on!
23
+ @on = true
24
+ end
25
+ end
26
+
27
+ class Client
28
+ def initialize(srv_id)
29
+ @srv_id = srv_id
30
+ end
31
+
32
+ def track(data={})
33
+ url = build_url(data)
34
+
35
+ if SaasPulse.on?
36
+ Thread.new {open(url)}
37
+ else
38
+ puts "[SaasPulse] Fake call to #{url}. To make a real call, run SaasPulse.on!"
39
+ end
40
+ end
41
+
42
+ def build_url(data)
43
+ [BASE_URI, @srv_id, "&", ArgParser.parse(data).to_params].join
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,80 @@
1
+ module SaasPulse
2
+ class NoAdapterError < StandardError; end
3
+
4
+ module Resource
5
+ @sp_defaults = {
6
+ :organization => "Default Org",
7
+ :user => "Default User",
8
+ :activity => "Default Activity",
9
+ :module => "Default Module"
10
+ }
11
+
12
+ module ClassMethods
13
+ def sp_default(key, val)
14
+ raise ArgumentError, "Key #{key.inspect} is not a valid option" unless @sp_defaults.keys.member?(key)
15
+
16
+ sp_defaults[key] = val
17
+ end
18
+
19
+ # action<Symbol>:: Action to track
20
+ # opts<Hash>:: Override defaults and set conditional tracking
21
+ def track(action, *opts)
22
+ tracker = SaasPulse::Tracker.new(action, *opts)
23
+ sp_trackers << tracker unless sp_trackers.find {|t| t.action.to_s == action.to_s}
24
+ end
25
+
26
+ def sp_trackers
27
+ @__sp_trackers__ ||= []
28
+ end
29
+
30
+ private
31
+
32
+ def inherited(klass)
33
+ super(klass)
34
+ klass.instance_variable_set :@sp_defaults, @sp_defaults.dup
35
+ end
36
+ end
37
+
38
+ def self.included(base)
39
+ base.extend ClassMethods
40
+ class << base; attr_reader :sp_defaults end
41
+ base.instance_variable_set :@sp_defaults, @sp_defaults.dup
42
+ base.send(SaasPulse.adapter.hook, :sp_run)
43
+ end
44
+
45
+ private
46
+
47
+ def sp_run
48
+ raise NoAdapterError, "No adapter has been set" unless SaasPulse.adapter
49
+
50
+ tracker = self.class.sp_trackers.find do |t|
51
+ t.action.to_s == send(SaasPulse.adapter.action_finder).to_s
52
+ end
53
+
54
+ return unless tracker
55
+
56
+ if condition = tracker.opts[:if]
57
+ return unless instance_eval(&condition)
58
+ end
59
+
60
+ SaasPulse.track({
61
+ :o => sp_opt(tracker, :organization),
62
+ :a => sp_opt(tracker, :activity),
63
+ :m => sp_opt(tracker, :module),
64
+ :u => sp_opt(tracker, :user)
65
+ })
66
+ end
67
+
68
+ def sp_opt(tracker, param)
69
+ value = tracker.opts[param] || sp_defaults[param]
70
+
71
+ return instance_eval(&value) if Proc === value
72
+ value
73
+ end
74
+
75
+ def sp_defaults
76
+ self.class.sp_defaults
77
+ end
78
+ end
79
+ end
80
+
@@ -0,0 +1,23 @@
1
+ module SaasPulse
2
+ class Tracker
3
+ def initialize(action, *opts)
4
+ @action = action
5
+ activity = opts.shift
6
+ @opts = opts.empty? ? {} : opts.shift
7
+
8
+ return unless activity
9
+
10
+ case activity
11
+ when String
12
+ @opts[:activity] = activity
13
+ when Hash
14
+ @opts = activity
15
+ else
16
+ raise ArgumentError, "activity must be a String or Hash"
17
+ end
18
+ end
19
+
20
+ attr_reader :action, :opts
21
+ end
22
+ end
23
+
@@ -0,0 +1,3 @@
1
+ module SaasPulse
2
+ VERSION = "0.1.1" unless defined?(::SaasPulse::VERSION)
3
+ end
data/lib/saas_pulse.rb ADDED
@@ -0,0 +1,15 @@
1
+ lib = File.expand_path('../../lib/', __FILE__)
2
+ $:.unshift(lib) unless $:.include?(lib)
3
+
4
+ require 'open-uri'
5
+ require 'cgi'
6
+
7
+ require 'saas_pulse/client'
8
+ require 'saas_pulse/arg_parser'
9
+ require 'saas_pulse/tracker'
10
+ require 'saas_pulse/adapter'
11
+ require 'saas_pulse/resource'
12
+ require 'saas_pulse/adapters/base'
13
+ require 'saas_pulse/adapters/merb'
14
+ require 'saas_pulse/adapters/rails'
15
+
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: saas_pulse-ruby
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
+ platform: ruby
11
+ authors:
12
+ - jonah honeyman
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-23 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ description: Enables easy integration of SaaSPulse tracking, with options for different ruby web frameworks
34
+ email:
35
+ - jonah@honeyman.org
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - lib/saas_pulse.rb
44
+ - lib/saas_pulse/version.rb
45
+ - lib/saas_pulse/arg_parser.rb
46
+ - lib/saas_pulse/client.rb
47
+ - lib/saas_pulse/resource.rb
48
+ - lib/saas_pulse/adapters/base.rb
49
+ - lib/saas_pulse/adapters/rails.rb
50
+ - lib/saas_pulse/adapters/merb.rb
51
+ - lib/saas_pulse/adapter.rb
52
+ - lib/saas_pulse/tracker.rb
53
+ - LICENSE
54
+ - README.md
55
+ has_rdoc: true
56
+ homepage: https://github.com/jonuts/saas_pulse-ruby
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options: []
61
+
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 1
79
+ - 3
80
+ - 6
81
+ version: 1.3.6
82
+ requirements: []
83
+
84
+ rubyforge_project: saas_pulse-ruby
85
+ rubygems_version: 1.3.7
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: API wrapper for SaaSPulse tracking integration
89
+ test_files: []
90
+