mixpanel_magic_lamp 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6c38f0a54b2215f7234f635b0deceee30894e2a9
4
+ data.tar.gz: 4dd271143b3fa52bade4221828ae161c26614e26
5
+ SHA512:
6
+ metadata.gz: 93d6be32305f3927639065860f01d05856f5ac20a4e8cc9a4d086c2983d576e70fee63dfbfd51ee86f8edc30fb64ecb2f6e48765c7e8d5e752716b7f6e0cf744
7
+ data.tar.gz: 3474e0f5503df78eec61fbe54cf95d011cd72d846660d57b8e35592f8be4572fb2f7507c110608b7542ae511ecbde80c7664508117bbeee2fd683c4ab25c717d
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ Gemfile.lock
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ ## 0.1.0 (March 13, 2015)
2
+
3
+ * Interface and expression builder
4
+ * Generator for initialization
5
+ * First doc
6
+
7
+ ## 1.0.0 (March 30, 2015)
8
+
9
+ * Monkey patch for ```Mixpanel::Client::prepare_paralell_request```
10
+ * Queue processor
11
+ * Formatter
12
+ * README info
13
+ * First offical release
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in mixpanel_magic_lamp.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use debugger
14
+ # gem 'debugger'
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Guillermo Guerrero
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,258 @@
1
+ # Mixpanel Magic Lamp
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/mixpanel_magic_lamp.svg)](http://badge.fury.io/rb/mixpanel_magic_lamp)
4
+
5
+ Rub the magic lamp and your desired Mixpanel ORM will appear!
6
+
7
+ If you're using [Mixpanel](https://mixpanel.com/) for your web site analytics you probably thought
8
+ in make reports exporting your data through any **Mixpanel API** client. This gem is your answer
9
+ for not overwarming your head with so many doc, and it will remind you to ```ActiveRecord```.
10
+
11
+ ## Install
12
+ You can install this *gem* by
13
+
14
+ ```
15
+ $ gem install mixpanel_magic_lamp
16
+ ```
17
+
18
+ Or bundle it on your app by adding this line at your *Gemfile*
19
+
20
+ ```ruby
21
+ gem 'mixpanel_magic_lamp'
22
+ ```
23
+
24
+ ## Configuration
25
+ To setup this gem you should add API keys and other config:
26
+ ```ruby
27
+ MixpanelMagicLamp.configure do |config|
28
+ # Set your API Key/Secret
29
+ config.api_key = "YOUR MIXPANEL API KEY"
30
+ config.api_secret = "YOUR MIXPANEL API SECRET"
31
+
32
+ # Run query in parallel (recomended for better performance)
33
+ config.parallel = true
34
+
35
+ # Default interval on from/to dates when dates are not provided
36
+ config.interval = 30
37
+ end
38
+ ```
39
+
40
+ ### Rails config generator
41
+ Copy base config file on your **Rails app** by
42
+ ```bash
43
+ rails generator mixpanel_magic_lamp:config
44
+ ```
45
+
46
+
47
+ ## Build your query
48
+ The most interesting feature from this library is probably the query builder, that
49
+ let you to build an 'ActiveRecord' like query to run API queries, it will remind you to
50
+ the Mixpanel UI:
51
+
52
+ ### where
53
+ Start any query with this keyword, and extend is as long as you need.
54
+ This method accept a hash as first parameter where each pair of key/value are traslated
55
+ to "key == value" (*equals_to*), a second parameter may change union word:
56
+
57
+ ```ruby
58
+ Mixpanel.where(country: 'Spain', gender: 'Female').to_s
59
+ => "(properties[\"country\"] == \"Spain\" and properties[\"gender\"] == \"Female\")"
60
+
61
+ Mixpanel.where({country: 'Spain', gender: 'Female'}, 'or').to_s
62
+ => "(properties[\"country\"] == \"Spain\" or properties[\"gender\"] == \"Female\")"
63
+ ```
64
+
65
+
66
+ Then you may append any existent query build to complete your API query:
67
+
68
+ ```ruby
69
+ Mixpanel.where(country: 'Spain').or.is_set('source').to_s
70
+ => "(properties[\"country\"] == \"Spain\") or (defined (properties[\"source\"]))"
71
+ ```
72
+
73
+ ### and/or
74
+ Concat as many query builders as you need with ```and``` and ```or``` operators:
75
+
76
+ ```ruby
77
+ Mixpanel.where(country: "Spain", browser: "Chrome")
78
+ .and.is_set('device_type')
79
+ .and.does_not_equal(user_type: 'bot')
80
+ .and.contains(url: '/sales')
81
+ => "(properties[\"country\"] == \"Spain\" and properties[\"browser\"] == \"Chrome\") and (defined (properties[\"device_type\"])) and (properties[\"user_type\"] != \"bot\") and (\"/sales\" in (properties[\"url\"]))">
82
+ ```
83
+
84
+
85
+ ### on
86
+ Use it as **by** statement on your UI, in order to group segmentation:
87
+
88
+ ```ruby
89
+ Mixpanel.on('country')
90
+ => "properties[\"country\"]"
91
+ ```
92
+
93
+ ### Builders
94
+
95
+ #### equals
96
+
97
+ ```ruby
98
+ Mixpanel.where.and.equals(country: 'Spain', user_type: 'human').to_s
99
+ => "(properties[\"country\"] == \"Spain\" and properties[\"user_type\"] == \"human\")"
100
+ ```
101
+
102
+ #### does_not_equal
103
+
104
+ ```ruby
105
+ Mixpanel.where.and.does_not_equal(country: 'Spain', user_type: 'human')
106
+ => "(properties[\"country\"] != \"Spain\" and properties[\"user_type\"] != \"human\")"
107
+ ```
108
+
109
+ #### contains
110
+
111
+ ```ruby
112
+ Mixpanel.where.and.contains(country: 'Spain', user_type: 'human').to_s
113
+ => "(\"Spain\" in (properties[\"country\"]) and \"human\" in (properties[\"user_type\"]))"
114
+ ```
115
+
116
+ #### does_not_contain
117
+
118
+ ```ruby
119
+ Mixpanel.where.and.does_not_contain(country: 'Spain', user_type: 'human').to_s
120
+ => "(not \"Spain\" in (properties[\"country\"]) and not \"human\" in (properties[\"user_type\"]))"
121
+ ```
122
+
123
+ #### is_set
124
+
125
+ ```ruby
126
+ Mixpanel.where.and.is_set(['country', 'user_type']).to_s
127
+ => "(defined (properties[\"country\"]) and defined (properties[\"user_type\"]))"
128
+ ```
129
+
130
+ #### is_not_set
131
+
132
+ ```ruby
133
+ Mixpanel.where.and.is_not_set(['country', 'user_type']).to_s
134
+ => "(not defined (properties[\"country\"]) and not defined (properties[\"user_type\"]))"
135
+ ```
136
+
137
+
138
+ ## Actions
139
+ Mixpanel API client has a lot of possible actions, so far these are the supported actions:
140
+
141
+ ### Segementation
142
+ Classic **Mixpanel** segmentation action, where you can specify *event name*, *from/to dates* and *any conditions* you want. Prepare and run as many request in parallel you need
143
+
144
+ ```ruby
145
+ interface = Mixpanel::Interface.new
146
+
147
+ page_visits_query = Mixpanel.where("product" => 'Finances')
148
+ .and.is_set("subproduct")
149
+ page_visits = interface.segmentation('Page visit', { from: Data.parse('2015-01-31'),
150
+ to: Date.today },
151
+ { where: page_visits_query })
152
+
153
+
154
+ login_clicks_query = Mixpanel.where("device_type" => 'mobile')
155
+ login_clicks = interface.segmentation('Login', { from: Data.parse('2015-04-01'),
156
+ to: Date.today },
157
+ { where: login_clicks_query })
158
+
159
+ # Run all the queued queries
160
+ interface.run!
161
+
162
+ # Present your data...
163
+ p page_visits[:data]
164
+ p login_clicks[:data]
165
+ ```
166
+
167
+ ### Segmentation by
168
+ Same as **segmentation** but grouping the output by any property you want to.
169
+
170
+ ```ruby
171
+ interface = Mixpanel::Interface.new
172
+
173
+ page_visits_query = Mixpanel.where("product" => 'Finances')
174
+ .and.is_set("subproduct")
175
+ page_visits = interface.segmentation('Page visit', { from: Data.parse('2015-01-31'),
176
+ to: Date.today },
177
+ { where: page_visits_query,
178
+ on: Mixpanel.on('device_type') })
179
+
180
+ # Run all the queued queries
181
+ interface.run!
182
+
183
+ # Present your data...
184
+ p page_visits[:data]
185
+ ```
186
+
187
+
188
+ ## Your own interface
189
+ Now you master all the above concepts, the best thing you can do is to build your own interface model for extracting your reports:
190
+
191
+ ```ruby
192
+ module Mixpanel
193
+ class LandingPagesInterface < Mixpanel::Interface
194
+
195
+ def initialize
196
+ super()
197
+ end
198
+
199
+ def views(from: nil, to: nil)
200
+ where_context = Mixpanel.where('page_type' => 'landing')
201
+ .and.is_set('device_type')
202
+
203
+ segmentation 'Page view', { from: from, to: to },
204
+ { where: where_context }
205
+ end
206
+
207
+ def views_by_devices(from: nil, to: nil)
208
+ where_context = Mixpanel.where('page_type' => 'landing')
209
+ .and.is_set('device_type')
210
+
211
+ segmentation_interval 'Page view', { from: from, to: to },
212
+ { where: where_context,
213
+ on: Mixpanel.on('device_type') }
214
+ end
215
+
216
+ end
217
+ end
218
+
219
+ # Initialize your interface
220
+ landing_interface = Mixpanel::LandingPagesInterface.new
221
+
222
+ # Prepare all the queries
223
+ landing_last_week_views = landing_interface.views(from: 14.days.ago, to: 7.days.ago)
224
+ landing_this_week_views = landing_interface.views(from: 6.days.ago, to: Date.today)
225
+ landing_last_week_view_by_devices = landing_interface.views_by_devices(from: 14.days.ago, to: 7.days.ago)
226
+
227
+ # Run all the queries
228
+ landing_interface.run!
229
+
230
+ # Retrieve your data!
231
+ p landing_last_week_views[:data]
232
+ p landing_this_week_views[:data]
233
+ p landing_last_week_view_by_devices[:data]
234
+
235
+ ```
236
+
237
+
238
+ ## On top of mixpanel_client Gem
239
+ This ORM is build on top [mixpanel_client](https://github.com/keolo/mixpanel_client#mixpanel-data-api-client) gem.
240
+
241
+ You'll find the oficial mixpanel info [here](https://mixpanel.com/docs/api-documentation/data-export-api#libs-ruby).
242
+
243
+ ### Monkey patching
244
+ On this gem you'll find a ```Mixpanel::Client``` class monkey patch to avoid exceptions raise
245
+ when any of the parallel request fails, i.e all the requests will run until completion and return
246
+ their correspondent HTTP status (error or success) and body as usual.
247
+ See it [here](https://github.com/gguerrero/mixpanel_magic_lamp/blob/master/lib/mixpanel_magic_lamp/client.rb).
248
+
249
+
250
+
251
+ ## Contribution
252
+ If you have cool idea for improving this Gem or any bug fix just open a pull request and
253
+ I'll be glad to have a look and merge it if seems fine.
254
+
255
+
256
+ ## License
257
+
258
+ This project rocks and uses [MIT-LICENSE](https://github.com/gguerrero/mixpanel_magic_lamp/blob/master/MIT-LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,10 @@
1
+ module MixpanelMagicLamp
2
+ class ConfigGenerator < Rails::Generators::Base
3
+ source_root File.expand_path("../templates", __FILE__)
4
+
5
+ desc "Generates the config initializer file for Mixpanel Magic Lamp options"
6
+ def copy_initializer_file
7
+ copy_file "mixpanel_magic_lamp.rb", "config/initializers/mixpanel_magic_lamp.rb"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ MixpanelMagicLamp.configure do |config|
2
+ # Set your API Key/Secret
3
+ # config.api_key = "YOUR MIXPANEL API KEY"
4
+ # config.api_secret = "YOUR MIXPANEL API SECRET"
5
+
6
+ config.parallel = true
7
+ config.interval = 30
8
+ end
@@ -0,0 +1,48 @@
1
+ # MONKEY PATCH!
2
+ # -------------
3
+ #
4
+ # Avoid 'fail' that makes all request to stop running...
5
+ # Original 4.1.1 lib/mixpanel/client.rb source:
6
+ #
7
+ # def prepare_parallel_request
8
+ # request = ::Typhoeus::Request.new(@uri)
9
+ #
10
+ # request.on_complete do |response|
11
+ # if response.success?
12
+ # Utils.to_hash(response.body, @format)
13
+ # elsif response.timed_out?
14
+ # fail TimeoutError
15
+ # elsif response.code == 0
16
+ # # Could not get an http response, something's wrong
17
+ # fail HTTPError, response.curl_error_message
18
+ # else
19
+ # # Received a non-successful http response
20
+ # if response.body && response.body != ''
21
+ # error_message = JSON.parse(response.body)['error']
22
+ # else
23
+ # error_message = response.code.to_s
24
+ # end
25
+ #
26
+ # fail HTTPError, error_message
27
+ # end
28
+ # end
29
+ #
30
+ # request
31
+ # end
32
+ #
33
+ #
34
+ module Mixpanel
35
+
36
+ class Client
37
+ def prepare_parallel_request
38
+ request = ::Typhoeus::Request.new(@uri)
39
+
40
+ request.on_complete do |response|
41
+ Utils.to_hash(response.body, @format) if response.success?
42
+ end
43
+
44
+ request
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,30 @@
1
+ module MixpanelMagicLamp
2
+ class << self
3
+ attr_accessor :configuration
4
+ end
5
+
6
+ def self.configure
7
+ self.configuration ||= Configuration.new
8
+ yield(configuration)
9
+ end
10
+
11
+ class Configuration
12
+ attr_accessor :api_key,
13
+ :api_secret,
14
+ :parallel,
15
+ :interval
16
+
17
+ def initialize
18
+ @parallel = true
19
+ @interval = 30
20
+ end
21
+
22
+ end
23
+
24
+ class ApiKeyMissingError < StandardError
25
+ def initialize
26
+ super "Missing API key and/or secret. Please, configure them."
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,4 @@
1
+ module MixpanelMagicLamp
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,85 @@
1
+ module MixpanelMagicLamp
2
+
3
+ module ClassMethods
4
+ def where(*args)
5
+ MixpanelMagicLamp::InstanceMethods::ExpressionBuilder.new(*args)
6
+ end
7
+
8
+ def on(property)
9
+ "properties[\"#{property}\"]"
10
+ end
11
+ end
12
+
13
+ module InstanceMethods
14
+ class ExpressionBuilder
15
+ attr_reader :expression
16
+
17
+ def initialize(*args)
18
+ @expression = ''
19
+ equals(*args) if args.any?
20
+ end
21
+
22
+ def to_s
23
+ @expression
24
+ end
25
+
26
+ def and
27
+ @expression += ' and ' if @expression.present? and not @expression =~ /(and|or)\s*$/
28
+ self
29
+ end
30
+
31
+ def or
32
+ @expression += ' or ' if @expression.present? and not @expression =~ /(and|or)\s*$/
33
+ self
34
+ end
35
+
36
+ def equals(args = {}, union = 'and')
37
+ @expression += join(args, union, "properties[\":name\"] == \":value\"")
38
+ self
39
+ end
40
+
41
+ def does_not_equal(args = {}, union = 'and')
42
+ @expression += join(args, union, "properties[\":name\"] != \":value\"")
43
+ self
44
+ end
45
+
46
+ def contains(args = {}, union = 'and')
47
+ @expression += join(args, union, "\":value\" in (properties[\":name\"])")
48
+ self
49
+ end
50
+
51
+ def does_not_contain(args = {}, union = 'and')
52
+ @expression += join(args, union, "not \":value\" in (properties[\":name\"])")
53
+ self
54
+ end
55
+
56
+ def is_set(args = [], union = 'and')
57
+ @expression += join(args, union, "defined (properties[\":name\"])")
58
+ self
59
+ end
60
+
61
+ def is_not_set(args = [], union = 'and')
62
+ @expression += join(args, union, "not defined (properties[\":name\"])")
63
+ self
64
+ end
65
+
66
+ private
67
+ def join(args, union, exp)
68
+ args = [args] unless args.is_a? Array or args.is_a? Hash
69
+ built_in = '(' + args.compact.map do |name, values|
70
+ if values.nil?
71
+ exp.gsub(':name', name)
72
+ else
73
+ values = [values] unless values.is_a? Array
74
+ values.map do |value|
75
+ exp.gsub(':name', name.to_s).gsub(':value', value.to_s)
76
+ end
77
+ end
78
+ end.flatten.join(" #{union} ") + ')'
79
+
80
+ built_in == '()' ? '' : built_in
81
+ end
82
+ end
83
+ end
84
+
85
+ end
@@ -0,0 +1,42 @@
1
+ module MixpanelMagicLamp
2
+
3
+ class Formatter
4
+
5
+ DEFAULT = 'values'
6
+
7
+ def initialize(request)
8
+ @response = request.response.handled_response.dup
9
+ end
10
+
11
+ def convert(format: DEFAULT)
12
+ send :"to_#{format}"
13
+ end
14
+
15
+ def to_values
16
+ @response['data']['values']
17
+ end
18
+
19
+ def to_line
20
+ @response['data']
21
+ end
22
+
23
+ def to_pie
24
+ @response['data']['series'] = [ @response['data']['series'].first,
25
+ @response['data']['series'].last ]
26
+ date_for_value = @response['data']['series'].first
27
+
28
+ @response['data']['values'].each do |section, values|
29
+ @response['data']['values'][section] = @response['data']['values'][section][date_for_value]
30
+ end
31
+
32
+ @response['data']
33
+ end
34
+
35
+ def method_missing(method, *args)
36
+ puts "Format '#{method}' not available. Formatting as 'to_#{DEFAULT}' instead."
37
+ send :"to_#{DEFAULT}"
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,61 @@
1
+ require 'mixpanel_client'
2
+
3
+ module MixpanelMagicLamp
4
+
5
+ module InstanceMethods
6
+ class Interface < ::Mixpanel::Client
7
+
8
+ attr_reader :queue
9
+
10
+ def initialize(interval: nil, parallel: nil, unit: 'day', type: 'unique')
11
+ if MixpanelMagicLamp.configuration.api_key.nil? or
12
+ MixpanelMagicLamp.configuration.api_secret.nil?
13
+ raise MixpanelMagicLamp::ApiKeyMissingError
14
+ end
15
+
16
+ @parallel = parallel.nil? ? MixpanelMagicLamp.configuration.parallel : parallel
17
+ @interval = interval.nil? ? MixpanelMagicLamp.configuration.interval : interval
18
+ @from = @interval.days.ago.to_date
19
+ @to = Date.today
20
+ @unit = unit
21
+ @type = type
22
+
23
+ @queue = MixpanelMagicLamp::Queue.new
24
+
25
+ super api_key: MixpanelMagicLamp.configuration.api_key,
26
+ api_secret: MixpanelMagicLamp.configuration.api_secret,
27
+ parallel: @parallel
28
+ end
29
+
30
+ def segmentation(event, dates = {}, options = {})
31
+ dates = { from: dates[:from] || @from, to: dates[:to] || @to }
32
+ @queue.push request('segmentation',
33
+ { event: event,
34
+ type: @type,
35
+ unit: @unit,
36
+ from_date: dates[:from].strftime('%Y-%m-%d'),
37
+ to_date: dates[:to].strftime('%Y-%m-%d') }.merge(options)),
38
+ format: 'line'
39
+ end
40
+
41
+ def segmentation_interval(event, dates = {}, options = {})
42
+ dates = { from: dates[:from].to_date || @from, to: dates[:to].to_date || @to }
43
+
44
+ @queue.push request('segmentation',
45
+ { event: event,
46
+ type: @type,
47
+ interval: (dates[:to] - dates[:from]).to_i + 1,
48
+ from_date: dates[:from].strftime('%Y-%m-%d'),
49
+ to_date: dates[:to].strftime('%Y-%m-%d') }.merge(options)),
50
+ format: 'pie'
51
+ end
52
+
53
+ def run!
54
+ run_parallel_requests
55
+ @queue.process!
56
+ end
57
+
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,36 @@
1
+ require 'json'
2
+
3
+ module MixpanelMagicLamp
4
+
5
+ class Queue < Array
6
+
7
+ def push(request, opts = {})
8
+ item = {
9
+ request: request,
10
+ format: opts.delete(:format),
11
+ status: nil,
12
+ response: nil,
13
+ data: nil }
14
+
15
+ self << item and return item
16
+ end
17
+
18
+ def process!
19
+ self.each do |request|
20
+ next unless request[:status].nil?
21
+ request[:status] = request[:request].response.code
22
+
23
+ if request[:request].response.success?
24
+ formatter = MixpanelMagicLamp::Formatter.new(request[:request])
25
+ request[:data] = formatter.convert format: request[:format]
26
+ else
27
+ request[:response] = JSON.parse(request[:request].response.body)
28
+ end
29
+ end
30
+
31
+ self
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,3 @@
1
+ module MixpanelMagicLamp
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,14 @@
1
+ require 'mixpanel_client'
2
+ require 'mixpanel_magic_lamp/configuration'
3
+ require 'mixpanel_magic_lamp/engine' if defined? Rails
4
+ require 'mixpanel_magic_lamp/client'
5
+ require 'mixpanel_magic_lamp/expression_builder'
6
+ require 'mixpanel_magic_lamp/formatter'
7
+ require 'mixpanel_magic_lamp/queue'
8
+ require 'mixpanel_magic_lamp/interface'
9
+
10
+ # Include and extend the magic lamp
11
+ Mixpanel.extend MixpanelMagicLamp::ClassMethods
12
+ module Mixpanel
13
+ include MixpanelMagicLamp::InstanceMethods
14
+ end
@@ -0,0 +1,19 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "mixpanel_magic_lamp/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |s|
8
+ s.name = "mixpanel_magic_lamp"
9
+ s.version = MixpanelMagicLamp::VERSION
10
+ s.authors = ["Guillermo Guerrero"]
11
+ s.email = ["g.guerrero.bus@gmail.com"]
12
+ s.homepage = "https://github.com/gguerrero/mixpanel_client_interface"
13
+ s.summary = "Mixpanel client ORM!"
14
+ s.description = "Mixpanel client ORM for easy querying and reporting data."
15
+ s.license = "MIT"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.add_dependency "mixpanel_client", ">= 4.1.1"
19
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mixpanel_magic_lamp
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Guillermo Guerrero
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mixpanel_client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.1.1
27
+ description: Mixpanel client ORM for easy querying and reporting data.
28
+ email:
29
+ - g.guerrero.bus@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - CHANGELOG.md
36
+ - Gemfile
37
+ - MIT-LICENSE
38
+ - README.md
39
+ - Rakefile
40
+ - lib/generators/mixpanel_magic_lamp/config_generator.rb
41
+ - lib/generators/mixpanel_magic_lamp/templates/mixpanel_magic_lamp.rb
42
+ - lib/mixpanel_magic_lamp.rb
43
+ - lib/mixpanel_magic_lamp/client.rb
44
+ - lib/mixpanel_magic_lamp/configuration.rb
45
+ - lib/mixpanel_magic_lamp/engine.rb
46
+ - lib/mixpanel_magic_lamp/expression_builder.rb
47
+ - lib/mixpanel_magic_lamp/formatter.rb
48
+ - lib/mixpanel_magic_lamp/interface.rb
49
+ - lib/mixpanel_magic_lamp/queue.rb
50
+ - lib/mixpanel_magic_lamp/version.rb
51
+ - mixpanel_magic_lamp.gemspec
52
+ homepage: https://github.com/gguerrero/mixpanel_client_interface
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.4.8
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: Mixpanel client ORM!
76
+ test_files: []