profitably-km 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/CHANGELOG +4 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +33 -0
  4. data/README.rdoc +14 -0
  5. data/Rakefile +19 -0
  6. data/VERSION +1 -0
  7. data/bin/km_send +42 -0
  8. data/doc/Accept.html +546 -0
  9. data/doc/Gemfile.html +110 -0
  10. data/doc/Hash.html +283 -0
  11. data/doc/Helper.html +318 -0
  12. data/doc/KM.html +493 -0
  13. data/doc/KM/IdentError.html +159 -0
  14. data/doc/KM/InitError.html +159 -0
  15. data/doc/KM/SaaS.html +451 -0
  16. data/doc/KMError.html +159 -0
  17. data/doc/Object.html +211 -0
  18. data/doc/README_rdoc.html +122 -0
  19. data/doc/Rakefile.html +111 -0
  20. data/doc/String.html +244 -0
  21. data/doc/bin/km_send.html +54 -0
  22. data/doc/created.rid +15 -0
  23. data/doc/images/brick.png +0 -0
  24. data/doc/images/brick_link.png +0 -0
  25. data/doc/images/bug.png +0 -0
  26. data/doc/images/bullet_black.png +0 -0
  27. data/doc/images/bullet_toggle_minus.png +0 -0
  28. data/doc/images/bullet_toggle_plus.png +0 -0
  29. data/doc/images/date.png +0 -0
  30. data/doc/images/find.png +0 -0
  31. data/doc/images/loadingAnimation.gif +0 -0
  32. data/doc/images/macFFBgHack.png +0 -0
  33. data/doc/images/package.png +0 -0
  34. data/doc/images/page_green.png +0 -0
  35. data/doc/images/page_white_text.png +0 -0
  36. data/doc/images/page_white_width.png +0 -0
  37. data/doc/images/plugin.png +0 -0
  38. data/doc/images/ruby.png +0 -0
  39. data/doc/images/tag_green.png +0 -0
  40. data/doc/images/wrench.png +0 -0
  41. data/doc/images/wrench_orange.png +0 -0
  42. data/doc/images/zoom.png +0 -0
  43. data/doc/index.html +142 -0
  44. data/doc/js/darkfish.js +116 -0
  45. data/doc/js/jquery.js +32 -0
  46. data/doc/js/quicksearch.js +114 -0
  47. data/doc/js/thickbox-compressed.js +10 -0
  48. data/doc/lib/km/saas_rb.html +54 -0
  49. data/doc/lib/km/version_rb.html +52 -0
  50. data/doc/lib/km_rb.html +60 -0
  51. data/doc/rdoc.css +730 -0
  52. data/doc/spec/accept_rb.html +62 -0
  53. data/doc/spec/km_old_rb.html +54 -0
  54. data/doc/spec/km_saas_spec_rb.html +56 -0
  55. data/doc/spec/km_send_spec_rb.html +54 -0
  56. data/doc/spec/km_spec_rb.html +54 -0
  57. data/doc/spec/setup_rb.html +60 -0
  58. data/doc/spec/watchr_rb.html +52 -0
  59. data/km.gemspec +28 -0
  60. data/lib/km.rb +262 -0
  61. data/lib/km/saas.rb +39 -0
  62. data/lib/km/version.rb +3 -0
  63. data/spec/accept.rb +90 -0
  64. data/spec/km_old.rb +105 -0
  65. data/spec/km_saas_spec.rb +121 -0
  66. data/spec/km_send_spec.rb +89 -0
  67. data/spec/km_spec.rb +186 -0
  68. data/spec/log/.hold +0 -0
  69. data/spec/setup.rb +78 -0
  70. data/spec/watchr.rb +3 -0
  71. metadata +237 -0
data/spec/km_spec.rb ADDED
@@ -0,0 +1,186 @@
1
+ require 'setup'
2
+ describe KM do
3
+ before do
4
+ KM::reset
5
+ now = Time.now
6
+ Time.stub!(:now).and_return(now)
7
+ FileUtils.rm_f KM::log_name(:error)
8
+ FileUtils.rm_f KM::log_name(:query)
9
+ Helper.clear
10
+ end
11
+ it "shouldn't write at all without init or identify" do
12
+ KM::record 'My Action'
13
+ IO.readlines(KM::log_name(:error)).join.should =~ /Need to initialize first \(KM::init <your_key>\)/
14
+
15
+ FileUtils.rm_f KM::log_name(:error)
16
+ KM::set :day => 'friday'
17
+ IO.readlines(KM::log_name(:error)).join.should =~ /Need to initialize first \(KM::init <your_key>\)/
18
+
19
+ KM::init 'KM_KEY', :log_dir => __('log'), :host => '127.0.0.1:9292'
20
+ FileUtils.rm_f KM::log_name(:error)
21
+ KM::record 'My Action'
22
+ IO.readlines(KM::log_name(:error)).last.should =~ /Need to identify first \(KM::identify <user>\)/
23
+
24
+ FileUtils.rm_f KM::log_name(:error)
25
+ KM::set :day => 'friday'
26
+ IO.readlines(KM::log_name(:error)).last.should =~ /Need to identify first \(KM::identify <user>\)/
27
+ end
28
+
29
+ it "shouldn't fail on alias without identifying" do
30
+ KM::init 'KM_OTHER', :log_dir => __('log'), :host => '127.0.0.1:9292'
31
+ KM::alias 'peter','joe' # Alias "bob" to "robert"
32
+ sleep 0.1
33
+ res = Helper.accept(:history).first.indifferent
34
+ res[:path].should == '/a'
35
+ res[:query]['_k'].first.should == 'KM_OTHER'
36
+ res[:query]['_p'].first.should == 'peter'
37
+ res[:query]['_n'].first.should == 'joe'
38
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
39
+ end
40
+ it "shouldn't fail on alias without identifying from commandline" do
41
+ KM::init 'KM_OTHER', :log_dir => __('log'), :host => '127.0.0.1:9292'
42
+ KM::alias 'peter','joe' # Alias "bob" to "robert"
43
+ sleep 0.1
44
+ res = Helper.accept(:history).first.indifferent
45
+ res[:path].should == '/a'
46
+ res[:query]['_k'].first.should == 'KM_OTHER'
47
+ res[:query]['_p'].first.should == 'peter'
48
+ res[:query]['_n'].first.should == 'joe'
49
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
50
+ end
51
+
52
+ describe "should record events" do
53
+ before do
54
+ KM::init 'KM_KEY', :log_dir => __('log'), :host => '127.0.0.1:9292'
55
+ KM::identify 'bob'
56
+ end
57
+ it "records an action with no action-specific properties" do
58
+ KM::record 'My Action'
59
+ sleep 0.1
60
+ res = Helper.accept(:history).first.indifferent
61
+ res[:path].should == '/e'
62
+ res[:query]['_k'].first.should == 'KM_KEY'
63
+ res[:query]['_p'].first.should == 'bob'
64
+ res[:query]['_n'].first.should == 'My Action'
65
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
66
+ end
67
+ it "records an action with properties" do
68
+ KM::record 'Signup', 'age' => 26
69
+ sleep 0.1
70
+ res = Helper.accept(:history).first.indifferent
71
+ res[:path].should == '/e'
72
+ res[:query]['_k'].first.should == 'KM_KEY'
73
+ res[:query]['_p'].first.should == 'bob'
74
+ res[:query]['_n'].first.should == 'Signup'
75
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
76
+ res[:query]['age'].first.should == 26.to_s
77
+ end
78
+ it "should be able to hace spaces in key and value" do
79
+ KM::record 'Signup', 'age' => 26, 'city of residence' => 'eug ene'
80
+ sleep 0.1
81
+ res = Helper.accept(:history).first.indifferent
82
+ res[:path].should == '/e'
83
+ res[:query]['_k'].first.should == 'KM_KEY'
84
+ res[:query]['_p'].first.should == 'bob'
85
+ res[:query]['_n'].first.should == 'Signup'
86
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
87
+ res[:query]['age'].first.should == 26.to_s
88
+ res[:query]['city of residence'].first.should == 'eug ene'
89
+ end
90
+ it "should not override important parts" do
91
+ KM::record 'Signup', 'age' => 26, '_p' => 'billybob', '_k' => 'foo', '_n' => 'something else'
92
+ sleep 0.1
93
+ res = Helper.accept(:history).first.indifferent
94
+ res[:path].should == '/e'
95
+ res[:query]['_k'].first.should == 'KM_KEY'
96
+ res[:query]['_p'].first.should == 'bob'
97
+ res[:query]['_n'].first.should == 'Signup'
98
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
99
+ res[:query]['age'].first.should == 26.to_s
100
+ end
101
+ it "should work with propps using @" do
102
+ KM::record 'Signup', 'email' => 'test@blah.com', '_p' => 'billybob', '_k' => 'foo', '_n' => 'something else'
103
+ res = Helper.accept(:history).first.indifferent
104
+ res[:path].should == '/e'
105
+ res[:query]['_k'].first.should == 'KM_KEY'
106
+ res[:query]['_p'].first.should == 'bob'
107
+ res[:query]['_n'].first.should == 'Signup'
108
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
109
+ res[:query]['email'].first.should == 'test@blah.com'
110
+ end
111
+ it "should just set properties without event" do
112
+ KM::record 'age' => 26
113
+ sleep 0.1
114
+ res = Helper.accept(:history).first.indifferent
115
+ res[:path].should == '/s'
116
+ res[:query]['_k'].first.should == 'KM_KEY'
117
+ res[:query]['_p'].first.should == 'bob'
118
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
119
+ res[:query]['age'].first.should == 26.to_s
120
+ end
121
+ it "should be able to use km set directly" do
122
+ KM::set 'age' => 26
123
+ sleep 0.1
124
+ res = Helper.accept(:history).first.indifferent
125
+ res[:path].should == '/s'
126
+ res[:query]['_k'].first.should == 'KM_KEY'
127
+ res[:query]['_p'].first.should == 'bob'
128
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
129
+ res[:query]['age'].first.should == 26.to_s
130
+ end
131
+ it "should work with multiple lines" do
132
+ # testing recording of multiple lines.
133
+ KM::record 'Signup', 'age' => 26
134
+ sleep 0.1
135
+ KM::record 'Signup', 'age' => 36
136
+ sleep 0.1
137
+ res = Helper.accept(:history)[0].indifferent
138
+ res[:path].should == '/e'
139
+ res[:query]['_k'].first.should == 'KM_KEY'
140
+ res[:query]['_p'].first.should == 'bob'
141
+ res[:query]['_n'].first.should == 'Signup'
142
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
143
+ res[:query]['age'].first.should == 26.to_s
144
+ res = Helper.accept(:history)[1].indifferent
145
+ res[:path].should == '/e'
146
+ res[:query]['_k'].first.should == 'KM_KEY'
147
+ res[:query]['_p'].first.should == 'bob'
148
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
149
+ res[:query]['age'].first.should == 36.to_s
150
+ end
151
+ it "should not have key hardcoded anywhere" do
152
+ KM::init 'KM_OTHER', :log_dir => __('log')
153
+ KM::alias 'truman','harry' # Alias "bob" to "robert"
154
+ sleep 0.1
155
+ res = Helper.accept(:history)[0].indifferent
156
+ res[:path].should == '/a'
157
+ res[:query]['_k'].first.should == 'KM_OTHER'
158
+ res[:query]['_p'].first.should == 'truman'
159
+ res[:query]['_n'].first.should == 'harry'
160
+ res[:query]['_t'].first.should == Time.now.to_i.to_s
161
+ end
162
+ end
163
+ context "reading from files" do
164
+ before do
165
+ Dir.glob(__('log','*')).each do |file|
166
+ FileUtils.rm file
167
+ end
168
+ KM.reset
169
+ end
170
+ it "should run fine even though there's no server to connect to" do
171
+ KM::init 'KM_OTHER', :log_dir => __('log'), :host => '127.0.0.1:9291', :to_stderr => false
172
+ KM::identify 'bob'
173
+ KM::record 'My Action' # records an action with no action-specific properties;
174
+ Helper.accept(:history).size.should == 0
175
+ File.exists?(__('log/kissmetrics_production_query.log')).should == true
176
+ File.exists?(__('log/kissmetrics_production_error.log')).should == true
177
+ end
178
+
179
+ it "should escape @ properly" do
180
+ KM::init 'KM_OTHER', :log_dir => __('log'), :host => '127.0.0.1:9292', :to_stderr => false, :use_cron => true
181
+ KM::identify 'bob'
182
+ KM::record 'prop_with_@_in' # records an action with no action-specific properties;
183
+ IO.readlines(KM::log_name(:query)).join.should_not contain_string('@')
184
+ end
185
+ end
186
+ end
data/spec/log/.hold ADDED
File without changes
data/spec/setup.rb ADDED
@@ -0,0 +1,78 @@
1
+ require 'ap'
2
+ require 'km'
3
+ require 'fileutils'
4
+ require 'accept'
5
+
6
+ class KM
7
+ class << self
8
+ public :log_name, :reset, :log
9
+ end
10
+ end
11
+
12
+ def __(*args)
13
+ file_this_included_from = caller.first.split(":").first
14
+ app_root = File.expand_path(File.dirname(file_this_included_from))
15
+ args = [app_root]+args
16
+ File.expand_path(File.join(args))
17
+ end
18
+
19
+ class Helper
20
+ def self.accept(cmd)
21
+ c = TCPSocket.new('localhost', 9292)
22
+ c.puts cmd.to_s
23
+ return JSON.parse(c.read) rescue nil
24
+ end
25
+ def self.history
26
+ accept :history
27
+ end
28
+ def self.clear
29
+ accept :clear
30
+ end
31
+ def self.exit
32
+ accept :exit
33
+ end
34
+ end
35
+ class String
36
+ def sort
37
+ self.split('').sort.join('')
38
+ end
39
+ def sort!
40
+ replace(self.sort)
41
+ end
42
+ end
43
+
44
+ RSpec::Matchers.define :have_query_string do |expected|
45
+ match do |value|
46
+ expected.sort == value.sort
47
+ end
48
+
49
+ failure_message_for_should do |value|
50
+ "expected #{value.inspect} to match #{expected.inspect}"
51
+ end
52
+ end
53
+ #======================================#
54
+ #= contain_string =#
55
+ #======================================#
56
+ # Check if a string has another string. Usage:
57
+ # some_string.should contain("my string")
58
+ RSpec::Matchers.define :contain_string do |needle|
59
+ match do |haystack|
60
+ haystack.index(needle) ? true : false
61
+ end
62
+ end
63
+
64
+ class Hash
65
+ def indifferent
66
+ Hash.new { |hash,key| hash[key.to_s] if key.class == Symbol }.merge(self)
67
+ end
68
+ end
69
+
70
+ def write_log(type, content)
71
+ KM.instance_eval { @log_dir = __('log') }
72
+ log_name = KM.send :log_name, type
73
+ File.open(log_name, 'w+') do |fh|
74
+ fh.puts content
75
+ end
76
+ end
77
+
78
+ accept = Accept.new
data/spec/watchr.rb ADDED
@@ -0,0 +1,3 @@
1
+ watch('spec/.*spec\.rb') { |md| system("bundle exec rspec --color #{md[0]}") }
2
+ watch('lib/km\.rb') { |md| system("bundle exec rake spec") }
3
+ watch('lib/km/saas\.rb') { |md| system("bundle exec rspec --color spec/km_saas_spec.rb") }
metadata ADDED
@@ -0,0 +1,237 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: profitably-km
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 2
10
+ version: 1.1.2
11
+ platform: ruby
12
+ authors:
13
+ - KISSmetrics
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-30 00:00:00 -04:00
19
+ default_executable: km_send
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ name: km
32
+ version_requirements: *id001
33
+ prerelease: false
34
+ type: :runtime
35
+ - !ruby/object:Gem::Dependency
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 23
42
+ segments:
43
+ - 1
44
+ - 0
45
+ - 0
46
+ version: 1.0.0
47
+ name: bundler
48
+ version_requirements: *id002
49
+ prerelease: false
50
+ type: :development
51
+ - !ruby/object:Gem::Dependency
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ hash: 31
58
+ segments:
59
+ - 2
60
+ - 4
61
+ - 0
62
+ version: 2.4.0
63
+ name: rspec
64
+ version_requirements: *id003
65
+ prerelease: false
66
+ type: :development
67
+ - !ruby/object:Gem::Dependency
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ name: awesome_print
78
+ version_requirements: *id004
79
+ prerelease: false
80
+ type: :development
81
+ - !ruby/object:Gem::Dependency
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ name: rake
92
+ version_requirements: *id005
93
+ prerelease: false
94
+ type: :development
95
+ - !ruby/object:Gem::Dependency
96
+ requirement: &id006 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ name: watchr
106
+ version_requirements: *id006
107
+ prerelease: false
108
+ type: :development
109
+ - !ruby/object:Gem::Dependency
110
+ requirement: &id007 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ name: json
120
+ version_requirements: *id007
121
+ prerelease: false
122
+ type: :development
123
+ description: KISSmetrics ruby API gem. Forked from https://github.com/challengepost/km
124
+ email: francis.hwang@profitably.com
125
+ executables:
126
+ - km_send
127
+ extensions: []
128
+
129
+ extra_rdoc_files:
130
+ - README.rdoc
131
+ files:
132
+ - CHANGELOG
133
+ - Gemfile
134
+ - Gemfile.lock
135
+ - README.rdoc
136
+ - Rakefile
137
+ - VERSION
138
+ - bin/km_send
139
+ - doc/Accept.html
140
+ - doc/Gemfile.html
141
+ - doc/Hash.html
142
+ - doc/Helper.html
143
+ - doc/KM.html
144
+ - doc/KM/IdentError.html
145
+ - doc/KM/InitError.html
146
+ - doc/KM/SaaS.html
147
+ - doc/KMError.html
148
+ - doc/Object.html
149
+ - doc/README_rdoc.html
150
+ - doc/Rakefile.html
151
+ - doc/String.html
152
+ - doc/bin/km_send.html
153
+ - doc/created.rid
154
+ - doc/images/brick.png
155
+ - doc/images/brick_link.png
156
+ - doc/images/bug.png
157
+ - doc/images/bullet_black.png
158
+ - doc/images/bullet_toggle_minus.png
159
+ - doc/images/bullet_toggle_plus.png
160
+ - doc/images/date.png
161
+ - doc/images/find.png
162
+ - doc/images/loadingAnimation.gif
163
+ - doc/images/macFFBgHack.png
164
+ - doc/images/package.png
165
+ - doc/images/page_green.png
166
+ - doc/images/page_white_text.png
167
+ - doc/images/page_white_width.png
168
+ - doc/images/plugin.png
169
+ - doc/images/ruby.png
170
+ - doc/images/tag_green.png
171
+ - doc/images/wrench.png
172
+ - doc/images/wrench_orange.png
173
+ - doc/images/zoom.png
174
+ - doc/index.html
175
+ - doc/js/darkfish.js
176
+ - doc/js/jquery.js
177
+ - doc/js/quicksearch.js
178
+ - doc/js/thickbox-compressed.js
179
+ - doc/lib/km/saas_rb.html
180
+ - doc/lib/km/version_rb.html
181
+ - doc/lib/km_rb.html
182
+ - doc/rdoc.css
183
+ - doc/spec/accept_rb.html
184
+ - doc/spec/km_old_rb.html
185
+ - doc/spec/km_saas_spec_rb.html
186
+ - doc/spec/km_send_spec_rb.html
187
+ - doc/spec/km_spec_rb.html
188
+ - doc/spec/setup_rb.html
189
+ - doc/spec/watchr_rb.html
190
+ - km.gemspec
191
+ - lib/km.rb
192
+ - lib/km/saas.rb
193
+ - lib/km/version.rb
194
+ - spec/accept.rb
195
+ - spec/km_old.rb
196
+ - spec/km_saas_spec.rb
197
+ - spec/km_send_spec.rb
198
+ - spec/km_spec.rb
199
+ - spec/log/.hold
200
+ - spec/setup.rb
201
+ - spec/watchr.rb
202
+ has_rdoc: true
203
+ homepage: http://github.com/profitably/km
204
+ licenses:
205
+ - MIT
206
+ post_install_message:
207
+ rdoc_options: []
208
+
209
+ require_paths:
210
+ - lib
211
+ required_ruby_version: !ruby/object:Gem::Requirement
212
+ none: false
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ hash: 3
217
+ segments:
218
+ - 0
219
+ version: "0"
220
+ required_rubygems_version: !ruby/object:Gem::Requirement
221
+ none: false
222
+ requirements:
223
+ - - ">="
224
+ - !ruby/object:Gem::Version
225
+ hash: 3
226
+ segments:
227
+ - 0
228
+ version: "0"
229
+ requirements: []
230
+
231
+ rubyforge_project:
232
+ rubygems_version: 1.6.2
233
+ signing_key:
234
+ specification_version: 3
235
+ summary: KISSmetrics ruby API gem. Forked from https://github.com/challengepost/km
236
+ test_files: []
237
+