flagsmith 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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