octocore-cassandra 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES.md +12 -0
- data/CONTRIBUTING +0 -0
- data/Gemfile +10 -0
- data/LICENSE +202 -0
- data/MAINTAINERS +0 -0
- data/NOTICE +8 -0
- data/README.md +69 -0
- data/Rakefile +142 -0
- data/bin/fakestream-cassandra +258 -0
- data/bin/octocore-admin-cassandra +54 -0
- data/lib/octocore-cassandra.rb +152 -0
- data/lib/octocore-cassandra/baseline.rb +131 -0
- data/lib/octocore-cassandra/callbacks.rb +117 -0
- data/lib/octocore-cassandra/config.rb +39 -0
- data/lib/octocore-cassandra/config/config.yml +1 -0
- data/lib/octocore-cassandra/config/search/index/user.yml +42 -0
- data/lib/octocore-cassandra/counter.rb +265 -0
- data/lib/octocore-cassandra/counter/helpers.rb +168 -0
- data/lib/octocore-cassandra/email.rb +63 -0
- data/lib/octocore-cassandra/featureflag.rb +79 -0
- data/lib/octocore-cassandra/helpers.rb +6 -0
- data/lib/octocore-cassandra/helpers/api_consumer_helper.rb +51 -0
- data/lib/octocore-cassandra/helpers/api_helper.rb +65 -0
- data/lib/octocore-cassandra/helpers/api_logger.rb +14 -0
- data/lib/octocore-cassandra/helpers/client_helper.rb +104 -0
- data/lib/octocore-cassandra/helpers/kong_helper.rb +164 -0
- data/lib/octocore-cassandra/helpers/sinatra_helper.rb +22 -0
- data/lib/octocore-cassandra/kafka_bridge.rb +60 -0
- data/lib/octocore-cassandra/kldivergence.rb +14 -0
- data/lib/octocore-cassandra/mailer.rb +1 -0
- data/lib/octocore-cassandra/mailer/subscriber_mailer.rb +30 -0
- data/lib/octocore-cassandra/message_parser.rb +114 -0
- data/lib/octocore-cassandra/models.rb +274 -0
- data/lib/octocore-cassandra/models/contactus.rb +42 -0
- data/lib/octocore-cassandra/models/enterprise.rb +76 -0
- data/lib/octocore-cassandra/models/enterprise/adapter_details.rb +18 -0
- data/lib/octocore-cassandra/models/enterprise/api_event.rb +14 -0
- data/lib/octocore-cassandra/models/enterprise/api_hit.rb +20 -0
- data/lib/octocore-cassandra/models/enterprise/api_key.rb +11 -0
- data/lib/octocore-cassandra/models/enterprise/api_track.rb +13 -0
- data/lib/octocore-cassandra/models/enterprise/app_init.rb +13 -0
- data/lib/octocore-cassandra/models/enterprise/app_login.rb +12 -0
- data/lib/octocore-cassandra/models/enterprise/app_logout.rb +12 -0
- data/lib/octocore-cassandra/models/enterprise/authorization.rb +67 -0
- data/lib/octocore-cassandra/models/enterprise/category.rb +14 -0
- data/lib/octocore-cassandra/models/enterprise/category_baseline.rb +19 -0
- data/lib/octocore-cassandra/models/enterprise/category_hit.rb +26 -0
- data/lib/octocore-cassandra/models/enterprise/category_trend.rb +19 -0
- data/lib/octocore-cassandra/models/enterprise/conversions.rb +69 -0
- data/lib/octocore-cassandra/models/enterprise/ctr.rb +54 -0
- data/lib/octocore-cassandra/models/enterprise/dimension_choice.rb +21 -0
- data/lib/octocore-cassandra/models/enterprise/engagement_time.rb +43 -0
- data/lib/octocore-cassandra/models/enterprise/funnel_data.rb +20 -0
- data/lib/octocore-cassandra/models/enterprise/funnel_tracker.rb +19 -0
- data/lib/octocore-cassandra/models/enterprise/funnels.rb +129 -0
- data/lib/octocore-cassandra/models/enterprise/gcm.rb +21 -0
- data/lib/octocore-cassandra/models/enterprise/newsfeed_hit.rb +52 -0
- data/lib/octocore-cassandra/models/enterprise/notification_hit.rb +42 -0
- data/lib/octocore-cassandra/models/enterprise/page.rb +15 -0
- data/lib/octocore-cassandra/models/enterprise/page_view.rb +14 -0
- data/lib/octocore-cassandra/models/enterprise/pageload_time.rb +43 -0
- data/lib/octocore-cassandra/models/enterprise/product.rb +22 -0
- data/lib/octocore-cassandra/models/enterprise/product_baseline.rb +20 -0
- data/lib/octocore-cassandra/models/enterprise/product_hit.rb +26 -0
- data/lib/octocore-cassandra/models/enterprise/product_page_view.rb +13 -0
- data/lib/octocore-cassandra/models/enterprise/product_trend.rb +18 -0
- data/lib/octocore-cassandra/models/enterprise/push_key.rb +15 -0
- data/lib/octocore-cassandra/models/enterprise/rules.rb +45 -0
- data/lib/octocore-cassandra/models/enterprise/segment.rb +65 -0
- data/lib/octocore-cassandra/models/enterprise/segment_data.rb +22 -0
- data/lib/octocore-cassandra/models/enterprise/tag.rb +14 -0
- data/lib/octocore-cassandra/models/enterprise/tag_baseline.rb +19 -0
- data/lib/octocore-cassandra/models/enterprise/tag_hit.rb +26 -0
- data/lib/octocore-cassandra/models/enterprise/tag_trend.rb +19 -0
- data/lib/octocore-cassandra/models/enterprise/template.rb +18 -0
- data/lib/octocore-cassandra/models/plans.rb +17 -0
- data/lib/octocore-cassandra/models/subscribe.rb +13 -0
- data/lib/octocore-cassandra/models/user.rb +15 -0
- data/lib/octocore-cassandra/models/user/push_token.rb +15 -0
- data/lib/octocore-cassandra/models/user/user_browser_details.rb +16 -0
- data/lib/octocore-cassandra/models/user/user_location_history.rb +15 -0
- data/lib/octocore-cassandra/models/user/user_persona.rb +101 -0
- data/lib/octocore-cassandra/models/user/user_phone_details.rb +17 -0
- data/lib/octocore-cassandra/models/user/user_profile.rb +20 -0
- data/lib/octocore-cassandra/models/user/user_timeline.rb +111 -0
- data/lib/octocore-cassandra/record.rb +20 -0
- data/lib/octocore-cassandra/schedeuleable.rb +20 -0
- data/lib/octocore-cassandra/scheduler.rb +72 -0
- data/lib/octocore-cassandra/search.rb +5 -0
- data/lib/octocore-cassandra/search/client.rb +33 -0
- data/lib/octocore-cassandra/search/indexer.rb +0 -0
- data/lib/octocore-cassandra/search/searchable.rb +18 -0
- data/lib/octocore-cassandra/search/setup.rb +71 -0
- data/lib/octocore-cassandra/segment.rb +287 -0
- data/lib/octocore-cassandra/stats.rb +33 -0
- data/lib/octocore-cassandra/trendable.rb +88 -0
- data/lib/octocore-cassandra/trends.rb +158 -0
- data/lib/octocore-cassandra/utils.rb +90 -0
- data/lib/octocore-cassandra/version.rb +4 -0
- data/spec/lib/stats_spec.rb +20 -0
- data/spec/spec_helper.rb +103 -0
- metadata +490 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'statsd-ruby'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
|
5
|
+
# Instrumentation and Statistical module
|
6
|
+
module Stats
|
7
|
+
|
8
|
+
# Instrument a block identified by its name
|
9
|
+
# @param [Symbol] name The name by which this would be identified
|
10
|
+
def instrument(name)
|
11
|
+
if stats
|
12
|
+
stats.time(name.to_s, &Proc.new)
|
13
|
+
else
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get stats instance
|
19
|
+
def stats
|
20
|
+
if statd_config
|
21
|
+
@statsd = Statsd.new(*statd_config.values) unless @statsd
|
22
|
+
@statsd
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Get stats config from Octo
|
29
|
+
def statd_config
|
30
|
+
Octo.get_config :statsd
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'octocore-cassandra/kldivergence'
|
2
|
+
require 'octocore-cassandra/counter'
|
3
|
+
|
4
|
+
module Octo
|
5
|
+
|
6
|
+
module Trendable
|
7
|
+
|
8
|
+
include Octo::KLDivergence
|
9
|
+
|
10
|
+
# Define the columns necessary for a trendable model
|
11
|
+
def trendables
|
12
|
+
column :divergence, :float
|
13
|
+
column :obp, :float
|
14
|
+
end
|
15
|
+
|
16
|
+
# Define the baseline class for this trend
|
17
|
+
def baseline(klass)
|
18
|
+
@baseline_klass = klass
|
19
|
+
end
|
20
|
+
|
21
|
+
# Define the class for trends
|
22
|
+
def trends_class(klass)
|
23
|
+
@trends_klass = klass
|
24
|
+
end
|
25
|
+
|
26
|
+
# Aggregates and attempts to store it into the database. This would only
|
27
|
+
# work if the class that extends Octo::Counter includes from
|
28
|
+
# Cequel::Record
|
29
|
+
def aggregate!(ts = Time.now.floor)
|
30
|
+
unless self.ancestors.include?Cequel::Record
|
31
|
+
raise NoMethodError, 'aggregate! not defined for this counter'
|
32
|
+
end
|
33
|
+
|
34
|
+
aggr = aggregate(ts)
|
35
|
+
sum = aggregate_sum(aggr)
|
36
|
+
aggr.each do |_ts, counterVals|
|
37
|
+
counterVals.each do |obj, count|
|
38
|
+
counter = self.new
|
39
|
+
counter.enterprise_id = obj.enterprise.id
|
40
|
+
counter.uid = obj.unique_id
|
41
|
+
counter.count = count
|
42
|
+
counter.type = Octo::Counter::TYPE_MINUTE
|
43
|
+
counter.ts = _ts
|
44
|
+
totalCount = sum[_ts][obj.enterprise_id.to_s].to_f
|
45
|
+
counter.obp = (count * 1.0)/totalCount
|
46
|
+
|
47
|
+
baseline_value = get_baseline_value(:TYPE_MINUTE, obj)
|
48
|
+
counter.divergence = kl_divergence(counter.obp,
|
49
|
+
baseline_value)
|
50
|
+
counter.save!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
call_completion_hook(Octo::Counter::TYPE_MINUTE, ts)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Aggregates to find the sum of all counters for an enterprise
|
59
|
+
# at a time
|
60
|
+
# @param [Hash] aggr The aggregated hash
|
61
|
+
# @return [Hash] The summed up hash
|
62
|
+
def aggregate_sum(aggr)
|
63
|
+
sum = {}
|
64
|
+
aggr.each do |ts, counterVals|
|
65
|
+
sum[ts] = {} unless sum.has_key?ts
|
66
|
+
counterVals.each do |obj, count|
|
67
|
+
if obj.respond_to?(:enterprise_id)
|
68
|
+
eid = obj.public_send(:enterprise_id).to_s
|
69
|
+
sum[ts][eid] = sum[ts].fetch(eid, 0) + count
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
sum
|
74
|
+
end
|
75
|
+
|
76
|
+
# Get the baseline value for an object.
|
77
|
+
# @param [Fixnum] baseline_type The type of baseline to fetch
|
78
|
+
# @param [Object] object The object for which baseline is to
|
79
|
+
# be fetched
|
80
|
+
def get_baseline_value(baseline_type, object)
|
81
|
+
clazz = @baseline_klass.constantize
|
82
|
+
clazz.public_send(:get_baseline_value, baseline_type, object)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'octocore-cassandra/baseline'
|
2
|
+
require 'octocore-cassandra/counter'
|
3
|
+
|
4
|
+
module Octo
|
5
|
+
|
6
|
+
module Trends
|
7
|
+
|
8
|
+
include Octo::Counter::Helper
|
9
|
+
|
10
|
+
DEFAULT_COUNT = 10
|
11
|
+
|
12
|
+
# Define the columns needed for Trends
|
13
|
+
def trendable
|
14
|
+
key :type, :int
|
15
|
+
key :ts, :timestamp
|
16
|
+
key :rank, :int
|
17
|
+
|
18
|
+
column :score, :float
|
19
|
+
column :uid, :text
|
20
|
+
|
21
|
+
generate_aggregators { |ts, method|
|
22
|
+
trendtype = method_names_type_counter(method)
|
23
|
+
aggregate_and_create trendtype, ts
|
24
|
+
}
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
# Aggregates and creates trends for all the enterprises for a specific
|
29
|
+
# trend type at a specific timestamp
|
30
|
+
# @param [Fixnum] oftype The type of trend to be calculated
|
31
|
+
# @param [Time] ts The time at which trend needs to be calculated
|
32
|
+
def aggregate_and_create(oftype, ts = Time.now.floor)
|
33
|
+
Octo::Enterprise.each do |enterprise|
|
34
|
+
calculate(enterprise.id, oftype, ts)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Override the aggregate! defined in counter class as the calculations
|
39
|
+
# for trending are a little different
|
40
|
+
def aggregate!(ts = Time.now.floor)
|
41
|
+
aggregate_and_create(Octo::Counter::TYPE_MINUTE, ts)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Performs the actual trend calculation
|
45
|
+
# @param [String] enterprise_id The enterprise ID for whom trend needs to be found
|
46
|
+
# @param [Fixnum] trend_type The trend type to be calculates
|
47
|
+
# @param [Time] ts The Timestamp at which trend needs to be calculated.
|
48
|
+
def calculate(enterprise_id, trend_type, ts = Time.now.floor)
|
49
|
+
args = {
|
50
|
+
enterprise_id: enterprise_id,
|
51
|
+
ts: ts,
|
52
|
+
type: trend_type
|
53
|
+
}
|
54
|
+
|
55
|
+
klass = @trend_for.constantize
|
56
|
+
hitsResult = klass.public_send(:where, args)
|
57
|
+
trends = hitsResult.map { |h| counter2trend(h) }
|
58
|
+
|
59
|
+
# group trends as per the time of their happening and rank them on their
|
60
|
+
# score
|
61
|
+
grouped_trends = trends.group_by { |x| x.ts }
|
62
|
+
grouped_trends.each do |_ts, trendlist|
|
63
|
+
sorted_trendlist = trendlist.sort_by { |x| x.score }
|
64
|
+
sorted_trendlist.each_with_index do |trend, index|
|
65
|
+
trend.rank = index
|
66
|
+
trend.type = trend_type
|
67
|
+
trend.save!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Define the class for which trends shall be found
|
73
|
+
def trend_for(klass)
|
74
|
+
unless klass.constantize.ancestors.include?Cequel::Record
|
75
|
+
raise ArgumentError, "Class #{ klass } does not represent a DB Model"
|
76
|
+
else
|
77
|
+
@trend_for = klass
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Define the class which would be returned while fetching trending objects
|
82
|
+
def trend_class(klass)
|
83
|
+
@trend_class = klass
|
84
|
+
end
|
85
|
+
|
86
|
+
# Gets the trend of a type at a time
|
87
|
+
# @param [String] enterprise_id The ID of enterprise for whom trend to fetch
|
88
|
+
# @param [Fixnum] type The type of trend to fetch
|
89
|
+
# @param [Hash] opts The options to be provided for finding trends
|
90
|
+
def get_trending(enterprise_id, type, opts={})
|
91
|
+
ts = opts.fetch(:ts, Time.now.floor)
|
92
|
+
args = {
|
93
|
+
enterprise_id: enterprise_id,
|
94
|
+
ts: opts.fetch(:ts, Time.now.floor),
|
95
|
+
type: type
|
96
|
+
}
|
97
|
+
res = where(args).limit(opts.fetch(:limit, DEFAULT_COUNT))
|
98
|
+
enterprise = Octo::Enterprise.find_by_id(enterprise_id)
|
99
|
+
if res.count == 0 and enterprise.fakedata?
|
100
|
+
Octo.logger.info 'Beginning to fake data'
|
101
|
+
res = []
|
102
|
+
if ts.class == Range
|
103
|
+
ts_begin = ts.begin
|
104
|
+
ts_end = ts.end
|
105
|
+
ts_begin.to(ts_end, 1.day).each do |_ts|
|
106
|
+
3.times do |rank|
|
107
|
+
items = @trend_class.constantize.send(:where, {enterprise_id: enterprise_id}).first(10)
|
108
|
+
if items.count > 0
|
109
|
+
uid = items.shuffle.pop.unique_id
|
110
|
+
_args = args.merge( ts: _ts, rank: rank, score: rank+1, uid: uid )
|
111
|
+
res << self.new(_args).save!
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
elsif ts.class == Time
|
116
|
+
3.times do |rank|
|
117
|
+
uid = 0
|
118
|
+
items = @trend_class.constantize.send(:where, {enterprise_id: enterprise_id}).first(10)
|
119
|
+
if items.count > 0
|
120
|
+
uid = items.shuffle.pop.unique_id
|
121
|
+
_args = args.merge( rank: rank, score: rank+1, uid: uid )
|
122
|
+
res << self.new(_args).save!
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
res.map do |r|
|
128
|
+
clazz = @trend_class.constantize
|
129
|
+
clazz.public_send(:recreate_from, r)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
# Converts a couunter into a trend
|
136
|
+
# @param [Object] counter A counter object. This object must belong
|
137
|
+
# to one of the counter types defined in models.
|
138
|
+
# @return [Object] Returns a trend instance corresponding to the counter
|
139
|
+
# instance
|
140
|
+
def counter2trend(counter)
|
141
|
+
self.new({
|
142
|
+
enterprise: counter.enterprise,
|
143
|
+
score: score(counter.divergence),
|
144
|
+
uid: counter.uid,
|
145
|
+
ts: counter.ts
|
146
|
+
})
|
147
|
+
end
|
148
|
+
|
149
|
+
# For now, just make sure divergence is absolute. This is responsible to
|
150
|
+
# score a counter on the basis of its divergence
|
151
|
+
# @param [Float] divergence The divergence value
|
152
|
+
# @return [Float] The score
|
153
|
+
def score(divergence)
|
154
|
+
return 0 if divergence.nil?
|
155
|
+
divergence.abs
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
|
5
|
+
module Utils
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# Serialize one record before adding it to the cache. Creates a ruby byte
|
10
|
+
# stream
|
11
|
+
# @param [Object] record Any object to be serialized
|
12
|
+
def serialize(record)
|
13
|
+
Marshal::dump(record).to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
# Deserialize a data.
|
17
|
+
# @param [String] data A string containing Marshal dump of the object
|
18
|
+
def deserialize(data)
|
19
|
+
Marshal::load(data)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ::Time
|
26
|
+
|
27
|
+
# Find floor time
|
28
|
+
# @param [Fixnum] height The minutes of height for floor. Defaults to 1
|
29
|
+
def floor(height = 1)
|
30
|
+
if height < 1
|
31
|
+
height = 1
|
32
|
+
end
|
33
|
+
sec = height.to_i * 60
|
34
|
+
Time.at((self.to_i / sec).round * sec)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Find ceil time
|
38
|
+
# @param [Fixnum] height The minutes of height for ceil. Defaults to 1
|
39
|
+
def ceil(height = 1)
|
40
|
+
if height < 1
|
41
|
+
height = 1
|
42
|
+
end
|
43
|
+
sec = height.to_i * 60
|
44
|
+
Time.at((1 + (self.to_i / sec)).round * sec)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Finds the steps between two time.
|
48
|
+
# @param [Time] to The end time
|
49
|
+
# @param [Time] step The step time. Defaults to 15.minute
|
50
|
+
# @return [Array<Time>] An array containint times
|
51
|
+
def to(to, step = 15.minutes)
|
52
|
+
[self].tap { |array| array << array.last + step while array.last < to }
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class ::String
|
58
|
+
|
59
|
+
# Create a custom method to convert strings to Slugs
|
60
|
+
def to_slug
|
61
|
+
#strip the string
|
62
|
+
ret = self.strip
|
63
|
+
|
64
|
+
#blow away apostrophes
|
65
|
+
ret.gsub!(/['`]/,'')
|
66
|
+
|
67
|
+
# @ --> at, and & --> and
|
68
|
+
ret.gsub!(/\s*@\s*/, ' at ')
|
69
|
+
ret.gsub!(/\s*&\s*/, ' and ')
|
70
|
+
|
71
|
+
#replace all non alphanumeric, underscore or periods with underscore
|
72
|
+
ret.gsub!(/\s*[^A-Za-z0-9\.\-]\s*/, '_')
|
73
|
+
|
74
|
+
#convert double underscores to single
|
75
|
+
ret.gsub!(/_+/,'_')
|
76
|
+
|
77
|
+
#strip off leading/trailing underscore
|
78
|
+
ret.gsub!(/\A[_\.]+|[_\.]+\z/,'')
|
79
|
+
|
80
|
+
ret
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
class ::Hash
|
86
|
+
def deep_merge(second)
|
87
|
+
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
88
|
+
self.merge(second.to_h, &merger)
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe Octo::Stats do
|
4
|
+
|
5
|
+
describe '#instrument' do
|
6
|
+
let(:dummy_class) { Class.new { extend Octo::Stats } }
|
7
|
+
|
8
|
+
it 'yields the given block' do
|
9
|
+
block = Proc.new { puts 'hello world' }
|
10
|
+
name = :hello_world
|
11
|
+
|
12
|
+
expect(dummy_class).to receive(:instrument).
|
13
|
+
with(name, &block).
|
14
|
+
and_yield(&block)
|
15
|
+
|
16
|
+
dummy_class.instrument(name, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
Bundler.setup
|
5
|
+
|
6
|
+
require 'octocore'
|
7
|
+
|
8
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
9
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
10
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
11
|
+
# this file to always be loaded, without a need to explicitly require it in any
|
12
|
+
# files.
|
13
|
+
#
|
14
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
15
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
16
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
17
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
18
|
+
# a separate helper file that requires the additional dependencies and performs
|
19
|
+
# the additional setup, and require it from the spec files that actually need
|
20
|
+
# it.
|
21
|
+
#
|
22
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
23
|
+
# users commonly want.
|
24
|
+
#
|
25
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
26
|
+
RSpec.configure do |config|
|
27
|
+
# rspec-expectations config goes here. You can use an alternate
|
28
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
29
|
+
# assertions if you prefer.
|
30
|
+
config.expect_with :rspec do |expectations|
|
31
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
32
|
+
# and `failure_message` of custom matchers include text for helper methods
|
33
|
+
# defined using `chain`, e.g.:
|
34
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
35
|
+
# # => "be bigger than 2 and smaller than 4"
|
36
|
+
# ...rather than:
|
37
|
+
# # => "be bigger than 2"
|
38
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
39
|
+
end
|
40
|
+
|
41
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
42
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
43
|
+
config.mock_with :rspec do |mocks|
|
44
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
45
|
+
# a real object. This is generally recommended, and will default to
|
46
|
+
# `true` in RSpec 4.
|
47
|
+
mocks.verify_partial_doubles = true
|
48
|
+
end
|
49
|
+
|
50
|
+
# The settings below are suggested to provide a good initial experience
|
51
|
+
# with RSpec, but feel free to customize to your heart's content.
|
52
|
+
=begin
|
53
|
+
# These two settings work together to allow you to limit a spec run
|
54
|
+
# to individual examples or groups you care about by tagging them with
|
55
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
56
|
+
# get run.
|
57
|
+
config.filter_run :focus
|
58
|
+
config.run_all_when_everything_filtered = true
|
59
|
+
|
60
|
+
# Allows RSpec to persist some state between runs in order to support
|
61
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
62
|
+
# you configure your source control system to ignore this file.
|
63
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
64
|
+
|
65
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
66
|
+
# recommended. For more details, see:
|
67
|
+
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
|
68
|
+
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
69
|
+
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
|
70
|
+
config.disable_monkey_patching!
|
71
|
+
|
72
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
73
|
+
# be too noisy due to issues in dependencies.
|
74
|
+
config.warnings = true
|
75
|
+
|
76
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
77
|
+
# file, and it's useful to allow more verbose output when running an
|
78
|
+
# individual spec file.
|
79
|
+
if config.files_to_run.one?
|
80
|
+
# Use the documentation formatter for detailed output,
|
81
|
+
# unless a formatter has already been configured
|
82
|
+
# (e.g. via a command-line flag).
|
83
|
+
config.default_formatter = 'doc'
|
84
|
+
end
|
85
|
+
|
86
|
+
# Print the 10 slowest examples and example groups at the
|
87
|
+
# end of the spec run, to help surface which specs are running
|
88
|
+
# particularly slow.
|
89
|
+
config.profile_examples = 10
|
90
|
+
|
91
|
+
# Run specs in random order to surface order dependencies. If you find an
|
92
|
+
# order dependency and want to debug it, you can fix the order by providing
|
93
|
+
# the seed, which is printed after each run.
|
94
|
+
# --seed 1234
|
95
|
+
config.order = :random
|
96
|
+
|
97
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
98
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
99
|
+
# test failures related to randomization by passing the same `--seed` value
|
100
|
+
# as the one that triggered the failure.
|
101
|
+
Kernel.srand config.seed
|
102
|
+
=end
|
103
|
+
end
|