fluidfeatures-rails 0.1.4 → 0.2.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.
@@ -0,0 +1,20 @@
1
+
2
+ class FluidFeatureAjaxController < ApplicationController
3
+
4
+ def index
5
+ render :json => {
6
+ :enabled => fluidfeature(params[:feature_name])
7
+ }, :status => 200
8
+ end
9
+ end
10
+
11
+ #
12
+ # This is a controller you can use to sends stats from your browser
13
+ #
14
+
15
+ class FluidGoalAjaxController < ApplicationController
16
+ def index
17
+ fluidgoal(params[:goal_name], { :version => params[:goal_version] })
18
+ render :json => {}, :status => 200
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+
2
+ require 'fluidfeatures/rails/app/controllers/fluidfeatures_controller'
3
+
4
+ Rails.application.routes.draw do
5
+ match "/fluidfeature/:feature_name" => "fluid_feature_ajax#index"
6
+ match "/fluidgoal/:goal_name" => "fluid_goal_ajax#index"
7
+ match "/fluidgoal/:goal_name/:goal_version" => "fluid_goal_ajax#index"
8
+ end
@@ -1,5 +1,5 @@
1
1
  module FluidFeatures
2
2
  module Rails
3
- VERSION = '0.1.4'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  end
@@ -207,9 +207,13 @@ module ActionController
207
207
  # This must be overriden within the user application.
208
208
  # We recommend doing this in application_controller.rb
209
209
  #
210
- def fluidfeatures_set_user_id(user_id, options={})
210
+ def fluidfeatures_initialize_user
211
211
 
212
- if user_id and not options[:anonymous]
212
+ # TODO: Do not always get verbose user details.
213
+ # Get for new users and then less frequently.
214
+ user = fluidfeature_current_user(verbose=true)
215
+
216
+ if user[:id] and not user[:anonymous]
213
217
  # We no longer an anoymous users. Let's delete the cookie
214
218
  if cookies.has_key? :fluidfeatures_anonymous
215
219
  cookies.delete(:fluidfeatures_anonymous)
@@ -217,28 +221,31 @@ module ActionController
217
221
  else
218
222
  # We're an anonymous user
219
223
 
220
- # if we were not given a user_id for this anonymous user, then get
224
+ # if we were not given a user[:id] for this anonymous user, then get
221
225
  # it from an existing cookie or create a new one.
222
- unless user_id
226
+ unless user[:id]
223
227
  # Have we seen them before?
224
228
  if cookies.has_key? :fluidfeatures_anonymous
225
- user_id = cookies[:fluidfeatures_anonymous]
229
+ user[:id] = cookies[:fluidfeatures_anonymous]
226
230
  else
227
231
  # 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
232
+ user[:id] = "anon-" + Random.rand(9999999999).to_s + "-" + ((Time.now.to_f * 1000000).to_i % 1000000).to_s
229
233
  end
230
234
  end
231
- # update the cookie, with whatever the user_id has been set to
232
- cookies[:fluidfeatures_anonymous] = user_id
235
+ # update the cookie, with whatever the user[:id] has been set to
236
+ cookies[:fluidfeatures_anonymous] = user[:id]
233
237
  end
238
+ user[:anonymous] = !!user[:anonymous]
239
+ @ff_user = user
240
+ end
234
241
 
235
- @ff_user_id = user_id
236
- @ff_user_anonymous = !!options[:anonymous]
237
- @ff_user_attributes = options[:attributes]
238
-
239
- user_id
242
+ def fluidfeatures_user
243
+ unless @ff_user
244
+ fluidfeatures_initialize_user
245
+ end
246
+ @ff_user
240
247
  end
241
-
248
+
242
249
  #
243
250
  # This is called by the developer's code to determine if the
244
251
  # feature, specified by "feature_name" is enabled for the
@@ -254,15 +261,15 @@ module ActionController
254
261
  end
255
262
  global_defaults = fluidfeatures_defaults || {}
256
263
  version_name = (defaults[:version] || global_defaults[:version]).to_s
257
- if not @features
264
+ if not @ff_features
258
265
  fluidfeatures_retrieve_user_features
259
266
  end
260
- if @features.has_key? feature_name
261
- if @features[feature_name].is_a? FalseClass or @features[feature_name].is_a? TrueClass
262
- enabled = @features[feature_name]
263
- elsif @features[feature_name].is_a? Hash
264
- if @features[feature_name].has_key? version_name
265
- enabled = @features[feature_name][version_name]
267
+ if @ff_features.has_key? feature_name
268
+ if @ff_features[feature_name].is_a? FalseClass or @ff_features[feature_name].is_a? TrueClass
269
+ enabled = @ff_features[feature_name]
270
+ elsif @ff_features[feature_name].is_a? Hash
271
+ if @ff_features[feature_name].has_key? version_name
272
+ enabled = @ff_features[feature_name][version_name]
266
273
  end
267
274
  end
268
275
  end
@@ -279,26 +286,34 @@ module ActionController
279
286
  FluidFeatures::Rails.unknown_feature_hit(feature_name, version_name, options)
280
287
  end
281
288
  if enabled
282
- @features_hit ||= {}
283
- @features_hit[feature_name] ||= {}
284
- @features_hit[feature_name][version_name.to_s] = {}
289
+ @ff_features_hit[feature_name] ||= {}
290
+ @ff_features_hit[feature_name][version_name.to_s] = {}
285
291
  end
286
292
  enabled
287
293
  end
288
294
 
295
+ def fluidgoal(goal_name, defaults={})
296
+ global_defaults = fluidfeatures_defaults || {}
297
+ version_name = (defaults[:version] || global_defaults[:version]).to_s
298
+ @ff_goals_hit[goal_name] ||= {}
299
+ @ff_goals_hit[goal_name][version_name.to_s] = {}
300
+ end
301
+
289
302
  #
290
303
  # Initialize the FluidFeatures state for this request.
291
304
  #
292
305
  def fluidfeatures_request_before
293
306
  @ff_request_start_time = Time.now
294
- @features = nil
307
+ @ff_features = nil
308
+ @ff_features_hit = {}
309
+ @ff_goals_hit = {}
295
310
  end
296
311
 
297
312
  #
298
313
  # Returns the features enabled for this request's user.
299
314
  #
300
315
  def fluidfeatures_retrieve_user_features
301
- @features = FluidFeatures::Rails.get_user_features(@ff_user_id)
316
+ @ff_features = FluidFeatures::Rails.get_user_features(fluidfeatures_user[:id])
302
317
  end
303
318
 
304
319
  #
@@ -309,28 +324,30 @@ module ActionController
309
324
  # without requiring the developer to do it manually.
310
325
  #
311
326
  def fluidfeatures_request_after
312
- if @features
313
- request_duration = Time.now - @ff_request_start_time
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)
327
+ request_duration = Time.now - @ff_request_start_time
328
+ url = "#{request.protocol}#{request.host_with_port}#{request.fullpath}"
329
+ payload = {
330
+ :user => {
331
+ :id => fluidfeatures_user[:id]
332
+ },
333
+ :stats => {
334
+ :request => {
335
+ :duration => request_duration
336
+ }
337
+ },
338
+ :hits => {
339
+ :feature => @ff_features_hit,
340
+ :goal => @ff_goals_hit
341
+ },
342
+ :url => url
343
+ }
344
+ if fluidfeatures_user[:anonymous]
345
+ (payload[:user] ||= {})[:anonymous] = true
346
+ end
347
+ if fluidfeatures_user[:attributes]
348
+ (payload[:user] ||= {})[:attributes] = fluidfeatures_user[:attributes]
333
349
  end
350
+ FluidFeatures::Rails.log_request(fluidfeatures_user[:id], payload)
334
351
  end
335
352
 
336
353
  def fluidfeatures_defaults
@@ -1,17 +1,16 @@
1
1
  class ApplicationController < ActionController::Base
2
- protect_from_forgery
3
-
4
- before_filter :authenticate_user
5
2
 
6
3
  # simple authentication. user passes their id
7
4
  def authenticate_user
8
- user_id = params[:user_id]
9
- unless user_id
10
- raise "user_id not given"
11
- end
12
-
13
- # inform fluidfeatures gem of the user id
14
- fluidfeatures_set_user_id(user_id)
5
+ params[:user_id]
6
+ end
7
+
8
+ def current_user_id
9
+ @current_user_id ||= authenticate_user
10
+ end
11
+
12
+ def fluidfeature_current_user(verbose=false)
13
+ { :id => current_user_id }
15
14
  end
16
15
 
17
16
  end
@@ -40,12 +40,19 @@ describe HomeController do
40
40
  features_hit_request = FakeWeb.last_request
41
41
  JsonSpec.exclude_keys("duration", "ff_latency")
42
42
  features_hit_request.body.should be_json_eql(%({
43
- "features": {
44
- "hit": {
43
+ "user": {
44
+ "id": "1"
45
+ },
46
+ "hits": {
47
+ "feature": {
45
48
  "apples": {
46
49
  "default": {}
47
50
  }
48
51
  },
52
+ "goal": {
53
+ }
54
+ },
55
+ "features": {
49
56
  "unknown": {
50
57
  // features that we have not seen before
51
58
  "apples": {
@@ -90,8 +97,11 @@ describe HomeController do
90
97
  features_hit_request = FakeWeb.last_request
91
98
  JsonSpec.exclude_keys("duration", "ff_latency")
92
99
  features_hit_request.body.should be_json_eql(%({
93
- "features": {
94
- "hit": {
100
+ "user": {
101
+ "id": "2"
102
+ },
103
+ "hits": {
104
+ "feature": {
95
105
  "oranges": {
96
106
  "default": {}
97
107
  },
@@ -99,6 +109,10 @@ describe HomeController do
99
109
  "default": {}
100
110
  }
101
111
  },
112
+ "goal": {
113
+ }
114
+ },
115
+ "features": {
102
116
  "unknown": {
103
117
  // no unknown features
104
118
  }
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.4
4
+ version: 0.2.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: 2012-09-22 00:00:00.000000000 Z
12
+ date: 2012-10-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: persistent_http
@@ -41,6 +41,8 @@ files:
41
41
  - Rakefile
42
42
  - fluidfeatures-rails.gemspec
43
43
  - lib/fluidfeatures/rails.rb
44
+ - lib/fluidfeatures/rails/app/controllers/fluidfeatures_controller.rb
45
+ - lib/fluidfeatures/rails/config/routes.rb
44
46
  - lib/fluidfeatures/rails/version.rb
45
47
  - test/testapp/.gitignore
46
48
  - test/testapp/Gemfile