vanity 3.0.2 → 4.0.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +28 -0
  3. data/.github/workflows/test.yml +3 -6
  4. data/.rubocop.yml +114 -0
  5. data/.rubocop_todo.yml +67 -0
  6. data/Appraisals +9 -31
  7. data/CHANGELOG +13 -0
  8. data/Gemfile +7 -3
  9. data/Gemfile.lock +32 -4
  10. data/README.md +4 -9
  11. data/Rakefile +25 -24
  12. data/bin/vanity +1 -1
  13. data/doc/configuring.textile +1 -0
  14. data/gemfiles/rails52.gemfile +6 -3
  15. data/gemfiles/rails52.gemfile.lock +34 -9
  16. data/gemfiles/rails60.gemfile +6 -3
  17. data/gemfiles/rails60.gemfile.lock +34 -9
  18. data/gemfiles/rails61.gemfile +6 -3
  19. data/gemfiles/rails61.gemfile.lock +34 -9
  20. data/lib/generators/vanity/migration_generator.rb +5 -7
  21. data/lib/vanity/adapters/abstract_adapter.rb +43 -45
  22. data/lib/vanity/adapters/active_record_adapter.rb +30 -30
  23. data/lib/vanity/adapters/mock_adapter.rb +14 -18
  24. data/lib/vanity/adapters/mongodb_adapter.rb +73 -69
  25. data/lib/vanity/adapters/redis_adapter.rb +19 -27
  26. data/lib/vanity/adapters.rb +1 -1
  27. data/lib/vanity/autoconnect.rb +6 -7
  28. data/lib/vanity/commands/list.rb +7 -7
  29. data/lib/vanity/commands/report.rb +18 -22
  30. data/lib/vanity/configuration.rb +23 -19
  31. data/lib/vanity/connection.rb +12 -14
  32. data/lib/vanity/experiment/ab_test.rb +95 -79
  33. data/lib/vanity/experiment/alternative.rb +3 -5
  34. data/lib/vanity/experiment/base.rb +24 -19
  35. data/lib/vanity/experiment/bayesian_bandit_score.rb +7 -13
  36. data/lib/vanity/experiment/definition.rb +6 -6
  37. data/lib/vanity/frameworks/rails.rb +39 -39
  38. data/lib/vanity/frameworks.rb +2 -2
  39. data/lib/vanity/helpers.rb +1 -1
  40. data/lib/vanity/metric/active_record.rb +21 -19
  41. data/lib/vanity/metric/base.rb +22 -23
  42. data/lib/vanity/metric/google_analytics.rb +6 -9
  43. data/lib/vanity/metric/remote.rb +3 -5
  44. data/lib/vanity/playground.rb +3 -6
  45. data/lib/vanity/vanity.rb +8 -12
  46. data/lib/vanity/version.rb +1 -1
  47. data/test/adapters/active_record_adapter_test.rb +1 -5
  48. data/test/adapters/mock_adapter_test.rb +0 -2
  49. data/test/adapters/mongodb_adapter_test.rb +1 -5
  50. data/test/adapters/redis_adapter_test.rb +2 -3
  51. data/test/adapters/shared_tests.rb +9 -12
  52. data/test/autoconnect_test.rb +3 -3
  53. data/test/cli_test.rb +0 -1
  54. data/test/configuration_test.rb +18 -34
  55. data/test/connection_test.rb +3 -3
  56. data/test/dummy/Rakefile +1 -1
  57. data/test/dummy/app/controllers/use_vanity_controller.rb +12 -8
  58. data/test/dummy/app/mailers/vanity_mailer.rb +3 -3
  59. data/test/dummy/config/application.rb +1 -1
  60. data/test/dummy/config/boot.rb +3 -3
  61. data/test/dummy/config/environment.rb +1 -1
  62. data/test/dummy/config/environments/development.rb +0 -1
  63. data/test/dummy/config/environments/test.rb +1 -1
  64. data/test/dummy/config/initializers/session_store.rb +1 -1
  65. data/test/dummy/config/initializers/vanity.rb +3 -0
  66. data/test/dummy/config/vanity.yml +7 -0
  67. data/test/dummy/config.ru +1 -1
  68. data/test/dummy/script/rails +2 -2
  69. data/test/experiment/ab_test.rb +188 -154
  70. data/test/experiment/base_test.rb +48 -32
  71. data/test/frameworks/rails/action_controller_test.rb +25 -25
  72. data/test/frameworks/rails/action_mailer_test.rb +2 -2
  73. data/test/frameworks/rails/action_view_test.rb +5 -6
  74. data/test/frameworks/rails/rails_test.rb +147 -181
  75. data/test/helper_test.rb +2 -2
  76. data/test/metric/active_record_test.rb +174 -212
  77. data/test/metric/base_test.rb +21 -46
  78. data/test/metric/google_analytics_test.rb +17 -25
  79. data/test/metric/remote_test.rb +7 -10
  80. data/test/playground_test.rb +7 -15
  81. data/test/templates_test.rb +16 -20
  82. data/test/test_helper.rb +28 -29
  83. data/test/vanity_test.rb +4 -10
  84. data/test/web/rails/dashboard_test.rb +21 -21
  85. data/vanity.gemspec +8 -7
  86. metadata +32 -30
  87. data/gemfiles/rails42.gemfile +0 -33
  88. data/gemfiles/rails42.gemfile.lock +0 -265
  89. data/gemfiles/rails42_protected_attributes.gemfile +0 -34
  90. data/gemfiles/rails42_protected_attributes.gemfile.lock +0 -264
  91. data/gemfiles/rails51.gemfile +0 -33
  92. data/gemfiles/rails51.gemfile.lock +0 -285
@@ -6,9 +6,10 @@ module Vanity
6
6
  # @since 1.4.0
7
7
  def redis_connection(spec)
8
8
  require "redis"
9
- fail "redis >= 2.1 is required" unless valid_redis_version?
9
+ raise "redis >= 2.1 is required" unless valid_redis_version?
10
+
10
11
  require "redis/namespace"
11
- fail "redis-namespace >= 1.1.0 is required" unless valid_redis_namespace_version?
12
+ raise "redis-namespace >= 1.1.0 is required" unless valid_redis_namespace_version?
12
13
 
13
14
  RedisAdapter.new(spec)
14
15
  end
@@ -28,7 +29,7 @@ module Vanity
28
29
  class RedisAdapter < AbstractAdapter
29
30
  attr_reader :redis
30
31
 
31
- def initialize(options)
32
+ def initialize(options) # rubocop:todo Lint/MissingSuper
32
33
  @options = options.clone
33
34
  @options[:db] ||= @options[:database] || (@options[:path] && @options.delete(:path).split("/")[1].to_i)
34
35
  @options[:thread_safe] = true
@@ -40,9 +41,7 @@ module Vanity
40
41
  end
41
42
 
42
43
  def disconnect!
43
- if redis
44
- redis.disconnect!
45
- end
44
+ redis.disconnect! if redis
46
45
  @redis = nil
47
46
  end
48
47
 
@@ -53,8 +52,8 @@ module Vanity
53
52
 
54
53
  def connect!
55
54
  @redis = @options[:redis] || Redis.new(@options)
56
- @metrics = Redis::Namespace.new("vanity:metrics", :redis=>redis)
57
- @experiments = Redis::Namespace.new("vanity:experiments", :redis=>redis)
55
+ @metrics = Redis::Namespace.new("vanity:metrics", redis: redis)
56
+ @experiments = Redis::Namespace.new("vanity:experiments", redis: redis)
58
57
  end
59
58
 
60
59
  def to_s
@@ -74,7 +73,7 @@ module Vanity
74
73
 
75
74
  def metric_track(metric, timestamp, identity, values)
76
75
  call_redis_with_failover(metric, timestamp, identity, values) do
77
- values.each_with_index do |v,i|
76
+ values.each_with_index do |v, i|
78
77
  @metrics.incrby "#{metric}:#{timestamp.to_date}:value:#{i}", v
79
78
  end
80
79
  @metrics.set("#{metric}:last_update_at", Time.now.to_i)
@@ -90,7 +89,6 @@ module Vanity
90
89
  @metrics.del(*@metrics.keys("#{metric}:*"))
91
90
  end
92
91
 
93
-
94
92
  # -- Experiments --
95
93
 
96
94
  def experiment_persisted?(experiment)
@@ -117,7 +115,7 @@ module Vanity
117
115
  completed_at && Time.at(completed_at.to_i)
118
116
  end
119
117
 
120
- def is_experiment_completed?(experiment)
118
+ def is_experiment_completed?(experiment) # rubocop:todo Naming/PredicateName
121
119
  call_redis_with_failover do
122
120
  @experiments.exists("#{experiment}:completed_at")
123
121
  end
@@ -129,7 +127,7 @@ module Vanity
129
127
  end
130
128
  end
131
129
 
132
- def is_experiment_enabled?(experiment)
130
+ def is_experiment_enabled?(experiment) # rubocop:todo Naming/PredicateName
133
131
  value = @experiments.get("#{experiment}:enabled")
134
132
  if Vanity.configuration.experiments_start_enabled
135
133
  value != 'false'
@@ -140,9 +138,9 @@ module Vanity
140
138
 
141
139
  def ab_counts(experiment, alternative)
142
140
  {
143
- :participants => @experiments.scard("#{experiment}:alts:#{alternative}:participants").to_i,
144
- :converted => @experiments.scard("#{experiment}:alts:#{alternative}:converted").to_i,
145
- :conversions => @experiments.get("#{experiment}:alts:#{alternative}:conversions").to_i
141
+ participants: @experiments.scard("#{experiment}:alts:#{alternative}:participants").to_i,
142
+ converted: @experiments.scard("#{experiment}:alts:#{alternative}:converted").to_i,
143
+ conversions: @experiments.get("#{experiment}:alts:#{alternative}:conversions").to_i,
146
144
  }
147
145
  end
148
146
 
@@ -174,11 +172,7 @@ module Vanity
174
172
  def ab_seen(experiment, identity, alternative_or_id)
175
173
  with_ab_seen_deprecation(experiment, identity, alternative_or_id) do |expt, ident, alt_id|
176
174
  call_redis_with_failover(expt, ident, alt_id) do
177
- if @experiments.sismember "#{expt}:alts:#{alt_id}:participants", ident
178
- alt_id
179
- else
180
- nil
181
- end
175
+ alt_id if @experiments.sismember "#{expt}:alts:#{alt_id}:participants", ident
182
176
  end
183
177
  end
184
178
  end
@@ -187,9 +181,7 @@ module Vanity
187
181
  def ab_assigned(experiment, identity)
188
182
  call_redis_with_failover do
189
183
  Vanity.playground.experiments[experiment].alternatives.each do |alternative|
190
- if @experiments.sismember "#{experiment}:alts:#{alternative.id}:participants", identity
191
- return alternative.id
192
- end
184
+ return alternative.id if @experiments.sismember "#{experiment}:alts:#{alternative.id}:participants", identity
193
185
  end
194
186
  nil
195
187
  end
@@ -219,7 +211,7 @@ module Vanity
219
211
  def destroy_experiment(experiment)
220
212
  cursor = nil
221
213
 
222
- while cursor != "0" do
214
+ while cursor != "0"
223
215
  cursor, keys = @experiments.scan(cursor || "0", match: "#{experiment}:*")
224
216
 
225
217
  @experiments.del(*keys) unless keys.empty?
@@ -229,11 +221,11 @@ module Vanity
229
221
  protected
230
222
 
231
223
  def call_redis_with_failover(*arguments)
232
- calling_method = caller[0][/`.*'/][1..-2]
224
+ calling_method = caller(1..1).first[/`.*'/][1..-2]
233
225
  begin
234
226
  yield
235
- rescue => e
236
- if Vanity.configuration.failover_on_datastore_error
227
+ rescue StandardError => e
228
+ if Vanity.configuration.failover_on_datastore_error # rubocop:todo Style/GuardClause
237
229
  Vanity.configuration.on_datastore_error.call(e, self.class, calling_method, arguments)
238
230
  else
239
231
  raise e
@@ -17,4 +17,4 @@ module Vanity
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -2,8 +2,7 @@ module Vanity
2
2
  # A singleton responsible for determining if the playground should connect
3
3
  # to the datastore.
4
4
  module Autoconnect
5
-
6
- BLACKLISTED_RAILS_RAKE_TASKS = [
5
+ BLACKLISTED_RAILS_RAKE_TASKS = [
7
6
  'about',
8
7
  'assets:clean',
9
8
  'assets:clobber',
@@ -38,7 +37,7 @@ module Vanity
38
37
  'stats',
39
38
  'time:zones:all',
40
39
  'tmp:clear',
41
- 'tmp:create'
40
+ 'tmp:create',
42
41
  ]
43
42
  ENVIRONMENT_VANITY_DISABLED_FLAG = "VANITY_DISABLED"
44
43
 
@@ -46,10 +45,10 @@ module Vanity
46
45
  def should_connect?
47
46
  !environment_disabled? && !in_blacklisted_rake_task?
48
47
  end
49
- alias_method :playground_should_autoconnect?, :should_connect?
48
+ alias playground_should_autoconnect? should_connect?
50
49
 
51
50
  def schema_relevant?
52
- current_rake_tasks.any? { |task| task =~ /\Adb:/ }
51
+ current_rake_tasks.any? { |task| task.start_with?('db:') }
53
52
  end
54
53
 
55
54
  def environment_disabled?
@@ -62,9 +61,9 @@ module Vanity
62
61
 
63
62
  def current_rake_tasks
64
63
  ::Rake.application.top_level_tasks
65
- rescue
64
+ rescue StandardError
66
65
  []
67
66
  end
68
67
  end
69
68
  end
70
- end
69
+ end
@@ -4,16 +4,16 @@ module Vanity
4
4
  # Lists all experiments and metrics.
5
5
  def list
6
6
  Vanity.playground.experiments.each do |id, experiment|
7
- puts "experiment :%-.20s (%-.40s)" % [id, experiment.name]
8
- if experiment.respond_to?(:alternatives)
9
- experiment.alternatives.each do |alt|
10
- hash = experiment.fingerprint(alt)
11
- puts " %s: %-40.40s (%s)" % [alt.name, alt.value, hash]
12
- end
7
+ puts format("experiment :%-.20s (%-.40s)", id, experiment.name)
8
+ next unless experiment.respond_to?(:alternatives)
9
+
10
+ experiment.alternatives.each do |alt|
11
+ hash = experiment.fingerprint(alt)
12
+ puts format(" %s: %-40.40s (%s)", alt.name, alt.value, hash)
13
13
  end
14
14
  end
15
15
  Vanity.playground.metrics.each do |id, metric|
16
- puts "metric :%-.20s (%-.40s)" % [id, metric.name]
16
+ puts format("metric :%-.20s (%-.40s)", id, metric.name)
17
17
  end
18
18
  end
19
19
  end
@@ -2,11 +2,9 @@ require "erb"
2
2
  require "cgi"
3
3
 
4
4
  module Vanity
5
-
6
5
  # Render method available to templates (when used by Vanity command line,
7
6
  # outside Rails).
8
7
  module Render
9
-
10
8
  # Render the named template. Used for reporting and the dashboard.
11
9
  def render(path_or_options, locals = {})
12
10
  if path_or_options.respond_to?(:keys)
@@ -29,21 +27,23 @@ module Vanity
29
27
  end
30
28
 
31
29
  class ProxyEmpty < String
32
- def method_missing(method, *args, &block); self.class.new end
30
+ def method_missing(_method, *_args) # rubocop:todo Style/MissingRespondToMissing
31
+ self.class.new
32
+ end
33
33
  end
34
34
 
35
35
  # prevent certain url helper methods from failing so we can run erb templates outside of rails for reports.
36
- def method_missing(method, *args, &block)
36
+ def method_missing(method, *args, &block) # rubocop:todo Style/MissingRespondToMissing
37
37
  %w(url_for flash).include?(method.to_s) ? ProxyEmpty.new : super
38
38
  end
39
39
 
40
40
  # Dumbed down from Rails' simple_format.
41
- def vanity_simple_format(text, options={})
42
- open = "<p #{options.map { |k,v| "#{k}=\"#{CGI.escapeHTML v}\"" }.join(" ")}>"
43
- text = open + text.gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
44
- gsub(/\n\n+/, "</p>\n\n#{open}"). # 2+ newline -> paragraph
45
- gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') + # 1 newline -> br
46
- "</p>"
41
+ def vanity_simple_format(text, options = {})
42
+ open = "<p #{options.map { |k, v| "#{k}=\"#{CGI.escapeHTML v}\"" }.join(' ')}>"
43
+ text = open + text.gsub(/\r\n?/, "\n") # \r\n and \r -> \n # rubocop:todo Lint/UselessAssignment
44
+ .gsub(/\n\n+/, "</p>\n\n#{open}") # 2+ newline -> paragraph
45
+ .gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') + # 1 newline -> br
46
+ "</p>"
47
47
  end
48
48
 
49
49
  protected
@@ -54,7 +54,7 @@ module Vanity
54
54
  struct = Struct.new(*keys)
55
55
  struct.send :include, Render
56
56
  locals = struct.new(*locals.values_at(*keys))
57
- path = "#{Vanity.template(path)}.erb" unless path =~ /\/.*\.erb\z/
57
+ path = "#{Vanity.template(path)}.erb" unless /\/.*\.erb\z/.match?(path)
58
58
  dir, base = File.split(path)
59
59
  path = File.join(dir, partialize(base))
60
60
  erb = ERB.new(File.read(path), nil, '<>')
@@ -63,10 +63,10 @@ module Vanity
63
63
  end
64
64
 
65
65
  def partialize(template_name)
66
- if template_name[0] != '_'
67
- "_#{template_name}"
68
- else
66
+ if template_name[0] == '_'
69
67
  template_name
68
+ else
69
+ "_#{template_name}"
70
70
  end
71
71
  end
72
72
  end
@@ -80,20 +80,16 @@ module Vanity
80
80
  # arguments.
81
81
  def report(output = nil)
82
82
  html = render(Vanity.template("_report.erb"),
83
- :experiments=>Vanity.playground.experiments,
84
- :experiments_persisted=>Vanity.playground.experiments_persisted?,
85
- :metrics=>Vanity.playground.metrics
86
- )
83
+ experiments: Vanity.playground.experiments,
84
+ experiments_persisted: Vanity.playground.experiments_persisted?,
85
+ metrics: Vanity.playground.metrics)
87
86
  if output
88
- File.open output, 'w' do |file|
89
- file.write html
90
- end
87
+ File.write(output, html)
91
88
  puts "New report available in #{output}"
92
89
  else
93
90
  $stdout.write html
94
91
  end
95
92
  end
96
-
97
93
  end
98
94
  end
99
95
  end
@@ -7,7 +7,7 @@ module Vanity
7
7
  LEGACY_CONNECTION_KEY = :connection
8
8
  LEGACY_REDIS_CONFIG_FILE = "redis.yml"
9
9
 
10
- class<<self
10
+ class << self
11
11
  private
12
12
 
13
13
  def default_logger # :nodoc:
@@ -30,9 +30,9 @@ module Vanity
30
30
  #
31
31
  def default_request_filter(request) # :nodoc:
32
32
  request &&
33
- request.env &&
34
- request.env["HTTP_USER_AGENT"] &&
35
- request.env["HTTP_USER_AGENT"].match( /(?:https?:\/\/)|(?:bot|spider|crawler)/i )
33
+ request.env &&
34
+ request.env["HTTP_USER_AGENT"] &&
35
+ request.env["HTTP_USER_AGENT"].match(/(?:https?:\/\/)|(?:bot|spider|crawler)/i)
36
36
  end
37
37
  end
38
38
 
@@ -46,9 +46,10 @@ module Vanity
46
46
  failover_on_datastore_error: false,
47
47
  locales_path: File.expand_path(File.join(File.dirname(__FILE__), 'locales')),
48
48
  logger: default_logger,
49
- on_datastore_error: ->(error, klass, method, arguments) {
49
+ on_datastore_error: lambda { |error, klass, method, arguments|
50
50
  default_on_datastore_error(error, klass, method, arguments)
51
51
  },
52
+ on_assignment: nil,
52
53
  request_filter: ->(request) { default_request_filter(request) },
53
54
  templates_path: File.expand_path(File.join(File.dirname(__FILE__), 'templates')),
54
55
  use_js: false,
@@ -181,10 +182,13 @@ module Vanity
181
182
  # Cookie path. If true, cookie will not be available to JS. By default false.
182
183
  attr_writer :cookie_httponly
183
184
 
185
+ # Default callback on assigment
186
+ attr_writer :on_assignment
187
+
184
188
  # We independently list each attr_accessor to includes docs, otherwise
185
189
  # something like DEFAULTS.each { |key, value| attr_accessor key } would be
186
190
  # shorter.
187
- DEFAULTS.each do |default, value|
191
+ DEFAULTS.each do |default, _value|
188
192
  define_method default do
189
193
  self[default]
190
194
  end
@@ -204,22 +208,22 @@ module Vanity
204
208
  end
205
209
 
206
210
  # @return nil or a hash of symbolized keys for connection settings
207
- def connection_params(file_name=nil)
211
+ def connection_params(file_name = nil)
208
212
  file_name ||= config_file
209
213
  file_path = File.join(config_path, file_name)
210
214
 
211
- if File.exist?(file_path)
212
- config = YAML.load(ERB.new(File.read(file_path)).result)
215
+ if File.exist?(file_path) # rubocop:todo Style/GuardClause
216
+ config = YAML.safe_load(ERB.new(File.read(file_path)).result, [], [], true)
213
217
  config ||= {}
214
218
  params_for_environment = config[environment.to_s]
215
219
 
216
- unless params_for_environment
217
- raise MissingEnvironment.new("No configuration for #{environment}")
218
- end
220
+ raise MissingEnvironment, "No configuration for #{environment}" unless params_for_environment
219
221
 
220
222
  # Symbolize keys if it's a hash.
221
223
  if params_for_environment.respond_to?(:inject)
222
- params_for_environment.inject({}) { |h,kv| h[kv.first.to_sym] = kv.last ; h }
224
+ params_for_environment.each_with_object({}) do |kv, h|
225
+ h[kv.first.to_sym] = kv.last
226
+ end
223
227
  else
224
228
  params_for_environment
225
229
  end
@@ -234,11 +238,11 @@ module Vanity
234
238
 
235
239
  connection_url = connection_config[LEGACY_CONNECTION_KEY]
236
240
 
237
- if connection_url
238
- logger.warn(%q{Deprecated: Please specify connection urls using the `url` key with a protocol prefix instead of `connection`. This fallback will be removed in a future version.})
241
+ if connection_url # rubocop:todo Style/GuardClause
242
+ logger.warn('Deprecated: Please specify connection urls using the `url` key with a protocol prefix instead of `connection`. This fallback will be removed in a future version.')
239
243
 
240
244
  # Legacy lack of protocol handling
241
- if connection_url =~ /^\w+:/
245
+ if /^\w+:/.match?(connection_url)
242
246
  connection_url
243
247
  else
244
248
  "redis://" + connection_url
@@ -250,10 +254,10 @@ module Vanity
250
254
  def redis_url_from_file
251
255
  connection_url = connection_params(LEGACY_REDIS_CONFIG_FILE)
252
256
 
253
- if connection_url
254
- logger.warn(%q{Deprecated: Please specify the vanity config file, the default fallback to "config/redis.yml" may be removed in a future version.})
257
+ if connection_url # rubocop:todo Style/GuardClause
258
+ logger.warn('Deprecated: Please specify the vanity config file, the default fallback to "config/redis.yml" may be removed in a future version.')
255
259
 
256
- if connection_url =~ /^\w+:/
260
+ if /^\w+:/.match?(connection_url)
257
261
  connection_url
258
262
  else
259
263
  "redis://" + connection_url
@@ -30,12 +30,10 @@ module Vanity
30
30
  # :host=>"redis.local"
31
31
  # )
32
32
  # @since 2.0.0
33
- def initialize(specification=nil)
33
+ def initialize(specification = nil)
34
34
  @specification = Specification.new(specification || DEFAULT_SPECIFICATION).to_h
35
35
 
36
- if Autoconnect.playground_should_autoconnect?
37
- @adapter = setup_connection(@specification)
38
- end
36
+ @adapter = setup_connection(@specification) if Autoconnect.playground_should_autoconnect?
39
37
  end
40
38
 
41
39
  # Closes the current connection.
@@ -68,16 +66,16 @@ module Vanity
68
66
  when String
69
67
  @spec = build_specification_hash_from_url(spec)
70
68
  when Hash
71
- if spec[:redis]
72
- @spec = {
73
- adapter: :redis,
74
- redis: spec[:redis]
75
- }
76
- else
77
- @spec = spec
78
- end
69
+ @spec = if spec[:redis]
70
+ {
71
+ adapter: :redis,
72
+ redis: spec[:redis],
73
+ }
74
+ else
75
+ spec
76
+ end
79
77
  else
80
- raise InvalidSpecification.new("Unsupported connection specification: #{spec.inspect}")
78
+ raise InvalidSpecification, "Unsupported connection specification: #{spec.inspect}"
81
79
  end
82
80
 
83
81
  validate_specification_hash(@spec)
@@ -104,7 +102,7 @@ module Vanity
104
102
  host: uri.host,
105
103
  port: uri.port,
106
104
  path: uri.path,
107
- params: params
105
+ params: params,
108
106
  }
109
107
  end
110
108
  end