flagsmith 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18c4f2e2e68aaffe9c18d2b1e2af5f0018695ecc17c5af3a94051c8bf4cde1b8
4
- data.tar.gz: 53e41364ca7a0347f0358d80616c4781f81835bff43b8f2aedc15d5fa53bb77d
3
+ metadata.gz: 55ba6a7589045f62c03387dfb9fba16bdcf0eec278ee14b3db7549c6d16d0bcc
4
+ data.tar.gz: 1a91d635ec437cfe284492e11e57b2aa06edd13013dd562db0550cc5245a85a6
5
5
  SHA512:
6
- metadata.gz: 3da8964610c7fa4dbd31b94fdbc74b323711b49a4b9be7ad6f92738fc4c9b38e9a69f6a97c1875b78d6ccb86283325cc579b3f16d8b7d97e3b23eab89e8f8c1d
7
- data.tar.gz: c464168ac8cfaff3611e95503b291b4e136e9bc944549b8ad66689232e0ef7411c2074781fbb8f7fd92bdb80775b3317400eb101f8c95bd83bb4d94206891033
6
+ metadata.gz: 1e8bc92bbd6382240c16e9a3a48c5f3509ce4d68518d7152594c43095c722dfe3503216d9e77fa1ff740013c5164c998555ec1a95f98ec6c9b4eed35c037fa8b
7
+ data.tar.gz: 6b3c87dd50db25cc67bb9cca968f9b21ac1a9ed3f935978b6589479cc9ce76689cc9ae7eae9f05cfeb70fd4a8dc090dcd4d3dea6614121d30c08b2b9c9be22eb
data/.rubocop.yml CHANGED
@@ -9,3 +9,4 @@ AllCops:
9
9
  Exclude:
10
10
  - 'spec/**/*'
11
11
  - 'example/**/*'
12
+ - 'vendor/**/*'
data/.rubocop_todo.yml CHANGED
@@ -1,29 +1,22 @@
1
1
  # This configuration was generated by
2
- # `rubocop --auto-gen-config --auto-gen-only-exclude`
3
- # on 2020-12-30 22:56:14 UTC using RuboCop version 1.7.0.
2
+ # `rubocop --auto-gen-config`
3
+ # on 2023-07-20 10:26:52 UTC using RuboCop version 1.54.2.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 1
10
- # Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
11
- # IgnoredMethods: refine
12
- Metrics/BlockLength:
9
+ # Offense count: 6
10
+ # Configuration parameters: EnforcedStyle, AllowedGems, Include.
11
+ # SupportedStyles: Gemfile, gems.rb, gemspec
12
+ # Include: **/*.gemspec, **/Gemfile, **/gems.rb
13
+ Gemspec/DevelopmentDependencies:
13
14
  Exclude:
14
- - '**/*.gemspec'
15
-
16
- # Offense count: 1
17
- # Configuration parameters: AllowedMethods.
18
- # AllowedMethods: respond_to_missing?
19
- Style/OptionalBooleanParameter:
20
- Exclude:
21
- - 'lib/flagsmith.rb'
15
+ - 'flagsmith.gemspec'
22
16
 
23
- # Offense count: 1
24
- # Cop supports --auto-correct.
25
- # Configuration parameters: AutoCorrect, Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
17
+ # Offense count: 4
18
+ # This cop supports safe autocorrection (--autocorrect).
19
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
26
20
  # URISchemes: http, https
27
21
  Layout/LineLength:
28
- Exclude:
29
- - 'flagsmith.gemspec'
22
+ Max: 183
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.4.0
1
+ 3.1.4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flagsmith (3.1.0)
4
+ flagsmith (3.2.0)
5
5
  faraday
6
6
  faraday-retry
7
7
  faraday_middleware
@@ -10,10 +10,10 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- ast (2.4.1)
13
+ ast (2.4.2)
14
14
  coderay (1.1.3)
15
15
  diff-lcs (1.4.4)
16
- faraday (1.10.0)
16
+ faraday (1.10.3)
17
17
  faraday-em_http (~> 1.0)
18
18
  faraday-em_synchrony (~> 1.0)
19
19
  faraday-excon (~> 1.1)
@@ -39,17 +39,21 @@ GEM
39
39
  faraday_middleware (1.2.0)
40
40
  faraday (~> 1.0)
41
41
  gem-release (2.2.0)
42
+ json (2.6.3)
43
+ language_server-protocol (3.17.0.3)
42
44
  method_source (1.0.0)
43
- multipart-post (2.2.3)
44
- parallel (1.20.1)
45
- parser (3.0.0.0)
45
+ multipart-post (2.3.0)
46
+ parallel (1.23.0)
47
+ parser (3.2.2.3)
46
48
  ast (~> 2.4.1)
49
+ racc
47
50
  pry (0.14.1)
48
51
  coderay (~> 1.1)
49
52
  method_source (~> 1.0)
50
- rainbow (3.0.0)
53
+ racc (1.7.1)
54
+ rainbow (3.1.1)
51
55
  rake (13.0.3)
52
- regexp_parser (2.0.3)
56
+ regexp_parser (2.8.1)
53
57
  rexml (3.2.5)
54
58
  rspec (3.10.0)
55
59
  rspec-core (~> 3.10.0)
@@ -64,21 +68,23 @@ GEM
64
68
  diff-lcs (>= 1.2.0, < 2.0)
65
69
  rspec-support (~> 3.10.0)
66
70
  rspec-support (3.10.1)
67
- rubocop (1.7.0)
71
+ rubocop (1.54.2)
72
+ json (~> 2.3)
73
+ language_server-protocol (>= 3.17.0)
68
74
  parallel (~> 1.10)
69
- parser (>= 2.7.1.5)
75
+ parser (>= 3.2.2.3)
70
76
  rainbow (>= 2.2.2, < 4.0)
71
77
  regexp_parser (>= 1.8, < 3.0)
72
- rexml
73
- rubocop-ast (>= 1.2.0, < 2.0)
78
+ rexml (>= 3.2.5, < 4.0)
79
+ rubocop-ast (>= 1.28.0, < 2.0)
74
80
  ruby-progressbar (~> 1.7)
75
- unicode-display_width (>= 1.4.0, < 2.0)
76
- rubocop-ast (1.3.0)
77
- parser (>= 2.7.1.5)
78
- ruby-progressbar (1.10.1)
81
+ unicode-display_width (>= 2.4.0, < 3.0)
82
+ rubocop-ast (1.29.0)
83
+ parser (>= 3.2.1.0)
84
+ ruby-progressbar (1.13.0)
79
85
  ruby2_keywords (0.0.5)
80
86
  semantic (1.6.1)
81
- unicode-display_width (1.7.0)
87
+ unicode-display_width (2.4.2)
82
88
 
83
89
  PLATFORMS
84
90
  ruby
data/example/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- flagsmith (3.0.0)
4
+ flagsmith (3.1.1)
5
5
  faraday
6
6
  faraday-retry
7
7
  faraday_middleware
@@ -10,8 +10,8 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- addressable (2.8.0)
14
- public_suffix (>= 2.0.2, < 5.0)
13
+ addressable (2.8.4)
14
+ public_suffix (>= 2.0.2, < 6.0)
15
15
  ast (2.4.2)
16
16
  better_errors (2.9.1)
17
17
  coderay (>= 1.0.0)
@@ -20,13 +20,14 @@ GEM
20
20
  bigdecimal (1.4.4)
21
21
  binding_of_caller (0.8.0)
22
22
  debug_inspector (>= 0.0.1)
23
- capybara (3.32.2)
23
+ capybara (3.39.0)
24
24
  addressable
25
+ matrix
25
26
  mini_mime (>= 0.1.3)
26
27
  nokogiri (~> 1.8)
27
28
  rack (>= 1.6.0)
28
29
  rack-test (>= 0.6.3)
29
- regexp_parser (~> 1.5)
30
+ regexp_parser (>= 1.5, < 3.0)
30
31
  xpath (~> 3.2)
31
32
  coderay (1.1.3)
32
33
  concurrent-ruby (1.1.10)
@@ -71,7 +72,7 @@ GEM
71
72
  dry-logic (~> 0.4, >= 0.4.0)
72
73
  dry-types (~> 0.11.0)
73
74
  erubi (1.10.0)
74
- faraday (1.10.0)
75
+ faraday (1.10.3)
75
76
  faraday-em_http (~> 1.0)
76
77
  faraday-em_synchrony (~> 1.0)
77
78
  faraday-excon (~> 1.1)
@@ -87,8 +88,8 @@ GEM
87
88
  faraday-em_synchrony (1.0.0)
88
89
  faraday-excon (1.1.0)
89
90
  faraday-httpclient (1.0.1)
90
- faraday-multipart (1.0.3)
91
- multipart-post (>= 1.2, < 3)
91
+ faraday-multipart (1.0.4)
92
+ multipart-post (~> 2)
92
93
  faraday-net_http (1.0.1)
93
94
  faraday-net_http_persistent (1.2.0)
94
95
  faraday-patron (1.0.0)
@@ -156,28 +157,31 @@ GEM
156
157
  inflecto (0.0.2)
157
158
  mail (2.7.1)
158
159
  mini_mime (>= 0.1.1)
160
+ matrix (0.4.2)
159
161
  method_source (1.0.0)
160
162
  mini_mime (1.1.2)
161
- mini_portile2 (2.4.0)
162
- multipart-post (2.1.1)
163
+ multipart-post (2.3.0)
163
164
  nio4r (2.5.8)
164
- nokogiri (1.10.10)
165
- mini_portile2 (~> 2.4.0)
165
+ nokogiri (1.14.3-arm64-darwin)
166
+ racc (~> 1.4)
167
+ nokogiri (1.14.3-x86_64-linux)
168
+ racc (~> 1.4)
166
169
  parallel (1.20.1)
167
170
  parser (3.1.2.0)
168
171
  ast (~> 2.4.1)
169
172
  pry (0.14.1)
170
173
  coderay (~> 1.1)
171
174
  method_source (~> 1.0)
172
- public_suffix (4.0.7)
175
+ public_suffix (5.0.1)
173
176
  puma (5.6.4)
174
177
  nio4r (~> 2.0)
175
- rack (2.2.3.1)
176
- rack-test (1.1.0)
177
- rack (>= 1.0, < 3)
178
+ racc (1.6.2)
179
+ rack (2.2.7)
180
+ rack-test (2.1.0)
181
+ rack (>= 1.3)
178
182
  rainbow (3.1.1)
179
183
  rake (13.0.6)
180
- regexp_parser (1.8.2)
184
+ regexp_parser (2.8.0)
181
185
  rexml (3.2.5)
182
186
  rom (3.3.3)
183
187
  concurrent-ruby (~> 1.0)
@@ -245,6 +249,7 @@ GEM
245
249
  nokogiri (~> 1.8)
246
250
 
247
251
  PLATFORMS
252
+ arm64-darwin-21
248
253
  x86_64-linux
249
254
 
250
255
  DEPENDENCIES
data/flagsmith.gemspec CHANGED
@@ -35,4 +35,5 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency 'faraday_middleware'
36
36
  spec.add_dependency 'faraday-retry'
37
37
  spec.add_dependency 'semantic'
38
+ spec.metadata['rubygems_mfa_required'] = 'true'
38
39
  end
@@ -40,9 +40,7 @@ module Flagsmith
40
40
  multivariate_feature_state_values.sort.each do |multi_fs_value|
41
41
  limit = multi_fs_value.percentage_allocation + start_percentage
42
42
 
43
- if start_percentage <= percentage_value && percentage_value < limit
44
- return multi_fs_value.multivariate_feature_option.value
45
- end
43
+ return multi_fs_value.multivariate_feature_option.value if start_percentage <= percentage_value && percentage_value < limit
46
44
 
47
45
  start_percentage = limit
48
46
  end
@@ -165,7 +163,7 @@ module Flagsmith
165
163
  attr_reader :priority
166
164
 
167
165
  def initialize(params = {})
168
- @priority = params[:priority].nil? ? nil : params[:priority].to_i
166
+ @priority = params[:priority]&.to_i
169
167
  end
170
168
  end
171
169
  end
@@ -25,6 +25,7 @@ module Flagsmith
25
25
  IS_SET = 'IS_SET'
26
26
  IS_NOT_SET = 'IS_NOT_SET'
27
27
  MODULO = 'MODULO'
28
+ IN = 'IN'
28
29
 
29
30
  CONDITION_OPERATORS = [
30
31
  EQUAL,
@@ -37,7 +38,8 @@ module Flagsmith
37
38
  NOT_EQUAL,
38
39
  REGEX,
39
40
  PERCENTAGE_SPLIT,
40
- MODULO
41
+ MODULO,
42
+ IN
41
43
  ].freeze
42
44
  end
43
45
  end
@@ -36,6 +36,7 @@ module Flagsmith
36
36
  end
37
37
  end
38
38
 
39
+ # rubocop:disable Metrics/MethodLength
39
40
  def traits_match_segment_rule(identity_traits, rule, segment_id, identity_id)
40
41
  matching_block = lambda { |condition|
41
42
  traits_match_segment_condition(identity_traits, condition, segment_id, identity_id)
@@ -44,23 +45,25 @@ module Flagsmith
44
45
  matches_conditions =
45
46
  if rule.conditions&.length&.positive?
46
47
  rule.conditions.send(rule.matching_function, &matching_block)
47
- else true
48
+ else
49
+ true
48
50
  end
49
51
 
50
52
  matches_conditions &&
51
53
  rule.rules.all? { |r| traits_match_segment_rule(identity_traits, r, segment_id, identity_id) }
52
54
  end
55
+ # rubocop:enable Metrics/MethodLength
53
56
 
54
57
  def traits_match_segment_condition(identity_traits, condition, segment_id, identity_id)
55
58
  if condition.operator == PERCENTAGE_SPLIT
56
- return hashed_percentage_for_object_ids([segment_id, identity_id]) <= condition.value.to_f
59
+ return hashed_percentage_for_object_ids([segment_id,
60
+ identity_id]) <= condition.value.to_f
57
61
  end
58
62
 
59
63
  trait = identity_traits.find { |t| t.key.to_s == condition.property }
60
64
 
61
- if [IS_SET, IS_NOT_SET].include?(condition.operator)
62
- return handle_trait_existence_conditions(trait, condition.operator)
63
- end
65
+ return handle_trait_existence_conditions(trait, condition.operator) if [IS_SET,
66
+ IS_NOT_SET].include?(condition.operator)
64
67
 
65
68
  return condition.match_trait_value?(trait.trait_value) if trait
66
69
 
@@ -56,10 +56,9 @@ module Flagsmith
56
56
 
57
57
  def match_trait_value?(trait_value)
58
58
  # handle some exceptions
59
- if @value.is_a?(String) && @value.match?(/:semver$/)
60
- trait_value = Semantic::Version.new(trait_value.gsub(/:semver$/, ''))
61
- end
59
+ trait_value = Semantic::Version.new(trait_value.gsub(/:semver$/, '')) if @value.is_a?(String) && @value.match?(/:semver$/)
62
60
 
61
+ return match_in_value(trait_value) if @operator == IN
63
62
  return match_modulo_value(trait_value) if @operator == MODULO
64
63
 
65
64
  type_as_trait_value = format_to_type_of(trait_value)
@@ -73,8 +72,8 @@ module Flagsmith
73
72
  {
74
73
  'String' => ->(v) { v.to_s },
75
74
  'Semantic::Version' => ->(v) { Semantic::Version.new(v.to_s.gsub(/:semver$/, '')) },
76
- 'TrueClass' => ->(v) { ['True', 'true', 'TRUE', true, 1, '1'].include?(v) ? true : false },
77
- 'FalseClass' => ->(v) { ['False', 'false', 'FALSE', false, 0, '0'].include?(v) ? false : true },
75
+ 'TrueClass' => ->(v) { ['True', 'true', 'TRUE', true, 1, '1'].include?(v) },
76
+ 'FalseClass' => ->(v) { !['False', 'false', 'FALSE', false, 0, '0'].include?(v) },
78
77
  'Integer' => ->(v) { v.to_i },
79
78
  'Float' => ->(v) { v.to_f }
80
79
  }[input.class.to_s]
@@ -83,11 +82,17 @@ module Flagsmith
83
82
 
84
83
  def match_modulo_value(trait_value)
85
84
  divisor, remainder = @value.split('|')
86
- trait_value.is_a?(Numeric) && trait_value % divisor.to_f == remainder.to_f
85
+ trait_value.is_a?(Numeric) && trait_value % divisor.to_f == remainder.to_f # rubocop:disable Lint/FloatComparison
87
86
  rescue StandardError
88
87
  false
89
88
  end
90
89
 
90
+ def match_in_value(trait_value)
91
+ return @value.split(',').include?(trait_value.to_s) if trait_value.is_a?(String) || trait_value.is_a?(Integer)
92
+
93
+ false
94
+ end
95
+
91
96
  class << self
92
97
  def build(json)
93
98
  new(**json.slice(:operator, :value).merge(property: json[:property_]))
@@ -33,7 +33,7 @@ module Flagsmith
33
33
 
34
34
  def track_feature(feature_name)
35
35
  @analytics_data[feature_name] = @analytics_data.fetch(feature_name, 0) + 1
36
- flush if (Time.now - @last_flushed) > TIMER * 1000
36
+ flush if (Time.now - @last_flushed) > TIMER
37
37
  end
38
38
  end
39
39
  end
@@ -84,7 +84,7 @@ module Flagsmith
84
84
 
85
85
  class << self
86
86
  def environment_key
87
- ENV['FLAGSMITH_ENVIRONMENT_KEY']
87
+ ENV.fetch('FLAGSMITH_ENVIRONMENT_KEY', nil)
88
88
  end
89
89
  end
90
90
  end
@@ -4,32 +4,34 @@ module Flagsmith
4
4
  module Flags
5
5
  class NotFound < StandardError; end
6
6
 
7
+ # Base data class for the flag entity
7
8
  class BaseFlag
8
9
  include Comparable
9
10
 
10
11
  attr_reader :enabled, :value, :default
11
-
12
+
12
13
  def initialize(enabled:, value:, default:)
13
14
  @enabled = enabled
14
15
  @value = value
15
16
  @default = default
16
17
  end
17
-
18
+
18
19
  def enabled?
19
20
  enabled
20
21
  end
21
-
22
+
22
23
  alias is_default default
23
24
  end
24
25
 
26
+ # Flag class to be used by default handler logic
25
27
  class DefaultFlag < BaseFlag
26
28
  def initialize(enabled:, value:)
27
29
  super(enabled: enabled, value: value, default: true)
28
30
  end
29
31
  end
30
32
 
33
+ # 'live' Flag class as returned by API or local evaluation
31
34
  class Flag < BaseFlag
32
-
33
35
  attr_reader :feature_name, :feature_id
34
36
 
35
37
  def initialize(feature_name:, enabled:, value:, feature_id:)
@@ -77,6 +79,8 @@ module Flagsmith
77
79
  end
78
80
  end
79
81
 
82
+ # Implementation of a class to hold a collection of flags.
83
+ # Implements methods for working with the list to avoid requesting flags for each feature evaluation.
80
84
  class Collection
81
85
  include Enumerable
82
86
 
@@ -159,7 +163,7 @@ module Flagsmith
159
163
  def from_feature_state_models(feature_states, identity_id: nil, **args)
160
164
  to_flag_object = lambda { |feature_state, acc|
161
165
  acc[normalize_key(feature_state.feature.name)] =
162
- Flagsmith::Flags::Flag.from_feature_state_model(feature_state, identity_id)
166
+ Flagsmith::Flags::Flag.from_feature_state_model(feature_state, identity_id)
163
167
  }
164
168
 
165
169
  new(
@@ -2,9 +2,10 @@
2
2
 
3
3
  module Flagsmith
4
4
  module Segments
5
+ # Data class to hold segment information.
5
6
  class Segment
6
7
  attr_reader :id, :name
7
-
8
+
8
9
  def initialize(id:, name:)
9
10
  @id = id
10
11
  @name = name
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flagsmith
4
- VERSION = '3.1.0'
4
+ VERSION = '3.2.0'
5
5
  end
data/lib/flagsmith.rb CHANGED
@@ -22,7 +22,7 @@ require 'flagsmith/engine/core'
22
22
  # no-doc
23
23
  module Flagsmith
24
24
  # Ruby client for flagsmith.com
25
- class Client
25
+ class Client # rubocop:disable Metrics/ClassLength
26
26
  extend Forwardable
27
27
  # A Flagsmith client.
28
28
  #
@@ -153,13 +153,13 @@ module Flagsmith
153
153
 
154
154
  def get_identity_segments(identifier, traits = {})
155
155
  unless environment
156
- raise Flagsmith::ClientError,
157
- 'Local evaluation required to obtain identity segments.'
156
+ raise Flagsmith::ClientError,
157
+ 'Local evaluation required to obtain identity segments.'
158
158
  end
159
159
 
160
160
  identity_model = build_identity_model(identifier, traits)
161
161
  segment_models = engine.get_identity_segments(environment, identity_model)
162
- return segment_models.map { |sm| Flagsmith::Segments::Segment.new(id: sm.id, name: sm.name) }.compact
162
+ segment_models.map { |sm| Flagsmith::Segments::Segment.new(id: sm.id, name: sm.name) }.compact
163
163
  end
164
164
 
165
165
  private
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flagsmith
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Stuart
8
8
  - Brian Moelk
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-11-01 00:00:00.000000000 Z
12
+ date: 2023-07-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -228,8 +228,9 @@ files:
228
228
  - lib/flagsmith/version.rb
229
229
  homepage: https://flagsmith.com
230
230
  licenses: []
231
- metadata: {}
232
- post_install_message:
231
+ metadata:
232
+ rubygems_mfa_required: 'true'
233
+ post_install_message:
233
234
  rdoc_options: []
234
235
  require_paths:
235
236
  - lib
@@ -244,8 +245,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
244
245
  - !ruby/object:Gem::Version
245
246
  version: '0'
246
247
  requirements: []
247
- rubygems_version: 3.3.7
248
- signing_key:
248
+ rubygems_version: 3.3.26
249
+ signing_key:
249
250
  specification_version: 4
250
251
  summary: Flagsmith - Ship features with confidence
251
252
  test_files: []