preact 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011-2013 Christopher Gooley
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.
@@ -0,0 +1,50 @@
1
+ require 'multi_json'
2
+ require 'rest_client'
3
+
4
+ class Preact::Client
5
+
6
+ def create_event(person, action_event)
7
+ params = {
8
+ :person => person,
9
+ :event => action_event
10
+ }
11
+
12
+ data = post_request("/events", params)
13
+ end
14
+
15
+ def update_person(person)
16
+ params = {
17
+ :person => person
18
+ }
19
+
20
+ data = post_request("/people", params)
21
+ end
22
+
23
+ private
24
+
25
+ def post_request(method, params={})
26
+ params = prepare_request_params(params)
27
+
28
+ puts "post_request to #{Preact.configuration.base_uri + method} with #{params.inspect}"
29
+
30
+ res = RestClient.post Preact.configuration.base_uri + method, params.to_json, :content_type => :json, :accept => :json
31
+ data = MultiJson.decode(res.body)
32
+ end
33
+
34
+ def get_request(method, params={})
35
+ params = prepare_request_params(params)
36
+
37
+ res = RestClient.get Preact.configuration.base_uri + method, { :params => params }
38
+ data = MultiJson.decode(res.body)
39
+ end
40
+
41
+ def prepare_request_params(params = {})
42
+ params.merge({
43
+ # :user => Preact.configuration.code,
44
+ # :password => Preact.configuration.secret,
45
+ :format => "json"
46
+ })
47
+ end
48
+
49
+
50
+ end
@@ -0,0 +1,80 @@
1
+ require 'preact/version'
2
+
3
+ module Preact
4
+ class Configuration
5
+
6
+ # Preact credentials
7
+ attr_accessor :code
8
+ attr_accessor :secret
9
+
10
+ # Default option settings
11
+ attr_accessor :disabled
12
+ attr_accessor :person_builder
13
+
14
+ # The URL of the API server
15
+ attr_accessor :scheme
16
+ attr_accessor :host
17
+ attr_accessor :base_path
18
+
19
+ def initialize
20
+ @scheme = 'https'
21
+ @host = 'api.preact.io'
22
+ @base_path = '/api/v2'
23
+
24
+ @disabled = false
25
+ @person_builder = nil
26
+
27
+ @user_agent = "ruby-preact:#{Preact::VERSION}"
28
+ end
29
+
30
+ def valid?
31
+ code && secret
32
+ end
33
+
34
+ def enabled?
35
+ !disabled
36
+ end
37
+
38
+ def disabled?
39
+ !!disabled
40
+ end
41
+
42
+ def user_agent
43
+ @user_agent
44
+ end
45
+
46
+ def base_uri
47
+ "#{scheme}://#{code}:#{secret}@#{host}#{base_path}"
48
+ end
49
+
50
+ def convert_to_person(user)
51
+ if person_builder
52
+ if person_builder.respond_to?(:call)
53
+ Person.new(person_builder.call(user))
54
+ else
55
+ raise "person_builder must be callable"
56
+ end
57
+ elsif user.respond_to?(:to_person)
58
+ Person.new(user.to_person)
59
+ elsif user.is_a? Hash
60
+ Person.new(user)
61
+ else
62
+ Person.new(default_user_to_person_hash(user))
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def default_user_to_person_hash(user)
69
+ {
70
+ :name => user.name,
71
+ :email => user.email,
72
+ :uid => user.id,
73
+ :properties => {
74
+ :created_at => (user.created_at.to_i if user.respond_to?(:created_at))
75
+ }
76
+ }
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,35 @@
1
+ module Preact
2
+ class ActionEvent < Event
3
+
4
+ attr_accessor :note, :links, :external_identifier, :extras
5
+
6
+ def add_link(name, href)
7
+ self.links ||= []
8
+ self.links << ActionLink.new({ :name => name, :href => href })
9
+ end
10
+
11
+ def as_json(options={})
12
+ super(options).merge({
13
+ :klass => "actionevent",
14
+ :note => self.note,
15
+ :external_identifier => self.external_identifier,
16
+ :extras => self.extras,
17
+ :links => self.links.nil? ? nil : self.links.as_json
18
+ })
19
+ end
20
+
21
+ end
22
+
23
+ class ActionLink < ApiObject
24
+
25
+ attr_accessor :name, :href
26
+
27
+ def as_json
28
+ {
29
+ :name => self.name,
30
+ :href => self.href
31
+ }
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ class Preact::ApiObject
2
+
3
+ def initialize(args={})
4
+ args.each do |k,v|
5
+ instance_variable_set("@#{k}", v) unless v.nil?
6
+ end
7
+ end
8
+
9
+ end
@@ -0,0 +1,14 @@
1
+ class Preact::Event < Preact::ApiObject
2
+
3
+ attr_accessor :name, :magnitude, :timestamp
4
+
5
+ def as_json(options={})
6
+ {
7
+ :name => self.name,
8
+ :magnitude => self.magnitude,
9
+ :timestamp => self.timestamp,
10
+ :source => Preact.configuration.user_agent # version of this logging library
11
+ }
12
+ end
13
+
14
+ end
@@ -0,0 +1,13 @@
1
+ class Preact::Message < Preact::Event
2
+
3
+ attr_accessor :subject, :body
4
+
5
+ def as_json(options={})
6
+ super(options).merge({
7
+ :klass => "message",
8
+ :subject => self.subject,
9
+ :body => self.body
10
+ })
11
+ end
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ class Preact::Person < Preact::ApiObject
2
+
3
+ attr_accessor :name, :email, :external_identifier, :properties, :uid
4
+
5
+ def as_json(options={})
6
+ {
7
+ :name => self.name,
8
+ :email => self.email,
9
+ :uid => self.uid || self.external_identifier,
10
+ :properties => self.properties
11
+ }
12
+ end
13
+
14
+ end
@@ -0,0 +1,15 @@
1
+ module Preact::Sidekiq
2
+ class PreactLoggingWorker
3
+ include Sidekiq::Worker
4
+
5
+ def perform(person, event=nil)
6
+ client = Preact::Client.new
7
+ if event
8
+ client.create_event(person, event)
9
+ else
10
+ client.update_person(person)
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ require 'preact/sidekiq/preact_logging_worker'
2
+
3
+ module Preact::Sidekiq
4
+
5
+ end
@@ -0,0 +1,3 @@
1
+ module Preact
2
+ VERSION = "0.5.0"
3
+ end
data/lib/preact.rb ADDED
@@ -0,0 +1,84 @@
1
+ require 'preact/configuration'
2
+ require 'preact/client'
3
+
4
+ require 'preact/objects/api_object'
5
+ require 'preact/objects/person'
6
+ require 'preact/objects/event'
7
+ require 'preact/objects/action_event'
8
+ require 'preact/objects/message'
9
+
10
+ module Preact
11
+
12
+ class << self
13
+ # A Preact configuration object. Must like a hash and return sensible values for all
14
+ # Preact configuration options. See Preact::Configuration
15
+ attr_accessor :configuration
16
+
17
+ attr_accessor :default_client
18
+
19
+ # Call this method to modify the configuration in your initializers
20
+ def configure
21
+ self.configuration ||= Configuration.new
22
+
23
+ yield(configuration) if block_given?
24
+
25
+ raise StandardError.new "Must specify project code and secret when configuring the Preact api client" unless configuration.valid?
26
+ end
27
+
28
+ def log_event(user, event_name, extras = {})
29
+ # Don't send requests when disabled
30
+ return if configuration.disabled?
31
+ return if user.nil?
32
+
33
+ person = configuration.convert_to_person(user).as_json
34
+ event = ActionEvent.new({
35
+ :name => event_name,
36
+ :timestamp => Time.now.to_f
37
+ }.merge(extras)).as_json
38
+
39
+ send_log(person, event)
40
+ end
41
+
42
+ def update_person(user)
43
+ # Don't send requests when disabled
44
+ return if configuration.disabled?
45
+ return if user.nil?
46
+
47
+ person = configuration.convert_to_person(user).as_json
48
+
49
+ send_log(person)
50
+ end
51
+
52
+ # message - a Hash with the following required keys
53
+ # :subject - subject of the message
54
+ # :body - body of the message
55
+ # * any additional keys are used as extra options for the message (:note, etc.)
56
+ def message(user, message = {})
57
+ # Don't send requests when disabled
58
+ return if configuration.disabled?
59
+ return if user.nil?
60
+
61
+ person = configuration.convert_to_person(user).as_json
62
+ message_obj = Message.new(message).as_json
63
+
64
+ send_log(person, message_obj)
65
+ end
66
+
67
+ protected
68
+
69
+ def send_log(person, event=nil)
70
+ psn = person.as_json
71
+ evt = event.nil? ? nil : event.as_json
72
+
73
+ if defined?(Preact::Sidekiq)
74
+ Preact::Sidekiq::PreactLoggingWorker.perform_async(psn, evt)
75
+ else
76
+ client.create_event(psn, evt)
77
+ end
78
+ end
79
+
80
+ def client
81
+ self.default_client ||= Client.new
82
+ end
83
+ end
84
+ end
data/readme.md ADDED
@@ -0,0 +1,111 @@
1
+ Preact Logging API Ruby Client
2
+ ===
3
+ Allow your Ruby app to easily submit server-side messages and events to Preact.
4
+
5
+ Installation
6
+ ---
7
+
8
+ In your Gemfile:
9
+
10
+ ```ruby
11
+ gem 'preact'
12
+ ```
13
+
14
+ Configuration
15
+ ---
16
+
17
+ Configure Preact with your API credentials. You can find your Preact credentials on the [API settings page](https://secure.preact.io/settings/api) (This should go in an initializer file named `/config/initializers/preact.rb` in Rails applications)
18
+
19
+ ```ruby
20
+ Preact.configure do |config|
21
+ config.code = 'abcdefg' # required
22
+ config.secret = '1234asdfasdf1234' # required
23
+
24
+ # Disable in Rails development environments
25
+ # config.disabled = (Rails.env != "development")
26
+
27
+ # Uncomment this this line to customize the data sent with your Person objects.
28
+ # Your procedure should return a Hash of attributes
29
+ # config.person_builder = lambda {|user| {:keys => :values}}
30
+ end
31
+ ```
32
+
33
+ Usage
34
+ ---
35
+
36
+ ```ruby
37
+ person = {
38
+ :name => "Christopher Gooley",
39
+ :email => "gooley@foliohd.com",
40
+ :uid => "gooley",
41
+ :properties => {
42
+ :account_level => "Pro",
43
+ :is_paying => true,
44
+ :created_at => 1347060566
45
+ :twitter => "gooley"
46
+ }
47
+ }
48
+
49
+ #common event examples:
50
+ Preact.log_event(person, 'logged-in')
51
+ Preact.log_event(person, 'upgraded')
52
+ Preact.log_event(person, 'processed:payment', :revenue => 900) # revenue specified in cents
53
+ Preact.log_event(person, "uploaded:file", :note => "awesome_resume.pdf")
54
+
55
+ Preact.log_event(person, 'purchased:item', {
56
+ :note => "black shoes",
57
+ :revenue => 2500,
58
+ :extras => {
59
+ :size => "13",
60
+ :color => "blue"
61
+ })
62
+ ```
63
+
64
+ ActiveRecord Integration
65
+ ---
66
+ In your `User` model, you can define a `to_person` method returning a Hash. Preact will detect and use this method on users passed to its logging events.
67
+
68
+ ```ruby
69
+ class User < ActiveRecord::Base
70
+ def to_person
71
+ {
72
+ :name => self.name,
73
+ :email => self.email,
74
+ :uid => self.id,
75
+ :properties => {
76
+ :account_level => self.account_level,
77
+ :is_paying => self.paying_customer?,
78
+ :created_at => self.created_at.to_i
79
+ }
80
+ }
81
+ end
82
+ end
83
+ ```
84
+
85
+ ```ruby
86
+ Preact.log_event(User.find(1), 'restored_answer_data')
87
+ Preact.log_event(User.find(1), 'updated-profile', :extras => {:twitter => "@gooley"})
88
+ ```
89
+
90
+ Sidekiq Integration
91
+ ---
92
+ Using [Sidekiq](http://sidekiq.org) for background processing? That's the best way to log data to Preact so it's not done in-process.
93
+
94
+ All you need to do is add `require 'preact/sidekiq'` at the top of your `preact.rb` initializer and we'll take it from there. Jobs will be placed on the :default queue.
95
+
96
+ Devise / Warden Integration
97
+ --
98
+ Automatically log your login/logout events by including this in your `preact.rb` initializer. Just put it under the Preact config block.
99
+
100
+ ```ruby
101
+ # after-auth hook to log the login
102
+ Warden::Manager.after_authentication do |user,auth,opts|
103
+ Preact.log_event(user, "logged-in")
104
+ end
105
+ Warden::Manager.before_logout do |user,auth,opts|
106
+ Preact.log_event(user, "logged-out")
107
+ end
108
+ ```
109
+
110
+
111
+ Copyright (c) 2011-2013 Christopher Gooley, Preact. See LICENSE.txt for further details.
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: preact
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Christopher Gooley
9
+ - Zach Millman
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-04-03 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rest-client
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: rspec
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 2.3.0
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 2.3.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: 1.0.0
63
+ - !ruby/object:Gem::Dependency
64
+ name: jeweler
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: 1.6.4
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: 1.6.4
79
+ - !ruby/object:Gem::Dependency
80
+ name: rcov
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: multi_json
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: '1.0'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ description: API library to allow you to connect and submit messages and actions to
112
+ your Preact project account
113
+ email: gooley@preact.io
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files:
117
+ - LICENSE.txt
118
+ files:
119
+ - lib/preact/client.rb
120
+ - lib/preact/configuration.rb
121
+ - lib/preact/objects/action_event.rb
122
+ - lib/preact/objects/api_object.rb
123
+ - lib/preact/objects/event.rb
124
+ - lib/preact/objects/message.rb
125
+ - lib/preact/objects/person.rb
126
+ - lib/preact/sidekiq/preact_logging_worker.rb
127
+ - lib/preact/sidekiq.rb
128
+ - lib/preact/version.rb
129
+ - lib/preact.rb
130
+ - readme.md
131
+ - LICENSE.txt
132
+ homepage: http://github.com/lessneglect/lessneglect-ruby
133
+ licenses:
134
+ - MIT
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ none: false
147
+ requirements:
148
+ - - ! '>='
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 1.8.25
154
+ signing_key:
155
+ specification_version: 3
156
+ summary: Preact Logging API client library
157
+ test_files: []