fluidfeatures-rails 0.1.3 → 0.1.4

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Build Status](https://secure.travis-ci.org/BigFastSite/fluidfeatures-rails.png)](http://travis-ci.org/BigFastSite/fluidfeatures-rails)
1
+ [![Build Status](https://secure.travis-ci.org/FluidFeatures/fluidfeatures-rails.png)](http://travis-ci.org/FluidFeatures/fluidfeatures-rails)
2
2
 
3
3
  fluidfeatures-rails
4
4
  ===================
@@ -1,5 +1,5 @@
1
1
  module FluidFeatures
2
2
  module Rails
3
- VERSION = '0.1.3'
3
+ VERSION = '0.1.4'
4
4
  end
5
5
  end
@@ -1,26 +1,37 @@
1
1
 
2
- require 'rails'
3
- require 'net/http'
4
- require 'persistent_http'
5
-
6
- #
7
- # Without these FluidFeatures credentials we cannot talk to
8
- # the FluidFeatures service.
9
- #
10
- %w[FLUIDFEATURES_BASEURI FLUIDFEATURES_SECRET FLUIDFEATURES_APPID].each do |key|
11
- unless ENV[key]
12
- raise "Environment variable #{key} expected"
13
- end
14
- end
15
-
16
2
  module FluidFeatures
17
3
  module Rails
4
+
5
+ class << self
6
+ attr_accessor :enabled
7
+ end
18
8
 
19
9
  #
20
10
  # This is called once, when your Rails application fires up.
21
11
  # It sets up the before and after request hooks
22
12
  #
23
13
  def self.initializer
14
+
15
+ #
16
+ # Without these FluidFeatures credentials we cannot talk to
17
+ # the FluidFeatures service.
18
+ #
19
+ %w[FLUIDFEATURES_BASEURI FLUIDFEATURES_SECRET FLUIDFEATURES_APPID].each do |key|
20
+ unless ENV[key]
21
+ $stderr.puts "!! fluidfeatures-rails requires ENV[\"#{key}\"] (fluidfeatures is disabled)"
22
+ return
23
+ end
24
+ end
25
+ unless defined? ::Rails
26
+ $stderr.puts "!! fluidfeatures-rails requires rails (fluidfeatures is disabled)"
27
+ return
28
+ end
29
+ $stderr.puts "=> fluidfeatures-rails initializing as app #{ENV["FLUIDFEATURES_APPID"]} with #{ENV["FLUIDFEATURES_BASEURI"]}"
30
+
31
+
32
+ require 'net/http'
33
+ require 'persistent_http'
34
+
24
35
  ::Rails::Application.initializer "fluidfeatures.initializer" do
25
36
  ActiveSupport.on_load(:action_controller) do
26
37
 
@@ -38,11 +49,13 @@ module FluidFeatures
38
49
  @@unknown_features = {}
39
50
  @@last_fetch_duration = nil
40
51
 
41
- ActionController::Base.append_before_filter :fluidfeatures_request_init
42
- ActionController::Base.append_after_filter :fluidfeatures_store_features_hit
52
+ ActionController::Base.append_before_filter :fluidfeatures_request_before
53
+ ActionController::Base.append_after_filter :fluidfeatures_request_after
43
54
 
44
55
  end
45
56
  end
57
+
58
+ @enabled = true
46
59
  end
47
60
 
48
61
  #
@@ -156,30 +169,18 @@ module FluidFeatures
156
169
  # back with the default_enabled status (see unknown_feature_hit)
157
170
  # so that FluidFeatures can auto-populate the dashboard.
158
171
  #
159
- def self.log_features_hit(user_id, features_hit, request_duration)
172
+ def self.log_request(user_id, payload)
160
173
  begin
161
- uri = URI(@@baseuri + "/app/" + @@app_id.to_s + "/user/" + user_id.to_s + "/features/hit")
174
+ (payload[:stats] ||= {})[:ff_latency] = @@last_fetch_duration
175
+ if @@unknown_features.size
176
+ (payload[:features] ||= {})[:unknown] = @@unknown_features
177
+ @@unknown_features = {}
178
+ end
179
+ uri = URI(@@baseuri + "/app/#{@@app_id}/user/#{user_id}/features/hit")
162
180
  request = Net::HTTP::Post.new uri.path
163
181
  request["Content-Type"] = "application/json"
164
182
  request["Accept"] = "application/json"
165
183
  request['AUTHORIZATION'] = @@secret
166
- payload = {
167
- :stats => {
168
- :fetch => {
169
- :duration => @@last_fetch_duration
170
- },
171
- :request => {
172
- :duration => request_duration
173
- }
174
- },
175
- :features => {
176
- :hit => features_hit
177
- }
178
- }
179
- if @@unknown_features.size
180
- payload[:features][:unknown] = @@unknown_features
181
- @@unknown_features = {}
182
- end
183
184
  request.body = JSON.dump(payload)
184
185
  response = @@http.request request
185
186
  unless response.is_a?(Net::HTTPSuccess)
@@ -197,14 +198,45 @@ end
197
198
  module ActionController
198
199
  class Base
199
200
 
201
+ # allow fluidfeature to be called from templates
202
+ helper_method :fluidfeature
203
+
200
204
  #
201
205
  # Here is how we know what your user_id is for the user
202
206
  # making the current request.
203
207
  # This must be overriden within the user application.
204
208
  # We recommend doing this in application_controller.rb
205
209
  #
206
- def fluidfeatures_set_user_id(user_id)
210
+ def fluidfeatures_set_user_id(user_id, options={})
211
+
212
+ if user_id and not options[:anonymous]
213
+ # We no longer an anoymous users. Let's delete the cookie
214
+ if cookies.has_key? :fluidfeatures_anonymous
215
+ cookies.delete(:fluidfeatures_anonymous)
216
+ end
217
+ else
218
+ # We're an anonymous user
219
+
220
+ # if we were not given a user_id for this anonymous user, then get
221
+ # it from an existing cookie or create a new one.
222
+ unless user_id
223
+ # Have we seen them before?
224
+ if cookies.has_key? :fluidfeatures_anonymous
225
+ user_id = cookies[:fluidfeatures_anonymous]
226
+ else
227
+ # Create new cookie. Use rand + micro-seconds of current time
228
+ user_id = "anon-" + Random.rand(9999999999).to_s + "-" + ((Time.now.to_f * 1000000).to_i % 1000000).to_s
229
+ end
230
+ end
231
+ # update the cookie, with whatever the user_id has been set to
232
+ cookies[:fluidfeatures_anonymous] = user_id
233
+ end
234
+
207
235
  @ff_user_id = user_id
236
+ @ff_user_anonymous = !!options[:anonymous]
237
+ @ff_user_attributes = options[:attributes]
238
+
239
+ user_id
208
240
  end
209
241
 
210
242
  #
@@ -217,6 +249,9 @@ module ActionController
217
249
  if defaults === true or defaults === false
218
250
  defaults = { :enabled => defaults }
219
251
  end
252
+ unless ::FluidFeatures::Rails.enabled
253
+ return defaults[:enabled] || false
254
+ end
220
255
  global_defaults = fluidfeatures_defaults || {}
221
256
  version_name = (defaults[:version] || global_defaults[:version]).to_s
222
257
  if not @features
@@ -254,7 +289,7 @@ module ActionController
254
289
  #
255
290
  # Initialize the FluidFeatures state for this request.
256
291
  #
257
- def fluidfeatures_request_init
292
+ def fluidfeatures_request_before
258
293
  @ff_request_start_time = Time.now
259
294
  @features = nil
260
295
  end
@@ -273,10 +308,28 @@ module ActionController
273
308
  # This helps the FluidFeatures database prepopulate the feature set
274
309
  # without requiring the developer to do it manually.
275
310
  #
276
- def fluidfeatures_store_features_hit
311
+ def fluidfeatures_request_after
277
312
  if @features
278
313
  request_duration = Time.now - @ff_request_start_time
279
- FluidFeatures::Rails.log_features_hit(@ff_user_id, @features_hit, request_duration)
314
+ url = "#{request.protocol}#{request.host_with_port}#{request.fullpath}"
315
+ payload = {
316
+ :stats => {
317
+ :request => {
318
+ :duration => request_duration
319
+ }
320
+ },
321
+ :features => {
322
+ :hit => @features_hit
323
+ },
324
+ :url => url
325
+ }
326
+ if @ff_user_anonymous
327
+ (payload[:user] ||= {})[:anonymous] = true
328
+ end
329
+ if @ff_user_attributes
330
+ (payload[:user] ||= {})[:attributes] = @ff_user_attributes
331
+ end
332
+ FluidFeatures::Rails.log_request(@ff_user_id, payload)
280
333
  end
281
334
  end
282
335
 
@@ -284,7 +337,7 @@ module ActionController
284
337
  # By default unknown features are disabled.
285
338
  {
286
339
  :enabled => false,
287
- :version => 1
340
+ :version => :default
288
341
  }
289
342
  end
290
343
 
@@ -38,33 +38,33 @@ describe HomeController do
38
38
 
39
39
  # Check the call to features hit
40
40
  features_hit_request = FakeWeb.last_request
41
- JsonSpec.exclude_keys("duration")
41
+ JsonSpec.exclude_keys("duration", "ff_latency")
42
42
  features_hit_request.body.should be_json_eql(%({
43
43
  "features": {
44
44
  "hit": {
45
45
  "apples": {
46
- "1": {}
46
+ "default": {}
47
47
  }
48
48
  },
49
49
  "unknown": {
50
50
  // features that we have not seen before
51
51
  "apples": {
52
52
  "versions": {
53
- "1": {
53
+ "default": {
54
54
  "enabled": true
55
55
  }
56
56
  }
57
57
  },
58
58
  "lemons": {
59
59
  "versions": {
60
- "1": {
60
+ "default": {
61
61
  "enabled": false
62
62
  }
63
63
  }
64
64
  },
65
65
  "oranges": {
66
66
  "versions": {
67
- "1": {
67
+ "default": {
68
68
  "enabled": false
69
69
  }
70
70
  }
@@ -72,13 +72,12 @@ describe HomeController do
72
72
  }
73
73
  },
74
74
  "stats": {
75
- "fetch": {
76
- // duration ignored
77
- },
75
+ "ff_latency": 1,
78
76
  "request": {
79
77
  // duration ignored
80
78
  }
81
- }
79
+ },
80
+ "url": "http://test.host/?user_id=1"
82
81
  }))
83
82
  end
84
83
 
@@ -89,15 +88,15 @@ describe HomeController do
89
88
 
90
89
  # Check the call to features hit
91
90
  features_hit_request = FakeWeb.last_request
92
- JsonSpec.exclude_keys("duration")
91
+ JsonSpec.exclude_keys("duration", "ff_latency")
93
92
  features_hit_request.body.should be_json_eql(%({
94
93
  "features": {
95
94
  "hit": {
96
95
  "oranges": {
97
- "1": {}
96
+ "default": {}
98
97
  },
99
98
  "lemons": {
100
- "1": {}
99
+ "default": {}
101
100
  }
102
101
  },
103
102
  "unknown": {
@@ -105,13 +104,12 @@ describe HomeController do
105
104
  }
106
105
  },
107
106
  "stats": {
108
- "fetch": {
109
- // duration ignored
110
- },
107
+ "ff_latency": 1,
111
108
  "request": {
112
109
  // duration ignored
113
110
  }
114
- }
111
+ },
112
+ "url": "http://test.host/?user_id=2"
115
113
  }))
116
114
  end
117
115
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluidfeatures-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
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: 2012-09-01 00:00:00.000000000 Z
12
+ date: 2012-09-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: persistent_http