saas_pulse-ruby 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+