preact 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,6 +33,11 @@ production: &defaults
33
33
  - "sessions#create"
34
34
  - "devise/sessions#create"
35
35
 
36
+ # specify how to retrieve the current user and account from within the application controller
37
+ # you may use either an instance variable (prefixed with @) or a method name
38
+ #current_user_getter: "current_user"
39
+ #current_account_getter: "@current_account"
40
+
36
41
  development:
37
42
  <<: *defaults
38
43
 
data/lib/preact.rb CHANGED
@@ -105,22 +105,21 @@ module Preact
105
105
  end
106
106
 
107
107
  if event.is_a?(String)
108
- preact_event = AccountEvent.new({
108
+ preact_event = {
109
109
  :name => event,
110
110
  :timestamp => Time.now.to_f
111
- })
111
+ }
112
112
  elsif event.is_a?(Hash)
113
- preact_event = AccountEvent.new(event)
114
- elsif event.is_a?(AccountEvent)
115
113
  preact_event = event
116
114
  else
117
- raise StandardError.new "Unknown event class, must pass a string event name, event hash or AccountEvent object"
115
+ raise StandardError.new "Unknown event class, must pass a string event name or event hash."
118
116
  end
119
117
 
120
118
  # attach the account info to the event
121
- preact_event.account = configuration.convert_to_account(account)
119
+ preact_event[:account] = configuration.convert_to_account(account)
120
+ preact_event[:klass] = "accountevent"
122
121
 
123
- send_log(nil, preact_event.as_json)
122
+ send_log(nil, preact_event)
124
123
  end
125
124
 
126
125
  def update_person(user)
@@ -160,7 +159,7 @@ module Preact
160
159
  protected
161
160
 
162
161
  def send_log(person, event=nil)
163
- psn = person.to_hash
162
+ psn = person.nil? ? nil : person.to_hash
164
163
  evt = event.nil? ? nil : event.to_hash
165
164
 
166
165
  if defined?(Preact::Sidekiq) && (configuration.logging_mode.nil? || configuration.logging_mode == :sidekiq)
@@ -16,6 +16,10 @@ module Preact
16
16
  attr_accessor :sidekiq_queue
17
17
  attr_accessor :request_timeout
18
18
  attr_accessor :logging_mode
19
+ attr_accessor :inject_javascript
20
+
21
+ attr_accessor :current_user_getter
22
+ attr_accessor :current_account_getter
19
23
 
20
24
  # Logger settings
21
25
  attr_accessor :logger
@@ -38,6 +42,11 @@ module Preact
38
42
  @logging_mode = nil
39
43
  @sidekiq_queue = :default
40
44
  @request_timeout = 5
45
+
46
+ @inject_javascript = false
47
+
48
+ @current_user_getter = :current_user
49
+ @current_account_getter = nil
41
50
 
42
51
  @user_agent = "ruby-preact:#{Preact::VERSION}"
43
52
 
@@ -49,6 +58,7 @@ module Preact
49
58
  end
50
59
 
51
60
  def valid?
61
+ # we require both the API keys
52
62
  code && secret
53
63
  end
54
64
 
@@ -68,6 +78,10 @@ module Preact
68
78
  "#{scheme}://#{code}:#{secret}@#{host}#{base_path}"
69
79
  end
70
80
 
81
+ def inject_javascript?
82
+ inject_javascript == true
83
+ end
84
+
71
85
  def autolog_enabled?
72
86
  autolog == true
73
87
  end
@@ -87,7 +101,31 @@ module Preact
87
101
  true
88
102
  end
89
103
 
104
+ def get_current_user(target)
105
+ return nil if current_user_getter.nil?
106
+
107
+ if current_user_getter.to_s.starts_with?("@")
108
+ # instance var
109
+ target.instance_variable_get(current_user_getter) rescue nil
110
+ else
111
+ target.send(current_user_getter) rescue nil
112
+ end
113
+ end
114
+
115
+ def get_current_account(target)
116
+ return nil if current_user_getter.nil?
117
+
118
+ if current_account_getter.to_s.starts_with?("@")
119
+ # instance var
120
+ target.instance_variable_get(current_account_getter) rescue nil
121
+ else
122
+ target.send(current_account_getter) rescue nil
123
+ end
124
+ end
125
+
90
126
  def convert_to_person(user)
127
+ return nil if user.nil?
128
+
91
129
  if person_builder
92
130
  if person_builder.respond_to?(:call)
93
131
  hash = person_builder.call(user)
@@ -106,6 +144,8 @@ module Preact
106
144
  end
107
145
 
108
146
  def convert_to_account(account)
147
+ return nil if account.nil?
148
+
109
149
  if account_builder
110
150
  if account_builder.respond_to?(:call)
111
151
  hash = account_builder.call(account)
@@ -124,6 +164,8 @@ module Preact
124
164
  end
125
165
 
126
166
  def prepare_person_hash(person)
167
+ return nil if person.nil?
168
+
127
169
  if external_id = person[:external_identifier] || person["external_identifier"]
128
170
  person[:uid] ||= external_id
129
171
  person.delete(:external_identifier)
@@ -44,16 +44,23 @@ module Preact
44
44
 
45
45
  # helper method on the controller to make logging events easy
46
46
  def preact_log(event, account=nil)
47
- if account
48
- Preact.log_event(current_user, event, account)
49
- else
50
- Preact.log_event(current_user, event)
51
- end
47
+ user = Preact.configuration.get_current_user(self) # handle nil
48
+ account ||= Preact.configuration.get_current_account(self) # handle nil
49
+
50
+ Preact.log_event(user, event, account)
52
51
 
53
52
  # make a note that we've logged an event on this controller
54
53
  @preact_logged_event = event
55
54
  end
56
55
 
56
+ def inject_javascript
57
+ if body_end = response.body.index("</body")
58
+ script = build_script
59
+
60
+ response.body = response.body.insert(body_end, script)
61
+ end
62
+ end
63
+
57
64
  # attach the after_filter to all controllers if we've enabled autologging
58
65
  if Preact.configuration.autolog_enabled?
59
66
  ActiveSupport.on_load(:action_controller) do
@@ -61,9 +68,40 @@ module Preact
61
68
  end
62
69
  end
63
70
 
71
+ if Preact.configuration.inject_javascript?
72
+ ActiveSupport.on_load(:action_controller) do
73
+ after_filter :inject_javascript
74
+ end
75
+ end
64
76
 
65
77
  protected
66
78
 
79
+ def build_script
80
+ script = <<-SCRIPT
81
+ <script>
82
+ var _preactq = _preactq || [];
83
+ _preactq.push(['_setCode', '#{Preact.configuration.code.to_s}']);
84
+ _preactq.push(['_setPersonData', #{Preact.configuration.convert_to_person(Preact.configuration.get_current_user(self)).to_json}]);
85
+ SCRIPT
86
+ if Preact.configuration.get_current_account(self)
87
+ script += <<-SCRIPT
88
+ _preactq.push(['_setAccount', #{Preact.configuration.convert_to_account(Preact.configuration.get_current_account(self)).to_json}]);
89
+ SCRIPT
90
+ end
91
+
92
+ script += <<-SCRIPT
93
+ _preactq.push(['_logEvent', '___loaded:preact']);
94
+ (function() {
95
+ var ln = document.createElement('script');
96
+ ln.type = 'text/javascript'; ln.async = true;
97
+ ln.src = 'https://d2bbvl6dq48fa6.cloudfront.net/js/preact-4.0.min.js';
98
+ var s = document.getElementsByTagName('script')[0];
99
+ s.parentNode.insertBefore(ln, s);
100
+ })();
101
+ </script>
102
+ SCRIPT
103
+ end
104
+
67
105
  def guess_target_item_name(controller)
68
106
  # get a little too clever and try to see if we've loaded an item
69
107
  guessed_target_variable = controller.split("/").last.singularize rescue nil
@@ -1,3 +1,3 @@
1
1
  module Preact
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
data/readme.md CHANGED
@@ -8,7 +8,7 @@ Installation
8
8
  In your Gemfile:
9
9
 
10
10
  ```ruby
11
- gem 'preact', "~> 0.8.0"
11
+ gem 'preact', '~> 1.0'
12
12
  ```
13
13
 
14
14
  Then do a `bundle install` to get the gem.
@@ -18,25 +18,59 @@ Configuration
18
18
 
19
19
  In version 0.8.1 we added a rails generator to make it really easy to add the initializer and get you up and running.
20
20
 
21
- First, obtain your Preact Project Code and API Secret from the [API settings page](https://secure.preact.io/settings/api). Then, in your application directory, run the generator:
21
+ First, obtain your Preact Project Code and API Secret from the [API settings page](https://secure.preact.com/settings/api). Then, in your application directory, run the generator:
22
22
 
23
23
  ```bash
24
24
  rails g preact your-code-1234 api-secret-xyzw
25
25
  ```
26
26
 
27
- That will generate a preact.rb initializer that looks something like this:
27
+ That will generate an initializer and a preact.yml config that looks something like this:
28
28
 
29
29
  ```ruby
30
- Preact.configure do |config|
31
- config.code = 'your-code-1234' # required
32
- config.secret = 'api-secret-xyzw' # required
33
-
34
- config.autolog = true
35
- config.autolog_ignored_actions = ["sessions#create"]
36
30
 
37
- # Disable in Rails development environments
38
- # config.disabled = Rails.env.development?
39
- end
31
+ Preact Logging Configs
32
+ ---
33
+ production: &defaults
34
+
35
+ # your Preact API credentials
36
+ code: "your-code-1234"
37
+ secret: "api-secret-xyzw"
38
+
39
+ # automatically log controller actions for authed users
40
+ # disable this if you want to only log manual events
41
+ autolog: true
42
+
43
+ # specify controller#action items that you want to ignore and not log to Preact.
44
+ # default is to not log sessions#create beacuse if you're using Devise, we get that already
45
+ autolog_ignored_actions:
46
+ - "sessions#create"
47
+ - "devise/sessions#create"
48
+
49
+ # specify how to retrieve the current user and account from within the application controller
50
+ # you may use either an instance variable (prefixed with @) or a method name
51
+ #current_user_getter: "current_user"
52
+ #current_account_getter: "@current_account"
53
+
54
+ development:
55
+ <<: *defaults
56
+
57
+ # we usually suggest that you use a different project for development, to keep
58
+ # those events separate from production events
59
+ #code: "DEV_CODE"
60
+ #secret: "DEV_SECRET"
61
+
62
+ # you may also completely disable event logging in development
63
+ #disabled: false
64
+
65
+ staging:
66
+ <<: *defaults
67
+
68
+ # if you want to log staging events separately as well
69
+ #code: "STAGING_CODE"
70
+ #secret: "STAGING_SECRET"
71
+
72
+ # you may also completely disable event logging in staging
73
+ #disabled: false
40
74
  ```
41
75
 
42
76
  Now when you launch your app and do something as an authenticated user, you should see the activity in Preact.
@@ -61,10 +95,12 @@ config.autolog_ignored_actions = [
61
95
  "secret_pages#*" # ignores ALL actions on the secret_pages_controller
62
96
  ]
63
97
  ```
98
+ Background Sending
99
+ ---
100
+ By default, Preact uses [SuckerPunch](https://github.com/brandonhilkert/sucker_punch) to make sure nothing gets blocked while logging events to Preact in the background.
64
101
 
65
102
  Rails Controller Helper
66
103
  ---
67
-
68
104
  Since version 0.8.1, we include a helper method on the base controller called `preact_log` to make it convenient for you to log events directly.
69
105
 
70
106
  The helper is aware of the current_user and so only requires you to pass the event information as things occur. So for instance, you may log a simple event from one of yoru controllers like so:
@@ -126,32 +162,29 @@ The `event` parameter may be either a String if you just are passing the event n
126
162
 
127
163
  ```ruby
128
164
  person = {
129
- :name => "Christopher Gooley",
130
- :email => "gooley@foliohd.com",
131
- :uid => "gooley",
132
- :properties => {
133
- :subscription_level => 4,
134
- :subscription_level_name => "Pro",
135
- :is_paying => true,
136
- :created_at => 1347060566
137
- :twitter => "gooley"
165
+ name: 'Christopher Gooley',
166
+ email: 'gooley@foliohd.com',
167
+ uid: 'gooley',
168
+ properties: {
169
+ created_at: 1347060566
170
+ twitter: 'gooley'
138
171
  }
139
172
  }
140
173
 
141
- #common event examples:
174
+ ##common event examples:
142
175
  Preact.log_event(person, 'logged-in')
143
176
  Preact.log_event(person, 'upgraded')
144
- Preact.log_event(person, { :name => 'processed:payment', :revenue => 900 }) # revenue specified in cents
145
- Preact.log_event(person, { :name => 'uploaded:file', :note => "awesome_resume.pdf" })
177
+ Preact.log_event(person, { name: 'processed:payment', revenue: 900 }) # revenue specified in cents
178
+ Preact.log_event(person, { name: 'uploaded:file', note: 'awesome_resume.pdf' })
146
179
 
147
180
  Preact.log_event(person, {
148
- :name => 'purchased:item',
149
- :note => "black shoes",
150
- :revenue => 2500,
151
- :extras => {
152
- :category => "shoes",
153
- :size => "13",
154
- :color => "blue"
181
+ name: 'purchased:item',
182
+ note: 'black shoes',
183
+ revenue: 2500,
184
+ extras: {
185
+ category: 'shoes',
186
+ size: '13',
187
+ color: 'blue'
155
188
  })
156
189
  ```
157
190
 
@@ -159,9 +192,9 @@ If you are a Preact B2B user, you should also log the `account` that this event
159
192
 
160
193
  ```ruby
161
194
  Preact.log_event(
162
- { :email => "bob@honda.com", :name => "Bob Smith" }, # person
163
- { :name => 'uploaded:file', :note => "awesome_resume.pdf" }, # event
164
- { :id => 1234, :name => "Honda"} # account
195
+ { email: 'bob@honda.com', name: 'Bob Smith' }, # person
196
+ { name: 'uploaded:file', note: 'awesome_resume.pdf' }, # event
197
+ { id: 1234, name: 'Honda'} # account
165
198
  )
166
199
  ```
167
200
 
@@ -173,21 +206,20 @@ In your `User` model, you can define a `to_preact` method returning a Hash. Prea
173
206
  class User < ActiveRecord::Base
174
207
  def to_preact
175
208
  {
176
- :name => self.name,
177
- :email => self.email,
178
- :uid => self.id,
179
- :properties => {
180
- :is_paying => self.paying_customer?,
181
- :created_at => self.created_at.to_i
182
- }
209
+ name: self.name,
210
+ email: self.email,
211
+ uid: self.id,
212
+ created_at: self.created_at.to_i
183
213
  }
184
214
  end
185
215
  end
186
216
  ```
187
217
 
218
+ For a list of available built-in person fields, see the [API Docs](http://www.preact.com/api#person_object) Person Object section.
219
+
188
220
  ```ruby
189
221
  Preact.log_event(@current_user, 'restored_answer_data')
190
- Preact.log_event(@current_user, { :name => 'updated-profile', :extras => {:twitter => "@gooley"} })
222
+ Preact.log_event(@current_user, { name: 'updated-profile', extras: {twitter: '@gooley'} })
191
223
  ```
192
224
 
193
225
  #### B2B Account mapping method
@@ -198,23 +230,26 @@ Likewise, if you are a Preact B2B user, you can define the `to_preact` method on
198
230
  class Project < ActiveRecord::Base
199
231
  def to_preact
200
232
  {
201
- :name => self.name,
202
- :id => self.id
233
+ name: self.name,
234
+ id: self.id,
235
+ license_status: self.account_status
203
236
  }
204
237
  end
205
238
  end
206
239
  ```
207
240
 
241
+ For a list of available built-in account fields, see the [API Docs](http://www.preact.com/api#account_object) Account Object section.
242
+
208
243
  Then, you just pass that model to the log_event method and we will associate the user's action with that account.
209
244
 
210
245
  ```ruby
211
246
  Preact.log_event(@current_user, 'restored_answer_data', @current_project)
212
- Preact.log_event(@current_user, { :name => 'updated-profile', :extras => {:twitter => "@gooley"} }, @current_project)
247
+ Preact.log_event(@current_user, { name: 'updated-profile', extras: {twitter: '@gooley'} }, @current_project)
213
248
  ```
214
249
 
215
250
  Sidekiq Integration
216
251
  ---
217
- 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.
252
+ Using [Sidekiq](http://sidekiq.org) for background processing?
218
253
 
219
254
  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.
220
255
 
@@ -224,9 +259,8 @@ If you are using Warden, Preact will automatically log your login/logout events.
224
259
  If when Preact loads, it notices that a ::Warden class is defined, it will require the preact/warden module which adds the appropriate hooks into Warden.
225
260
 
226
261
 
227
-
228
262
  License
229
- --
263
+ ---
230
264
  Copyright (c) 2011-2013 Christopher Gooley, Preact / Less Neglect, Inc. See LICENSE.txt for further details.
231
265
 
232
266
  Thanks to [Zach Millman](https://github.com/zmillman) for many contributions.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: preact
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-24 00:00:00.000000000 Z
12
+ date: 2014-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client