preact 1.0.1 → 1.1.0

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.
@@ -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