flagsmith 4.0.0 → 4.1.0

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/lib/flagsmith/engine/environments/models.rb +14 -3
  4. data/lib/flagsmith/sdk/analytics_processor.rb +7 -2
  5. data/lib/flagsmith/version.rb +1 -1
  6. data/lib/flagsmith.rb +29 -10
  7. metadata +2 -37
  8. data/example/.env.development +0 -5
  9. data/example/.env.test +0 -4
  10. data/example/.gitignore +0 -5
  11. data/example/.hanamirc +0 -3
  12. data/example/.rspec +0 -2
  13. data/example/Gemfile +0 -25
  14. data/example/Gemfile.lock +0 -274
  15. data/example/README.md +0 -29
  16. data/example/Rakefile +0 -9
  17. data/example/apps/web/application.rb +0 -162
  18. data/example/apps/web/config/routes.rb +0 -1
  19. data/example/apps/web/controllers/.gitkeep +0 -0
  20. data/example/apps/web/controllers/home/index.rb +0 -32
  21. data/example/apps/web/templates/application.html.slim +0 -7
  22. data/example/apps/web/templates/home/index.html.slim +0 -10
  23. data/example/apps/web/views/application_layout.rb +0 -7
  24. data/example/apps/web/views/home/index.rb +0 -29
  25. data/example/config/boot.rb +0 -2
  26. data/example/config/environment.rb +0 -17
  27. data/example/config/initializers/.gitkeep +0 -0
  28. data/example/config/initializers/flagsmith.rb +0 -7
  29. data/example/config/puma.rb +0 -15
  30. data/example/config.ru +0 -3
  31. data/example/spec/example/entities/.gitkeep +0 -0
  32. data/example/spec/example/mailers/.gitkeep +0 -0
  33. data/example/spec/example/repositories/.gitkeep +0 -0
  34. data/example/spec/features_helper.rb +0 -12
  35. data/example/spec/spec_helper.rb +0 -103
  36. data/example/spec/support/.gitkeep +0 -0
  37. data/example/spec/support/capybara.rb +0 -8
  38. data/example/spec/web/controllers/.gitkeep +0 -0
  39. data/example/spec/web/controllers/home/index_spec.rb +0 -9
  40. data/example/spec/web/features/.gitkeep +0 -0
  41. data/example/spec/web/views/application_layout_spec.rb +0 -10
  42. data/example/spec/web/views/home/index_spec.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7e45006cc3caabc6941c7daaf58f339940cb1ea1fc3ec76be0a7897d84212fa
4
- data.tar.gz: 32703828745194ea1befb791266e592e888c7fac888fd35c4cc6b6e9b6f3e204
3
+ metadata.gz: c1951f9f2c2eebff1765ad5b1bbdcdd2502f33c0c86262d4450e53b5921c4646
4
+ data.tar.gz: 0d2fe63cdde7a4da85d71b8a982a38c07b65d141eae3f174200d4cb990db8a6f
5
5
  SHA512:
6
- metadata.gz: fa77df821acafa8ccc9d0580845573b47fe0287c1937a7f8200d08532f559d77af1c41e6862a52a0ab90fec30cc020ea63068120aa95a95da41cff2b2a48e84d
7
- data.tar.gz: 25f98c085b4b8253356fbc203e5605fa6ac53930e7ac8bbe7d2be1f5ba8dc8bf0374ca9a85b57bebafb08b9e57077dcc18637fca9b9d91a758ec404398de663a
6
+ metadata.gz: 6617e71586183e9dc163e21b857a8d26fd0698390b51066b4aa2a812831e1b44a4c076eb728e1586fc8ab604c359bc0652cb2f79e4426e6c1a8a5c5637106625
7
+ data.tar.gz: c720ab5adbd784ca3447970d7eceb97f93c656779cddc75c5149c5437a62a8838107b692cc6e58c74e52f06a434e2e56032bc67597e844881a673bb1a08f6f14
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flagsmith (4.0.0)
4
+ flagsmith (4.1.0)
5
5
  faraday (>= 2.0.1)
6
6
  faraday-retry
7
7
  semantic
@@ -17,7 +17,7 @@ GEM
17
17
  faraday-net_http (>= 2.0, < 3.2)
18
18
  faraday-net_http (3.1.0)
19
19
  net-http
20
- faraday-retry (2.2.0)
20
+ faraday-retry (2.2.1)
21
21
  faraday (~> 2.0)
22
22
  gem-release (2.2.2)
23
23
  json (2.7.1)
@@ -6,24 +6,35 @@ module Flagsmith
6
6
  class Environment
7
7
  attr_reader :id, :api_key
8
8
  attr_accessor :project, :feature_states, :amplitude_config, :segment_config,
9
- :mixpanel_config, :heap_config
9
+ :mixpanel_config, :heap_config, :identity_overrides
10
10
 
11
- def initialize(id:, api_key:, project:, feature_states: [])
11
+ def initialize(id:, api_key:, project:, feature_states: [], identity_overrides: [])
12
12
  @id = id
13
13
  @api_key = api_key
14
14
  @project = project
15
15
  @feature_states = feature_states
16
+ @identity_overrides = identity_overrides
16
17
  end
17
18
 
18
19
  class << self
20
+ # rubocop:disable Metrics/MethodLength
19
21
  def build(json)
20
22
  project = Flagsmith::Engine::Project.build(json[:project])
21
23
  feature_states = json[:feature_states].map do |fs|
22
24
  Flagsmith::Engine::FeatureState.build(fs)
23
25
  end
24
26
 
25
- new(**json.slice(:id, :api_key).merge(project: project, feature_states: feature_states))
27
+ identity_overrides = json.fetch(:identity_overrides, []).map do |io|
28
+ Flagsmith::Engine::Identity.build(io)
29
+ end
30
+
31
+ new(**json.slice(:id, :api_key).merge(
32
+ project: project,
33
+ feature_states: feature_states,
34
+ identity_overrides: identity_overrides
35
+ ))
26
36
  end
37
+ # rubocop:enable Metrics/MethodLength
27
38
  end
28
39
  end
29
40
 
@@ -19,15 +19,20 @@ module Flagsmith
19
19
  @analytics_data = {}
20
20
  @api_client = data.fetch(:api_client)
21
21
  @timeout = data.fetch(:timeout, 3)
22
+ @logger = data.fetch(:logger)
22
23
  end
23
24
 
24
25
  # Sends all the collected data to the api asynchronously and resets the timer
25
26
  def flush
26
27
  return if @analytics_data.empty?
27
28
 
28
- @api_client.post(ENDPOINT, @analytics_data.to_json)
29
+ begin
30
+ @api_client.post(ENDPOINT, @analytics_data.to_json)
31
+ @analytics_data = {}
32
+ rescue StandardError => e
33
+ @logger.warn "Temporarily unable to access flag analytics endpoint for exception: #{e}"
34
+ end
29
35
 
30
- @analytics_data = {}
31
36
  @last_flushed = Time.now
32
37
  end
33
38
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flagsmith
4
- VERSION = '4.0.0'
4
+ VERSION = '4.1.0'
5
5
  end
data/lib/flagsmith.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pry'
4
- require 'pry-byebug'
5
-
6
3
  require 'faraday'
7
4
  require 'faraday/retry'
8
5
 
@@ -52,13 +49,14 @@ module Flagsmith
52
49
  #
53
50
  # You can see full description in the Flagsmith::Config
54
51
 
55
- attr_reader :config, :environment
52
+ attr_reader :config, :environment, :identity_overrides_by_identifier
56
53
 
57
54
  delegate Flagsmith::Config::OPTIONS => :@config
58
55
 
59
56
  def initialize(config)
60
57
  @_mutex = Mutex.new
61
58
  @config = Flagsmith::Config.new(config)
59
+ @identity_overrides_by_identifier = {}
62
60
 
63
61
  validate_offline_mode!
64
62
 
@@ -94,7 +92,8 @@ module Flagsmith
94
92
  @analytics_processor ||=
95
93
  Flagsmith::AnalyticsProcessor.new(
96
94
  api_client: api_client,
97
- timeout: request_timeout_seconds
95
+ timeout: request_timeout_seconds,
96
+ logger: @config.logger
98
97
  )
99
98
  end
100
99
 
@@ -105,7 +104,7 @@ module Flagsmith
105
104
  def environment_data_polling_manager
106
105
  return nil unless @config.local_evaluation?
107
106
 
108
- update_environment
107
+ update_environment if @environment_data_polling_manager.nil?
109
108
 
110
109
  @environment_data_polling_manager ||= Flagsmith::EnvironmentDataPollingManager.new(
111
110
  self, environment_refresh_interval_seconds
@@ -116,6 +115,16 @@ module Flagsmith
116
115
  # You only need to call this if you wish to bypass environment_refresh_interval_seconds.
117
116
  def update_environment
118
117
  @_mutex.synchronize { @environment = environment_from_api }
118
+ update_identity_overrides
119
+ end
120
+
121
+ def update_identity_overrides
122
+ return unless @environment
123
+
124
+ @identity_overrides_by_identifier = {}
125
+ @environment.identity_overrides.each do |identity|
126
+ @identity_overrides_by_identifier[identity.identifier] = identity
127
+ end
119
128
  end
120
129
 
121
130
  def environment_from_api
@@ -180,7 +189,7 @@ module Flagsmith
180
189
  'Local evaluation or offline handler is required to obtain identity segments.'
181
190
  end
182
191
 
183
- identity_model = build_identity_model(identifier, traits)
192
+ identity_model = get_identity_model(identifier, traits)
184
193
  segment_models = engine.get_identity_segments(environment, identity_model)
185
194
  segment_models.map { |sm| Flagsmith::Segments::Segment.new(id: sm.id, name: sm.name) }.compact
186
195
  end
@@ -197,10 +206,11 @@ module Flagsmith
197
206
  end
198
207
 
199
208
  def get_identity_flags_from_document(identifier, traits = {})
200
- identity_model = build_identity_model(identifier, traits)
209
+ identity_model = get_identity_model(identifier, traits)
201
210
 
202
211
  Flagsmith::Flags::Collection.from_feature_state_models(
203
212
  engine.get_identity_feature_states(environment, identity_model),
213
+ identity_id: identity_model.composite_key,
204
214
  analytics_processor: analytics_processor,
205
215
  default_flag_handler: default_flag_handler,
206
216
  offline_handler: offline_handler
@@ -278,19 +288,28 @@ module Flagsmith
278
288
  )
279
289
  end
280
290
 
281
- def build_identity_model(identifier, traits = {})
291
+ # rubocop:disable Metrics/MethodLength
292
+ def get_identity_model(identifier, traits = {})
282
293
  unless environment
283
294
  raise Flagsmith::ClientError,
284
- 'Unable to build identity model when no local environment present.'
295
+ 'Unable to get identity model when no local environment present.'
285
296
  end
286
297
 
287
298
  trait_models = traits.map do |key, value|
288
299
  Flagsmith::Engine::Identities::Trait.new(trait_key: key, trait_value: value)
289
300
  end
301
+
302
+ if identity_overrides_by_identifier.key? identifier
303
+ identity = identity_overrides_by_identifier[identifier]
304
+ identity.update_traits trait_models
305
+ return identity
306
+ end
307
+
290
308
  Flagsmith::Engine::Identity.new(
291
309
  identity_traits: trait_models, environment_api_key: environment_key, identifier: identifier
292
310
  )
293
311
  end
312
+ # rubocop:enable Metrics/MethodLength
294
313
 
295
314
  def generate_identities_data(identifier, traits = {})
296
315
  {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flagsmith
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Stuart
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2024-01-30 00:00:00.000000000 Z
13
+ date: 2024-04-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -171,41 +171,6 @@ files:
171
171
  - LICENCE
172
172
  - README.md
173
173
  - Rakefile
174
- - example/.env.development
175
- - example/.env.test
176
- - example/.gitignore
177
- - example/.hanamirc
178
- - example/.rspec
179
- - example/Gemfile
180
- - example/Gemfile.lock
181
- - example/README.md
182
- - example/Rakefile
183
- - example/apps/web/application.rb
184
- - example/apps/web/config/routes.rb
185
- - example/apps/web/controllers/.gitkeep
186
- - example/apps/web/controllers/home/index.rb
187
- - example/apps/web/templates/application.html.slim
188
- - example/apps/web/templates/home/index.html.slim
189
- - example/apps/web/views/application_layout.rb
190
- - example/apps/web/views/home/index.rb
191
- - example/config.ru
192
- - example/config/boot.rb
193
- - example/config/environment.rb
194
- - example/config/initializers/.gitkeep
195
- - example/config/initializers/flagsmith.rb
196
- - example/config/puma.rb
197
- - example/spec/example/entities/.gitkeep
198
- - example/spec/example/mailers/.gitkeep
199
- - example/spec/example/repositories/.gitkeep
200
- - example/spec/features_helper.rb
201
- - example/spec/spec_helper.rb
202
- - example/spec/support/.gitkeep
203
- - example/spec/support/capybara.rb
204
- - example/spec/web/controllers/.gitkeep
205
- - example/spec/web/controllers/home/index_spec.rb
206
- - example/spec/web/features/.gitkeep
207
- - example/spec/web/views/application_layout_spec.rb
208
- - example/spec/web/views/home/index_spec.rb
209
174
  - flagsmith.gemspec
210
175
  - lib/flagsmith.rb
211
176
  - lib/flagsmith/engine/core.rb
@@ -1,5 +0,0 @@
1
- # Define ENV variables for development environment
2
- DATABASE_URL="sqlite://db/example_development.sqlite"
3
- SERVE_STATIC_ASSETS="true"
4
- WEB_SESSIONS_SECRET="4743628fa58981a0eaf99cc636146f49ceffd0ab6a8423c0e2493e67cd825f67"
5
- FLAGSMITH_ENVIRONMENT_KEY="YOUR_FLAGSMITH_ENVIRONMENT_KEY"
data/example/.env.test DELETED
@@ -1,4 +0,0 @@
1
- # Define ENV variables for test environment
2
- DATABASE_URL="sqlite://db/example_test.sqlite"
3
- SERVE_STATIC_ASSETS="true"
4
- WEB_SESSIONS_SECRET="50f1a22a68ccc6d06b48387f4cd4aa63cbaabd2b525c288f0f7a7046b10cc6ac"
data/example/.gitignore DELETED
@@ -1,5 +0,0 @@
1
- /db/*.sqlite
2
- /public/assets*
3
- /tmp
4
- .env.local
5
- .env.*.local
data/example/.hanamirc DELETED
@@ -1,3 +0,0 @@
1
- project=example
2
- test=rspec
3
- template=slim
data/example/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --require spec_helper
data/example/Gemfile DELETED
@@ -1,25 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'hanami', '~> 1.3'
4
- gem 'hanami-model', '~> 1.3'
5
- gem 'slim'
6
- gem 'sqlite3'
7
- gem "puma", "~> 6.3"
8
-
9
- gemspec path: '../'
10
-
11
- group :development do
12
- # Code reloading
13
- # See: https://guides.hanamirb.org/projects/code-reloading
14
- gem 'hanami-webconsole'
15
- gem 'shotgun', platforms: :ruby
16
- end
17
-
18
- group :test, :development do
19
- gem 'dotenv', '~> 2.4'
20
- end
21
-
22
- group :test do
23
- gem 'capybara'
24
- gem 'rspec'
25
- end
data/example/Gemfile.lock DELETED
@@ -1,274 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- flagsmith (3.1.1)
5
- faraday
6
- faraday-retry
7
- faraday_middleware
8
- semantic
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- addressable (2.8.4)
14
- public_suffix (>= 2.0.2, < 6.0)
15
- ast (2.4.2)
16
- better_errors (2.9.1)
17
- coderay (>= 1.0.0)
18
- erubi (>= 1.0.0)
19
- rack (>= 0.9.0)
20
- bigdecimal (1.4.4)
21
- binding_of_caller (0.8.0)
22
- debug_inspector (>= 0.0.1)
23
- capybara (3.39.0)
24
- addressable
25
- matrix
26
- mini_mime (>= 0.1.3)
27
- nokogiri (~> 1.8)
28
- rack (>= 1.6.0)
29
- rack-test (>= 0.6.3)
30
- regexp_parser (>= 1.5, < 3.0)
31
- xpath (~> 3.2)
32
- coderay (1.1.3)
33
- concurrent-ruby (1.1.10)
34
- debug_inspector (1.1.0)
35
- diff-lcs (1.5.0)
36
- dotenv (2.7.6)
37
- dry-cli (0.7.0)
38
- dry-configurable (0.11.6)
39
- concurrent-ruby (~> 1.0)
40
- dry-core (~> 0.4, >= 0.4.7)
41
- dry-equalizer (~> 0.2)
42
- dry-container (0.7.2)
43
- concurrent-ruby (~> 1.0)
44
- dry-configurable (~> 0.1, >= 0.1.3)
45
- dry-core (0.4.9)
46
- concurrent-ruby (~> 1.0)
47
- dry-equalizer (0.3.0)
48
- dry-initializer (1.4.1)
49
- dry-logic (0.4.2)
50
- dry-container (~> 0.2, >= 0.2.6)
51
- dry-core (~> 0.2)
52
- dry-equalizer (~> 0.2)
53
- dry-struct (0.3.1)
54
- dry-configurable (~> 0.1)
55
- dry-core (~> 0.3)
56
- dry-equalizer (~> 0.2)
57
- dry-types (~> 0.9, >= 0.9.0)
58
- ice_nine (~> 0.11)
59
- dry-types (0.11.1)
60
- concurrent-ruby (~> 1.0)
61
- dry-configurable (~> 0.1)
62
- dry-container (~> 0.3)
63
- dry-core (~> 0.2, >= 0.2.1)
64
- dry-equalizer (~> 0.2)
65
- dry-logic (~> 0.4, >= 0.4.0)
66
- inflecto (~> 0.0.0, >= 0.0.2)
67
- dry-validation (0.11.0)
68
- concurrent-ruby (~> 1.0)
69
- dry-configurable (~> 0.1, >= 0.1.3)
70
- dry-core (~> 0.2, >= 0.2.1)
71
- dry-equalizer (~> 0.2)
72
- dry-logic (~> 0.4, >= 0.4.0)
73
- dry-types (~> 0.11.0)
74
- erubi (1.10.0)
75
- faraday (1.10.3)
76
- faraday-em_http (~> 1.0)
77
- faraday-em_synchrony (~> 1.0)
78
- faraday-excon (~> 1.1)
79
- faraday-httpclient (~> 1.0)
80
- faraday-multipart (~> 1.0)
81
- faraday-net_http (~> 1.0)
82
- faraday-net_http_persistent (~> 1.0)
83
- faraday-patron (~> 1.0)
84
- faraday-rack (~> 1.0)
85
- faraday-retry (~> 1.0)
86
- ruby2_keywords (>= 0.0.4)
87
- faraday-em_http (1.0.0)
88
- faraday-em_synchrony (1.0.0)
89
- faraday-excon (1.1.0)
90
- faraday-httpclient (1.0.1)
91
- faraday-multipart (1.0.4)
92
- multipart-post (~> 2)
93
- faraday-net_http (1.0.1)
94
- faraday-net_http_persistent (1.2.0)
95
- faraday-patron (1.0.0)
96
- faraday-rack (1.0.0)
97
- faraday-retry (1.0.3)
98
- faraday_middleware (1.2.0)
99
- faraday (~> 1.0)
100
- gem-release (2.2.2)
101
- hanami (1.3.5)
102
- bundler (>= 1.6, < 3)
103
- concurrent-ruby (~> 1.0)
104
- dry-cli (~> 0.5)
105
- hanami-assets (~> 1.3)
106
- hanami-controller (~> 1.3, >= 1.3.3)
107
- hanami-helpers (~> 1.3)
108
- hanami-mailer (~> 1.3)
109
- hanami-router (~> 1.3)
110
- hanami-utils (~> 1.3)
111
- hanami-validations (>= 1.3, < 3)
112
- hanami-view (~> 1.3)
113
- hanami-assets (1.3.5)
114
- hanami-helpers (~> 1.3)
115
- hanami-utils (~> 1.3)
116
- tilt (~> 2.0, >= 2.0.2)
117
- hanami-controller (1.3.3)
118
- hanami-utils (~> 1.3)
119
- rack (~> 2.0)
120
- hanami-helpers (1.3.3)
121
- hanami-utils (~> 1.3)
122
- hanami-mailer (1.3.3)
123
- hanami-utils (~> 1.3)
124
- mail (~> 2.6)
125
- tilt (~> 2.0, >= 2.0.1)
126
- hanami-model (1.3.3)
127
- bigdecimal (~> 1.4)
128
- concurrent-ruby (~> 1.0)
129
- dry-logic (~> 0.4.2, < 0.5)
130
- dry-types (~> 0.11.0)
131
- hanami-utils (~> 1.3)
132
- rom (~> 3.3, >= 3.3.3)
133
- rom-repository (~> 1.4)
134
- rom-sql (~> 1.3, >= 1.3.5)
135
- hanami-router (1.3.2)
136
- hanami-utils (~> 1.3)
137
- http_router (= 0.11.2)
138
- rack (~> 2.0)
139
- hanami-utils (1.3.8)
140
- concurrent-ruby (~> 1.0)
141
- transproc (~> 1.0)
142
- hanami-validations (1.3.8)
143
- dry-configurable (<= 0.12)
144
- dry-logic (~> 0.4.2, < 0.5)
145
- dry-validation (~> 0.11, < 0.12)
146
- hanami-utils (~> 1.3)
147
- hanami-view (1.3.3)
148
- hanami-utils (~> 1.3)
149
- tilt (~> 2.0, >= 2.0.1)
150
- hanami-webconsole (0.1.0)
151
- better_errors (~> 2.4)
152
- binding_of_caller (~> 0.8)
153
- http_router (0.11.2)
154
- rack (>= 1.0.0)
155
- url_mount (~> 0.2.1)
156
- ice_nine (0.11.2)
157
- inflecto (0.0.2)
158
- mail (2.7.1)
159
- mini_mime (>= 0.1.1)
160
- matrix (0.4.2)
161
- method_source (1.0.0)
162
- mini_mime (1.1.2)
163
- multipart-post (2.3.0)
164
- nio4r (2.5.9)
165
- nokogiri (1.14.3-arm64-darwin)
166
- racc (~> 1.4)
167
- nokogiri (1.14.3-x86_64-linux)
168
- racc (~> 1.4)
169
- parallel (1.20.1)
170
- parser (3.1.2.0)
171
- ast (~> 2.4.1)
172
- pry (0.14.1)
173
- coderay (~> 1.1)
174
- method_source (~> 1.0)
175
- public_suffix (5.0.1)
176
- puma (6.3.1)
177
- nio4r (~> 2.0)
178
- racc (1.6.2)
179
- rack (2.2.7)
180
- rack-test (2.1.0)
181
- rack (>= 1.3)
182
- rainbow (3.1.1)
183
- rake (13.0.6)
184
- regexp_parser (2.8.0)
185
- rexml (3.2.5)
186
- rom (3.3.3)
187
- concurrent-ruby (~> 1.0)
188
- dry-core (~> 0.3)
189
- dry-equalizer (~> 0.2)
190
- dry-initializer (~> 1.3)
191
- dry-types (~> 0.9, >= 0.9.4)
192
- rom-mapper (~> 0.5, >= 0.5.1)
193
- rom-mapper (0.5.1)
194
- dry-core (~> 0.2, >= 0.2.3)
195
- dry-equalizer (~> 0.2)
196
- transproc (~> 1.0)
197
- rom-repository (1.4.0)
198
- dry-core (~> 0.3, >= 0.3.1)
199
- dry-struct (~> 0.3)
200
- rom (~> 3.3)
201
- rom-mapper (~> 0.5)
202
- rom-sql (1.3.5)
203
- dry-core (~> 0.3)
204
- dry-equalizer (~> 0.2)
205
- dry-types (~> 0.11.0)
206
- rom (~> 3.2, >= 3.2.2)
207
- sequel (~> 4.43)
208
- rspec (3.11.0)
209
- rspec-core (~> 3.11.0)
210
- rspec-expectations (~> 3.11.0)
211
- rspec-mocks (~> 3.11.0)
212
- rspec-core (3.11.0)
213
- rspec-support (~> 3.11.0)
214
- rspec-expectations (3.11.0)
215
- diff-lcs (>= 1.2.0, < 2.0)
216
- rspec-support (~> 3.11.0)
217
- rspec-mocks (3.11.1)
218
- diff-lcs (>= 1.2.0, < 2.0)
219
- rspec-support (~> 3.11.0)
220
- rspec-support (3.11.0)
221
- rubocop (1.12.1)
222
- parallel (~> 1.10)
223
- parser (>= 3.0.0.0)
224
- rainbow (>= 2.2.2, < 4.0)
225
- regexp_parser (>= 1.8, < 3.0)
226
- rexml
227
- rubocop-ast (>= 1.2.0, < 2.0)
228
- ruby-progressbar (~> 1.7)
229
- unicode-display_width (>= 1.4.0, < 3.0)
230
- rubocop-ast (1.4.1)
231
- parser (>= 2.7.1.5)
232
- ruby-progressbar (1.11.0)
233
- ruby2_keywords (0.0.5)
234
- semantic (1.6.1)
235
- sequel (4.49.0)
236
- shotgun (0.9.2)
237
- rack (>= 1.0)
238
- slim (4.1.0)
239
- temple (>= 0.7.6, < 0.9)
240
- tilt (>= 2.0.6, < 2.1)
241
- sqlite3 (1.4.2)
242
- temple (0.8.2)
243
- tilt (2.0.10)
244
- transproc (1.1.1)
245
- unicode-display_width (2.1.0)
246
- url_mount (0.2.1)
247
- rack
248
- xpath (3.2.0)
249
- nokogiri (~> 1.8)
250
-
251
- PLATFORMS
252
- arm64-darwin-21
253
- x86_64-linux
254
-
255
- DEPENDENCIES
256
- bundler
257
- capybara
258
- dotenv (~> 2.4)
259
- flagsmith!
260
- gem-release
261
- hanami (~> 1.3)
262
- hanami-model (~> 1.3)
263
- hanami-webconsole
264
- pry
265
- puma (~> 6.3)
266
- rake
267
- rspec
268
- rubocop
269
- shotgun
270
- slim
271
- sqlite3
272
-
273
- BUNDLED WITH
274
- 2.3.14
data/example/README.md DELETED
@@ -1,29 +0,0 @@
1
- # Flagsmith Basic Ruby Example
2
-
3
- This directory contains a basic Flask application which utilises Flagsmith. To run the example application, you'll
4
- need to go through the following steps:
5
-
6
- 1. Create an account, organisation and project on [Flagsmith](https://flagsmith.com)
7
- 2. Create a feature in the project called "secret_button"
8
- 3. Give the feature a value using the json editor as follows:
9
-
10
- ```json
11
- {"colour": "#ababab"}
12
- ```
13
-
14
- 4. Create a .env.local file from the template located in this directory with the environment key of one of the environments
15
- in flagsmith (This can be found on the 'settings' page accessed from the menu on the left under the chosen environment.)
16
- 5. From a terminal window, export those environment variables (either manually or by using `export $(cat .env)`)
17
- 6. Install dependencies:
18
- ```bash
19
- bundle install
20
- ```
21
- 7. Run the application:
22
- ```
23
- bundle exec hanami server
24
- ```
25
- 8. Browse to http://localhost:2300
26
-
27
- Now you can play around with the 'secret_button' feature in flagsmith, turn it on to show it and edit the colour in the
28
- json value to edit the colour of the button. You can also identify as a given user and then update the settings for the
29
- secret button feature for that user in the flagsmith interface to see the affect that has too.
data/example/Rakefile DELETED
@@ -1,9 +0,0 @@
1
- require 'rake'
2
- require 'hanami/rake_tasks'
3
-
4
- begin
5
- require 'rspec/core/rake_task'
6
- RSpec::Core::RakeTask.new(:spec)
7
- task default: :spec
8
- rescue LoadError
9
- end
@@ -1,162 +0,0 @@
1
- require 'hanami/helpers'
2
- require 'hanami/assets'
3
-
4
- require_relative '../../../lib/flagsmith'
5
-
6
- module Web
7
- class Application < Hanami::Application
8
- configure do
9
- root __dir__
10
-
11
- load_paths << %w[
12
- controllers
13
- views
14
- ]
15
-
16
- routes 'config/routes'
17
-
18
- layout :application # It will load Web::Views::ApplicationLayout
19
-
20
- templates 'templates'
21
-
22
- ##
23
- # ASSETS
24
- #
25
- assets do
26
- # In order to skip JavaScript compression comment the following line
27
- javascript_compressor :builtin
28
-
29
- # In order to skip stylesheet compression comment the following line
30
- stylesheet_compressor :builtin
31
- end
32
-
33
- ##
34
- # SECURITY
35
- #
36
-
37
- # X-Frame-Options is a HTTP header supported by modern browsers.
38
- # It determines if a web page can or cannot be included via <frame> and
39
- # <iframe> tags by untrusted domains.
40
- #
41
- # Web applications can send this header to prevent Clickjacking attacks.
42
- #
43
- # Read more at:
44
- #
45
- # * https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options
46
- # * https://www.owasp.org/index.php/Clickjacking
47
- #
48
- security.x_frame_options 'DENY'
49
-
50
- # X-Content-Type-Options prevents browsers from interpreting files as
51
- # something else than declared by the content type in the HTTP headers.
52
- #
53
- # Read more at:
54
- #
55
- # * https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-Content-Type-Options
56
- # * https://msdn.microsoft.com/en-us/library/gg622941%28v=vs.85%29.aspx
57
- # * https://blogs.msdn.microsoft.com/ie/2008/09/02/ie8-security-part-vi-beta-2-update
58
- #
59
- security.x_content_type_options 'nosniff'
60
-
61
- # X-XSS-Protection is a HTTP header to determine the behavior of the
62
- # browser in case an XSS attack is detected.
63
- #
64
- # Read more at:
65
- #
66
- # * https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
67
- # * https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-XSS-Protection
68
- #
69
- security.x_xss_protection '1; mode=block'
70
-
71
- # Content-Security-Policy (CSP) is a HTTP header supported by modern
72
- # browsers. It determines trusted sources of execution for dynamic
73
- # contents (JavaScript) or other web related assets: stylesheets, images,
74
- # fonts, plugins, etc.
75
- #
76
- # Web applications can send this header to mitigate Cross Site Scripting
77
- # (XSS) attacks.
78
- #
79
- # The default value allows images, scripts, AJAX, fonts and CSS from the
80
- # same origin, and does not allow any other resources to load (eg object,
81
- # frame, media, etc).
82
- #
83
- # Inline JavaScript is NOT allowed. To enable it, please use:
84
- # "script-src 'unsafe-inline'".
85
- #
86
- # Content Security Policy introduction:
87
- #
88
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/
89
- # * https://www.owasp.org/index.php/Content_Security_Policy
90
- # * https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29
91
- #
92
- # Inline and eval JavaScript risks:
93
- #
94
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful
95
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/#eval-too
96
- #
97
- # Content Security Policy usage:
98
- #
99
- # * http://content-security-policy.com/
100
- # * https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Using_Content_Security_Policy
101
- #
102
- # Content Security Policy references:
103
- #
104
- # * https://developer.mozilla.org/en-US/docs/Web/Security/CSP/CSP_policy_directives
105
- #
106
- security.content_security_policy %(
107
- form-action 'self';
108
- frame-ancestors 'self';
109
- base-uri 'self';
110
- default-src 'none';
111
- script-src 'self';
112
- connect-src 'self';
113
- img-src 'self' https: data:;
114
- style-src 'self' 'unsafe-inline' https:;
115
- font-src 'self';
116
- object-src 'none';
117
- plugin-types application/pdf;
118
- child-src 'self';
119
- frame-src 'self';
120
- media-src 'self'
121
- )
122
-
123
- ##
124
- # FRAMEWORKS
125
- #
126
-
127
- # Configure the code that will yield each time Web::Action is included
128
- # This is useful for sharing common functionality
129
- #
130
- # See: http://www.rubydoc.info/gems/hanami-controller#Configuration
131
- controller.prepare do
132
- # include MyAuthentication # included in all the actions
133
- # before :authenticate! # run an authentication before callback
134
- end
135
-
136
- # Configure the code that will yield each time Web::View is included
137
- # This is useful for sharing common functionality
138
- #
139
- # See: http://www.rubydoc.info/gems/hanami-view#Configuration
140
- view.prepare do
141
- include Hanami::Helpers
142
- include Web::Assets::Helpers
143
- end
144
- end
145
-
146
- ##
147
- # DEVELOPMENT
148
- #
149
- configure :development do
150
- # Don't handle exceptions, render the stack trace
151
- handle_exceptions false
152
- end
153
-
154
- ##
155
- # TEST
156
- #
157
- configure :test do
158
- # Don't handle exceptions, render the stack trace
159
- handle_exceptions false
160
- end
161
- end
162
- end
@@ -1 +0,0 @@
1
- get '/', to: 'home#index'
File without changes
@@ -1,32 +0,0 @@
1
- module Web
2
- module Controllers
3
- module Home
4
- class Index
5
- include Web::Action
6
-
7
- expose :identifier, :show_button, :button_color
8
-
9
- def call(params)
10
- @identifier = params.get(:flagsmith, :identifier)
11
-
12
- if @identifier.nil? || @identifier.blank?
13
- # Get the default flags for the current environment
14
- flags = $flagsmith.get_environment_flags
15
- @show_button = flags.is_feature_enabled("secret_button")
16
- @button_data = JSON.parse(flags.get_feature_value("secret_button"))["colour"]
17
- else
18
- trait_key = params.get(:flagsmith, :trait_key)
19
- trait_value = params.get(:flagsmith, :trait_value)
20
- traits = trait_key.nil? ? nil : { trait_key: trait_value }
21
-
22
- # Get the flags for an identity, including the provided trait which will be
23
- # persisted to the API for future requests.
24
- identity_flags = $flagsmith.get_identity_flags(identifier, traits)
25
- @show_button = identity_flags.is_feature_enabled('secret_button')
26
- @button_color = JSON.parse(identity_flags.get_feature_value('secret_button'))['colour']
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,7 +0,0 @@
1
- doctype html
2
- html
3
- head
4
- title Flagsmith Example
5
- body
6
- main[style="max-width: 768px; margin: auto; text-align: center"]
7
- = yield
@@ -1,10 +0,0 @@
1
- p
2
- ' Hello,
3
- = (identifier.nil? || identifier.blank?) ? 'World' : identifier
4
-
5
- = if show_button
6
- button[style="background-color: #{button_color}"] A secret button
7
-
8
- p
9
-
10
- = form
@@ -1,7 +0,0 @@
1
- module Web
2
- module Views
3
- class ApplicationLayout
4
- include Web::Layout
5
- end
6
- end
7
- end
@@ -1,29 +0,0 @@
1
- module Web
2
- module Views
3
- module Home
4
- class Index
5
- include Web::View
6
-
7
- def form
8
- form_for :flagsmith, '/', method: :get do
9
- h3 'Identify as a User'
10
- div style: 'margin-bottom: 1em;' do
11
- label :identifier
12
- text_field :identifier
13
- end
14
- p '... with an optional user trait'
15
- div style: 'margin-bottom: 1em;' do
16
- label :trait_key
17
- text_field :trait_key
18
- end
19
- div style: 'margin-bottom: 1em;' do
20
- label :trait_value
21
- text_field :trait_value
22
- end
23
- div { submit 'Identify!' }
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,2 +0,0 @@
1
- require_relative './environment'
2
- Hanami.boot
@@ -1,17 +0,0 @@
1
- require 'bundler/setup'
2
- require 'hanami/setup'
3
- require 'hanami/model'
4
- require_relative '../apps/web/application'
5
-
6
- Hanami.configure do
7
- mount Web::Application, at: '/'
8
-
9
- model do
10
- adapter :sql, ENV.fetch('DATABASE_URL')
11
- end
12
-
13
- environment :development do
14
- # See: https://guides.hanamirb.org/projects/logging
15
- logger level: :debug
16
- end
17
- end
File without changes
@@ -1,7 +0,0 @@
1
- $flagsmith = Flagsmith::Client.new(
2
- enable_local_evaluation: true,
3
- environment_refresh_interval_seconds: 60,
4
- default_flag_handler: lambda { |feature_name|
5
- Flagsmith::Flags::DefaultFlag.new(enabled: false, value: {}.to_json)
6
- }
7
- )
@@ -1,15 +0,0 @@
1
- require_relative './environment'
2
- workers 1
3
-
4
- threads_count = 1
5
- threads threads_count, threads_count
6
-
7
- preload_app!
8
-
9
- rackup DefaultRackup
10
- port 2300
11
- environment 'development'
12
-
13
- on_worker_boot do
14
- Hanami.boot
15
- end
data/example/config.ru DELETED
@@ -1,3 +0,0 @@
1
- require_relative 'config/environment'
2
-
3
- run Hanami.app
File without changes
File without changes
File without changes
@@ -1,12 +0,0 @@
1
- # Require this file for feature tests
2
- require_relative './spec_helper'
3
-
4
- require 'capybara'
5
- require 'capybara/rspec'
6
-
7
- RSpec.configure do |config|
8
- config.include RSpec::FeatureExampleGroup
9
-
10
- config.include Capybara::DSL, feature: true
11
- config.include Capybara::RSpecMatchers, feature: true
12
- end
@@ -1,103 +0,0 @@
1
- # Require this file for unit tests
2
- ENV['HANAMI_ENV'] ||= 'test'
3
-
4
- require_relative '../config/environment'
5
- Hanami.boot
6
- Hanami::Utils.require!("#{__dir__}/support")
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://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
68
- # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
- # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
70
- config.disable_monkey_patching!
71
-
72
- # This setting enables warnings. It's recommended, but in many cases may
73
- # be too noisy due to issues in dependencies.
74
- config.warnings = false
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
File without changes
@@ -1,8 +0,0 @@
1
- module RSpec
2
- module FeatureExampleGroup
3
- def self.included(group)
4
- group.metadata[:type] = :feature
5
- Capybara.app = Hanami.app
6
- end
7
- end
8
- end
File without changes
@@ -1,9 +0,0 @@
1
- RSpec.describe Web::Controllers::Home::Index, type: :action do
2
- let(:action) { described_class.new }
3
- let(:params) { Hash[] }
4
-
5
- it 'is successful' do
6
- response = action.call(params)
7
- expect(response[0]).to eq 200
8
- end
9
- end
File without changes
@@ -1,10 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe Web::Views::ApplicationLayout, type: :view do
4
- let(:layout) { Web::Views::ApplicationLayout.new({ format: :html }, "contents") }
5
- let(:rendered) { layout.render }
6
-
7
- it 'contains application name' do
8
- expect(rendered).to include('Web')
9
- end
10
- end
@@ -1,10 +0,0 @@
1
- RSpec.describe Web::Views::Home::Index, type: :view do
2
- let(:exposures) { Hash[format: :html] }
3
- let(:template) { Hanami::View::Template.new('apps/web/templates/home/index.html.slim') }
4
- let(:view) { described_class.new(template, exposures) }
5
- let(:rendered) { view.render }
6
-
7
- it 'exposes #format' do
8
- expect(view.format).to eq exposures.fetch(:format)
9
- end
10
- end