fino-solid 1.10.0 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d001f6bb38d131992464c9cdeab1e5927fd5a16623759459c7020b1c35d6664a
4
- data.tar.gz: 339ab6d35c8dc40ecd553f835f536eb74a6978375ed29943cf5c8905c9c812e2
3
+ metadata.gz: dab2e123b7d5d9d00d30db649e0c70230180f8f4239bf4e48b609a7ff7b92c9b
4
+ data.tar.gz: bf585a94289c2f70bf12d6222478aa6c4182e940b7d2474d8b61e3500d8df7dd
5
5
  SHA512:
6
- metadata.gz: 6f81641ee84473e0fb6262bfa41d6beefd0e2051eb8caf6fc15364198385324f162f395a959d6658791dd70b9dbc28de46259a561a7c08b7df90f7d04f7c0f54
7
- data.tar.gz: 53eef4644ef38aaa358cf40d9f2cbf5ed587800a5acb0e47b94cf09b8f51371d5cb5a34678385f691a524d2beda08ed5814e029ebbf0180cf63a6055299585c8
6
+ metadata.gz: b6504803c3963065069f690c30089cd76f5e08a2c6156bca88a798753f3b45f0bf9b2fc1ba5985e7f65f3dddda8a24ab97466710514f5e22a4be66a9b5fb5237
7
+ data.tar.gz: b2167cdbea48102228fef66fcf63cf0c4e30c38cca534c0a7784c487597e48801091e0eba9ba2173bb93ff3e8495718c140f7fe580063d4044e7018bc3944a75
data/README.md CHANGED
@@ -238,7 +238,7 @@ Fino.value(:model, at: :openai, for: "user_2") #=> "gpt-5"
238
238
 
239
239
  #### Experiment analysis
240
240
 
241
- Some Fino adapters support A/B testing analysis, e.g built-in Redis adapter
241
+ Fino adapters might support A/B testing analysis, both built-in `solid` and `redis` adapters do
242
242
 
243
243
  When you run an A/B test for a setting, fino automatically calculates variant based on a stable identifier you pass as
244
244
  a `for` option
@@ -416,6 +416,14 @@ end
416
416
  end
417
417
  ```
418
418
 
419
+ ## Development
420
+
421
+ To create and mugrate dummy app db to test solid adapter, do
422
+
423
+ ```bash
424
+ cd spec/dummy && bin/rails db:create db:migrate
425
+ ```
426
+
419
427
  ## Releasing
420
428
 
421
429
  `rake release`
@@ -37,7 +37,7 @@ module Fino
37
37
 
38
38
  Fino::Solid::Setting.upsert(
39
39
  { key: setting_definition.key, data: data },
40
- unique_by: :key
40
+ **unique_by_option(:key)
41
41
  )
42
42
  end
43
43
 
@@ -45,8 +45,8 @@ module Fino
45
45
  Fino::Solid::Setting.pluck(:key)
46
46
  end
47
47
 
48
- def clear(setting_key)
49
- Fino::Solid::Setting.where(key: setting_key).delete_all > 0
48
+ def clear(setting_key) # rubocop:disable Naming/PredicateMethod
49
+ Fino::Solid::Setting.where(key: setting_key).delete_all.positive?
50
50
  end
51
51
 
52
52
  def fetch_value_from(raw_adapter_data)
@@ -62,6 +62,36 @@ module Fino
62
62
  end
63
63
  end
64
64
 
65
+ def record_ab_testing_conversion(setting_definition, variant, scope, time)
66
+ Fino::Solid::Conversion.insert(
67
+ {
68
+ setting_key: setting_definition.key,
69
+ variant_id: variant.id,
70
+ scope: scope.to_s,
71
+ converted_at: time
72
+ },
73
+ **unique_by_option(:idx_fino_conversions_unique)
74
+ )
75
+ end
76
+
77
+ def read_ab_testing_conversions(setting_definition, variants)
78
+ rows =
79
+ Fino::Solid::Conversion
80
+ .where(setting_key: setting_definition.key, variant_id: variants.map(&:id))
81
+ .pluck(:variant_id, :scope, :converted_at)
82
+
83
+ grouped = rows.group_by(&:first)
84
+
85
+ variants.each_with_object({}) do |variant, memo|
86
+ entries = grouped.fetch(variant.id, [])
87
+ memo[variant] = entries.map { |_vid, scope, converted_at| [scope, (converted_at.to_f * 1000).to_i] }
88
+ end
89
+ end
90
+
91
+ def clear_ab_testing_conversions(setting_key)
92
+ Fino::Solid::Conversion.where(setting_key: setting_key).delete_all
93
+ end
94
+
65
95
  def fetch_raw_variants_from(raw_adapter_data)
66
96
  raw_adapter_data.each_with_object([]) do |(key, value), memo|
67
97
  next unless key.start_with?("#{VARIANT_PREFIX}/")
@@ -71,6 +101,18 @@ module Fino
71
101
  memo << { percentage: percentage.to_f, value: value }
72
102
  end
73
103
  end
104
+
105
+ private
106
+
107
+ def unique_by_option(constraint)
108
+ return {} if mysql_adapter?
109
+
110
+ { unique_by: constraint }
111
+ end
112
+
113
+ def mysql_adapter?
114
+ Fino::Solid::Record.connection.adapter_name.match?(/Mysql2|Trilogy/i)
115
+ end
74
116
  end
75
117
  end
76
118
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fino
4
+ module Solid
5
+ class Conversion < Record
6
+ self.table_name = "fino_ab_testing_conversions"
7
+ end
8
+ end
9
+ end
@@ -1,8 +1,9 @@
1
1
  Description:
2
- Installs Fino::Solid adapter by creating necessary database migration.
2
+ Installs Fino::Solid adapter by creating necessary database migrations.
3
3
 
4
4
  Example:
5
5
  bin/rails generate fino:solid:install
6
6
 
7
7
  This will create:
8
8
  db/migrate/[timestamp]_create_fino_settings.rb
9
+ db/migrate/[timestamp]_create_fino_ab_testing_conversions.rb
@@ -11,8 +11,10 @@ module Fino
11
11
 
12
12
  source_root File.expand_path("templates", __dir__)
13
13
 
14
- def copy_migration
14
+ def copy_migrations
15
15
  migration_template "create_fino_settings.rb.tt", File.join(db_migrate_path, "create_fino_settings.rb")
16
+ migration_template "create_fino_ab_testing_conversions.rb.tt",
17
+ File.join(db_migrate_path, "create_fino_ab_testing_conversions.rb")
16
18
  end
17
19
 
18
20
  private
@@ -0,0 +1,17 @@
1
+ class CreateFinoAbTestingConversions < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :fino_ab_testing_conversions do |t|
4
+ t.string :setting_key, null: false
5
+ t.string :variant_id, null: false
6
+ t.string :scope, null: false
7
+ t.datetime :converted_at, null: false
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :fino_ab_testing_conversions, %i[setting_key variant_id scope],
13
+ unique: true, name: :idx_fino_conversions_unique
14
+ add_index :fino_ab_testing_conversions, %i[setting_key variant_id],
15
+ name: :idx_fino_conversions_lookup
16
+ end
17
+ end
data/lib/fino/solid.rb CHANGED
@@ -16,6 +16,7 @@ end
16
16
 
17
17
  require "fino/solid/record"
18
18
  require "fino/solid/setting"
19
+ require "fino/solid/conversion"
19
20
  require "fino/solid/adapter"
20
21
  require "fino/solid/railtie" if defined?(Rails::Railtie)
21
22
 
data/lib/fino/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fino
4
- VERSION = "1.10.0"
4
+ VERSION = "1.11.1"
5
5
  REQUIRED_RUBY_VERSION = ">= 3.2.0"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fino-solid
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Egor Iskrenkov
@@ -29,56 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 1.10.0
32
+ version: 1.11.1
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 1.10.0
40
- - !ruby/object:Gem::Dependency
41
- name: mysql2
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: '0.5'
47
- type: :development
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '0.5'
54
- - !ruby/object:Gem::Dependency
55
- name: pg
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '1.0'
61
- type: :development
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: '1.0'
68
- - !ruby/object:Gem::Dependency
69
- name: sqlite3
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '1.4'
75
- type: :development
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: '1.4'
39
+ version: 1.11.1
82
40
  email:
83
41
  - egor@iskrenkov.me
84
42
  executables: []
@@ -91,8 +49,10 @@ files:
91
49
  - lib/fino/solid.rb
92
50
  - lib/fino/solid/README.md
93
51
  - lib/fino/solid/adapter.rb
52
+ - lib/fino/solid/conversion.rb
94
53
  - lib/fino/solid/generators/install/USAGE
95
54
  - lib/fino/solid/generators/install/install_generator.rb
55
+ - lib/fino/solid/generators/install/templates/create_fino_ab_testing_conversions.rb.tt
96
56
  - lib/fino/solid/generators/install/templates/create_fino_settings.rb.tt
97
57
  - lib/fino/solid/railtie.rb
98
58
  - lib/fino/solid/record.rb
@@ -119,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
79
  - !ruby/object:Gem::Version
120
80
  version: '0'
121
81
  requirements: []
122
- rubygems_version: 3.6.9
82
+ rubygems_version: 4.0.6
123
83
  specification_version: 4
124
84
  summary: ActiveRecord adapter for Fino settings engine
125
85
  test_files: []