Class: Vanity::Adapters::MongodbAdapter

Inherits:
AbstractAdapter show all
Defined in:
lib/vanity/adapters/mongodb_adapter.rb

Overview

MongoDB adapter.

Since:

  • 1.4.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ MongodbAdapter

Returns a new instance of MongodbAdapter

Since:

  • 1.4.0



20
21
22
23
24
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 20

def initialize(options)
  @options = options.clone
  @options[:database] ||= (@options[:path] && @options[:path].split("/")[1]) || "vanity"
  connect!
end

Instance Attribute Details

#mongoObject (readonly)

Since:

  • 1.4.0



18
19
20
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 18

def mongo
  @mongo
end

Instance Method Details

#ab_add_conversion(experiment, alternative, identity, count = 1, implicit = false) ⇒ Object

Since:

  • 1.4.0



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 216

def ab_add_conversion(experiment, alternative, identity, count = 1, implicit = false)
  if implicit
    @participants.find(:experiment=>experiment, :identity=>identity).find_one_and_replace(
      {
        "$push"=>{ :seen=>alternative }
      },
      :upsert=>true
    )
  else
    participating = @participants.find(:experiment=>experiment, :identity=>identity, :seen=>alternative).limit(1).first
  end

  if implicit || participating
    @participants.find(:experiment=>experiment, :identity=>identity).find_one_and_replace(
      {
        "$push"=>{ :converted=>alternative }
      },
      :upsert=>true
    )
  end

  @experiments.find(:_id=>experiment).find_one_and_replace(
    {
      "$inc"=>{ "conversions.#{alternative}"=>count }
    },
    :upsert=>true
  )
end

#ab_add_participant(experiment, alternative, identity) ⇒ Object

Since:

  • 1.4.0



193
194
195
196
197
198
199
200
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 193

def ab_add_participant(experiment, alternative, identity)
  @participants.find(:experiment=>experiment, :identity=>identity).find_one_and_replace(
    {
      "$push"=>{ :seen=>alternative }
    },
    :upsert=>true
  )
end

#ab_assigned(experiment, identity) ⇒ Object

Returns the participant's seen alternative in this experiment, if it exists

Since:

  • 1.4.0



211
212
213
214
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 211

def ab_assigned(experiment, identity)
  participant = @participants.find(:experiment=>experiment, :identity=>identity).limit(1).projection(:seen=>1).first
  participant && participant["seen"].first
end

#ab_counts(experiment, alternative) ⇒ Object

Since:

  • 1.4.0



162
163
164
165
166
167
168
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 162

def ab_counts(experiment, alternative)
  record = @experiments.find(:_id=>experiment ).limit(1).projection(:conversions=>1).first
  conversions = record && record["conversions"]
  { :participants => @participants.find({ :experiment=>experiment, :seen=>alternative }).count,
    :converted    => @participants.find({ :experiment=>experiment, :converted=>alternative }).count,
    :conversions  => conversions && conversions[alternative.to_s] || 0 }
end

#ab_get_outcome(experiment) ⇒ Object

Since:

  • 1.4.0



245
246
247
248
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 245

def ab_get_outcome(experiment)
  experiment = @experiments.find(:_id=>experiment).limit(1).projection(:outcome=>1).first
  experiment && experiment["outcome"]
end

#ab_not_showing(experiment, identity) ⇒ Object

Since:

  • 1.4.0



184
185
186
187
188
189
190
191
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 184

def ab_not_showing(experiment, identity)
  @participants.find(:experiment=>experiment, :identity=>identity).find_one_and_replace(
    {
      "$unset"=> { :show => "" }
    },
    :upsert=>true
  )
end

#ab_seen(experiment, identity, alternative_or_id) ⇒ Object

Determines if a participant already has seen this alternative in this experiment.

Since:

  • 1.4.0



203
204
205
206
207
208
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 203

def ab_seen(experiment, identity, alternative_or_id)
  with_ab_seen_deprecation(experiment, identity, alternative_or_id) do |expt, ident, alt_id|
    participant = @participants.find(:experiment=>expt, :identity=>ident).limit(1).projection(:seen=>1).first
    participant && participant["seen"].first == alt_id
  end
end

#ab_set_outcome(experiment, alternative = 0) ⇒ Object

Since:

  • 1.4.0



250
251
252
253
254
255
256
257
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 250

def ab_set_outcome(experiment, alternative = 0)
  @experiments.find(:_id=>experiment).find_one_and_replace(
    {
      "$set"=>{ :outcome=>alternative }
    },
    :upsert=>true
  )
end

#ab_show(experiment, identity, alternative) ⇒ Object

Since:

  • 1.4.0



170
171
172
173
174
175
176
177
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 170

def ab_show(experiment, identity, alternative)
  @participants.find(:experiment=>experiment, :identity=>identity).find_one_and_replace(
    {
      "$set"=>{ :show=>alternative }
    },
    :upsert=>true
  )
end

#ab_showing(experiment, identity) ⇒ Object

Since:

  • 1.4.0



179
180
181
182
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 179

def ab_showing(experiment, identity)
  participant = @participants.find(:experiment=>experiment, :identity=>identity).limit(1).projection(:show=>1).first
  participant && participant["show"]
end

#active?Boolean

Returns:

  • (Boolean)

Since:

  • 1.4.0



26
27
28
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 26

def active?
  !!@mongo
end

#connect!Object

Since:

  • 1.4.0



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 41

def connect!
  Mongo::Logger.logger = Vanity.logger
  setup_connection(@options)

  @metrics = @mongo["vanity.metrics"]
  @metrics.create unless @mongo.database.collection_names.include?("vanity.metrics")
  @experiments = @mongo["vanity.experiments"]
  @experiments.create unless @mongo.database.collection_names.include?("vanity.experiments")
  @participants = @mongo["vanity.participants"]
  @participants.create unless @mongo.database.collection_names.include?("vanity.participants")
  @participants.indexes.create_many(
    { :key => { :experiment => 1, :identity => 1 }, :unique=>true },
    { :key => { :experiment => 1, :seen => 1 } },
    { :key => { :experiment => 1, :converted => 1 } }
  )

  @mongo
end

#destroy_experiment(experiment) ⇒ Object

Since:

  • 1.4.0



259
260
261
262
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 259

def destroy_experiment(experiment)
  @experiments.find(:_id=>experiment).delete_one
  @participants.find(:experiment=>experiment).delete_many
end

#destroy_metric(metric) ⇒ Object

Since:

  • 1.4.0



99
100
101
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 99

def destroy_metric(metric)
  @metrics.find(:_id=>metric).delete_one
end

#disconnect!Object

Since:

  • 1.4.0



30
31
32
33
34
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 30

def disconnect!
  @mongo.close rescue nil if @mongo
  @metrics, @experiments = nil
  @mongo = nil
end

#experiment_persisted?(experiment) ⇒ Boolean

– Experiments –

Returns:

  • (Boolean)

Since:

  • 1.4.0



106
107
108
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 106

def experiment_persisted?(experiment)
  !!@experiments.find(:_id=>experiment).limit(1).first
end

#flushdbObject

Since:

  • 1.4.0



65
66
67
68
69
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 65

def flushdb
  @metrics.drop
  @experiments.drop
  @participants.drop
end

#get_experiment_completed_at(experiment) ⇒ Object

Since:

  • 1.4.0



135
136
137
138
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 135

def get_experiment_completed_at(experiment)
  record = @experiments.find(:_id=>experiment).limit(1).projection(:completed_at=>1).first
  record && record["completed_at"]
end

#get_experiment_created_at(experiment) ⇒ Object

Since:

  • 1.4.0



120
121
122
123
124
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 120

def get_experiment_created_at(experiment)
  record = @experiments.find(:_id=>experiment).limit(1).projection(:created_at=>1).first
  record && record["created_at"]
  #Returns nil if either the record or the field doesn't exist
end

#get_metric_last_update_at(metric) ⇒ Object

– Metrics –

Since:

  • 1.4.0



74
75
76
77
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 74

def get_metric_last_update_at(metric)
  record = @metrics.find(:_id=>metric).limit(1).first
  record && record["last_update_at"]
end

#is_experiment_completed?(experiment) ⇒ Boolean

Returns:

  • (Boolean)

Since:

  • 1.4.0



140
141
142
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 140

def is_experiment_completed?(experiment)
  !!@experiments.find(:_id=>experiment, :completed_at=>{ "$exists"=>true }).limit(1).first
end

#is_experiment_enabled?(experiment) ⇒ Boolean

Returns:

  • (Boolean)

Since:

  • 1.4.0



153
154
155
156
157
158
159
160
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 153

def is_experiment_enabled?(experiment)
  record = @experiments.find(:_id=>experiment).limit(1).projection(:enabled=>1).first
  if Vanity.configuration.experiments_start_enabled
    record == nil || record["enabled"] != false
  else
    record && record["enabled"] == true
  end
end

#metric_track(metric, timestamp, identity, values) ⇒ Object

Since:

  • 1.4.0



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 79

def metric_track(metric, timestamp, identity, values)
  inc = {}
  values.each_with_index do |v,i|
    inc["data.#{timestamp.to_date}.#{i}"] = v
  end
  @metrics.find(:_id=>metric).find_one_and_replace(
    {
      "$inc"=>inc,
      "$set"=>{ :last_update_at=>Time.now }
    },
    :upsert=>true
  )
end

#metric_values(metric, from, to) ⇒ Object

Since:

  • 1.4.0



93
94
95
96
97
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 93

def metric_values(metric, from, to)
  record = @metrics.find(:_id=>metric).limit(1).first
  data = record && record["data"] || {}
  (from.to_date..to.to_date).map { |date| (data[date.to_s] || {}).values }
end

#reconnect!Object

Since:

  • 1.4.0



36
37
38
39
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 36

def reconnect!
  disconnect!
  connect!
end

#set_experiment_completed_at(experiment, time) ⇒ Object

Since:

  • 1.4.0



126
127
128
129
130
131
132
133
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 126

def set_experiment_completed_at(experiment, time)
  @experiments.find(:_id=>experiment).find_one_and_replace(
    {
      "$set"=>{ :completed_at=>time }
    },
    :upsert=>true
  )
end

#set_experiment_created_at(experiment, time) ⇒ Object

Since:

  • 1.4.0



110
111
112
113
114
115
116
117
118
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 110

def set_experiment_created_at(experiment, time)
  # @experiments.insert_one(:_id=>experiment, :created_at=>time)
  @experiments.find(:_id=>experiment).find_one_and_replace(
    {
      "$setOnInsert"=>{ :created_at=>time }
    },
    :upsert=>true
  )
end

#set_experiment_enabled(experiment, enabled) ⇒ Object

Since:

  • 1.4.0



144
145
146
147
148
149
150
151
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 144

def set_experiment_enabled(experiment, enabled)
  @experiments.find(:_id=>experiment).find_one_and_replace(
    {
      "$set"=>{ :enabled=>enabled }
    },
    :upsert=>true
  )
end

#to_sObject

Since:

  • 1.4.0



60
61
62
63
# File 'lib/vanity/adapters/mongodb_adapter.rb', line 60

def to_s
  userinfo = @options.values_at(:username, :password).join(":") if @options[:username]
  URI::Generic.build(:scheme=>"mongodb", :userinfo=>userinfo, :host=>(@mongo.host || @options[:host]), :port=>(@mongo.port || @options[:port]), :path=>"/#{@options[:database]}").to_s
end