i_wonder 0.0.9 → 0.1.1

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.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- = IWonder (Alpha)
1
+ = IWonder (Beat)
2
2
 
3
3
  Flexible Analytics, and Testing for every corner of your rails application. I read "The Lean Startup" and got inspired. There were a few good solutions, but none of them quite did what I was looking for.
4
4
 
@@ -6,7 +6,7 @@ module IWonder
6
6
 
7
7
  has_many :test_group_memberships, :dependent => :destroy, :foreign_key => "ab_test_sym", :primary_key => :sym
8
8
 
9
- has_many :ab_test_goals, :dependent => :destroy, :foreign_key => "ab_test_sym", :primary_key => :sym
9
+ has_many :ab_test_goals, :dependent => :destroy, :foreign_key => "ab_test_sym", :primary_key => "sym"
10
10
  accepts_nested_attributes_for :ab_test_goals, :allow_destroy => true
11
11
 
12
12
  hash_accessor :options, :test_group_names, :type => :array, :reject_blanks => true
@@ -18,6 +18,31 @@ module IWonder
18
18
  validates_uniqueness_of :sym, :on => :create, :message => "must be unique"
19
19
  validates_inclusion_of :test_applies_to, :in => %w( session user account ), :on => :create, :message => "extension %s is not included in the list"
20
20
 
21
+
22
+ # ----------------------------------------------------------------------------------------------------------------------------------------
23
+ # These two methods should NOT be needed. For some reason the accepts_nested_attributes_for is not autosaving or deleting associated goals
24
+
25
+ def ab_test_goals_attributes=(hash)
26
+ hash.each{|key,value|
27
+ goal = self.ab_test_goals.detect{|tg| tg.id == value["id"].to_i}
28
+ goal ||= self.ab_test_goals.build
29
+ goal.attributes = value
30
+
31
+ if value["_destroy"] =~ /true|1/ or value["_destroy"].is_a?(TrueClass)
32
+ goal.mark_for_destruction
33
+ end
34
+ }
35
+ end
36
+ before_save :remove_deleted_test_goals
37
+ def remove_deleted_test_goals
38
+ ab_test_goals.select(&:marked_for_destruction?).each(&:destroy)
39
+ ab_test_goals.each(&:save)
40
+ end
41
+
42
+
43
+ # ----------------------------------------------------------------------------------------------------------------------------------------
44
+
45
+
21
46
  validate :has_two_groups_and_a_goal
22
47
  def has_two_groups_and_a_goal
23
48
  unless test_group_names.length >= 2
@@ -30,7 +55,7 @@ module IWonder
30
55
  end
31
56
 
32
57
  after_save :save_to_file
33
- def save_to_file
58
+ def save_to_file
34
59
  AbTesting::Loader.save_ab_test(self)
35
60
  end
36
61
 
@@ -47,7 +72,13 @@ module IWonder
47
72
  if(current_group = get_current_group(current_controller))
48
73
  return current_group.test_group_name
49
74
  else
50
- test_group = add_to_test_group(randomly_chosen_test_group, current_controller)
75
+ begin
76
+ test_group = add_to_test_group(randomly_chosen_test_group, current_controller)
77
+ rescue Exception => e
78
+ # If there is some error, just return a randome option. Better not to crash
79
+ # TODO: this should warn developer somehow
80
+ return randomly_chosen_test_group
81
+ end
51
82
  return test_group.test_group_name
52
83
  end
53
84
  end
@@ -71,7 +102,9 @@ module IWonder
71
102
 
72
103
  scoped_groups_with_goal_events = ab_test_goal.add_goal_to_query(scoped_groups_with_events)
73
104
 
74
- scoped_groups_with_goal_events.count
105
+ scoped_groups_with_goal_events = scoped_groups_with_goal_events.select("COUNT(DISTINCT i_wonder_events.#{event_membership_key}) as count_all")
106
+
107
+ AbTest.connection.execute(scoped_groups_with_goal_events.to_sql)[0]["count_all"].to_i
75
108
  end
76
109
 
77
110
  def from_xml(xml)
@@ -14,6 +14,14 @@ module IWonder
14
14
  validates_presence_of :event_type, :if => :tracks_event?
15
15
  validates_presence_of :page_view_controller, :if => :tracks_page_view?
16
16
 
17
+ before_validation :clean_up_controller
18
+ def clean_up_controller
19
+ if tracks_page_view?
20
+ page_view_controller.gsub!("Controller", "")
21
+ page_view_controller.downcase!
22
+ end
23
+ end
24
+
17
25
  def tracks_event?
18
26
  goal_type == "Event"
19
27
  end
@@ -26,7 +34,7 @@ module IWonder
26
34
  if tracks_event?
27
35
  sc = scoped_statement.where("i_wonder_events.event_type = ?", event_type)
28
36
  else
29
- sc = scoped_statement.where("i_wonder_events.event_type = ? AND controller = ?", "hit", page_view_controller)
37
+ sc = scoped_statement.where("i_wonder_events.event_type = ? AND i_wonder_events.controller = ?", "hit", page_view_controller)
30
38
 
31
39
  if page_view_action.present?
32
40
  sc = sc.where("i_wonder_events.action = ?", page_view_action)
@@ -15,7 +15,7 @@
15
15
  </ul>
16
16
  <% end %>
17
17
 
18
- <% unless Rails.env.production? %>
18
+ <% if Rails.env.development? %>
19
19
  <p>
20
20
  <%= button_to "Create a new ABTest", url_for(:action => :new), :method => :get%>
21
21
  </p>
@@ -1,12 +1,12 @@
1
1
  <div class="show">
2
- <% if Rails.env.production? %>
3
- <span class="description">No Modifying tests in production</span>
4
- <% else %>
2
+ <% if Rails.env.development? %>
5
3
  <p>
6
4
  <%= link_to "Edit", edit_ab_test_path(@ab_test) %>
7
5
  |
8
6
  <%= link_to "Delete", @ab_test, :method => :delete, :confirm => "Are you sure?" %>
9
7
  </p>
8
+ <% else %>
9
+ <span class="description">No Modifying tests in production</span>
10
10
  <% end %>
11
11
 
12
12
  <h2>I wonder <%= @ab_test.name%>?</h2>
@@ -5,8 +5,7 @@ module IWonder
5
5
 
6
6
  initializer "i_wonder.loading_tests" do |app|
7
7
 
8
- # can't load if it's migrating the db
9
- unless ( File.basename($0) == "rake" && ARGV.include?("db:migrate") )
8
+ unless File.basename($0) == "rake" # don't run on rake tasks (migration and asset:precompile have cause lot's of problems)
10
9
  ActiveRecord::Base.send :include, HashAccessor # this is to avoid load order issues from a required gem
11
10
  AbTesting::Loader.load_all
12
11
  end
@@ -28,7 +27,7 @@ class Railtie < Rails::Railtie
28
27
  ApplicationController.send :include, IWonder::Logging::ActionControllerMixins
29
28
  ApplicationController.send :include, IWonder::AbTesting::ActionControllerMixins
30
29
 
31
- ActiveRecord.send :include, IWonder::Logging::ActiveRecordMixins
30
+ ActiveRecord::Base.send :include, IWonder::Logging::ActiveRecordMixins
32
31
  end
33
32
 
34
33
  end
@@ -1,3 +1,3 @@
1
1
  module IWonder
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -67879,3 +67879,24 @@ Served asset /i_wonder/reports.js - 304 Not Modified (0ms)
67879
67879
 
67880
67880
  Started GET "/assets/i_wonder/application.js?body=1" for 127.0.0.1 at 2011-10-31 11:41:44 -0700
67881
67881
  Served asset /i_wonder/application.js - 304 Not Modified (0ms)
67882
+ IWonder::AbTest Load (1.4ms) SELECT "i_wonder_ab_tests".* FROM "i_wonder_ab_tests" WHERE "i_wonder_ab_tests"."sym" = 'unique_sym_1' LIMIT 1
67883
+ WARNING: Can't mass-assign protected attributes: ab_test_goals
67884
+ WARNING: Can't mass-assign protected attributes: type, ab_test_sym
67885
+  (0.1ms) BEGIN
67886
+  (0.4ms) SELECT 1 FROM "i_wonder_ab_tests" WHERE "i_wonder_ab_tests"."name" = 'Unique Test 1' LIMIT 1
67887
+  (0.2ms) SELECT 1 FROM "i_wonder_ab_tests" WHERE "i_wonder_ab_tests"."sym" = 'unique_sym_1' LIMIT 1
67888
+ SQL (3.3ms) INSERT INTO "i_wonder_ab_tests" ("created_at", "description", "name", "options", "sym", "test_applies_to", "test_group_data", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["created_at", Tue, 01 Nov 2011 01:12:12 UTC +00:00], ["description", nil], ["name", "Unique Test 1"], ["options", "--- \n:test_group_names: \n- Options 1\n- Options 2\n"], ["sym", "unique_sym_1"], ["test_applies_to", "session"], ["test_group_data", "--- {}\n\n"], ["updated_at", Tue, 01 Nov 2011 01:12:12 UTC +00:00]]
67889
+ SQL (0.7ms) INSERT INTO "i_wonder_ab_test_goals" ("ab_test_sym", "options") VALUES ($1, $2) RETURNING "id" [["ab_test_sym", "unique_sym_1"], ["options", "--- \n:event_type: success\n:goal_type: Event\n"]]
67890
+  (0.6ms) COMMIT
67891
+ PGError: ERROR: column "member_id" does not exist
67892
+ LINE 1: SELECT DISTINCT(member_id), COUNT(*) FROM "i_wonder_events"
67893
+ ^
67894
+ : SELECT DISTINCT(member_id), COUNT(*) FROM "i_wonder_events"
67895
+ PGError: ERROR: column "i_wonder_events.session_id" must appear in the GROUP BY clause or be used in an aggregate function
67896
+ LINE 1: SELECT DISTINCT(session_id), COUNT(*) FROM "i_wonder_events"...
67897
+ ^
67898
+ : SELECT DISTINCT(session_id), COUNT(*) FROM "i_wonder_events"
67899
+ PGError: ERROR: column "i_wonder_events.id" must appear in the GROUP BY clause or be used in an aggregate function
67900
+ LINE 1: SELECT "i_wonder_events".* FROM "i_wonder_events" GROUP BY ...
67901
+ ^
67902
+ : SELECT "i_wonder_events".* FROM "i_wonder_events" GROUP BY session_id