fino 1.0.3 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69285bc3c8b50977e454b0de3c9da140c18260acb43ee1f42f62f8a9288c3183
4
- data.tar.gz: 714affd74ca27f673cc0b1d80a2ba66f151f9e2723c7034331d64cb5b667c7ce
3
+ metadata.gz: a2820a64cf64defc88202ae9e9ee7140efe02246c812e33cfe6ce07877f68b9e
4
+ data.tar.gz: 6b2b9c1cf4ae0ac28ad60912e0a5026cf01901b3a6006c03ecf1f5550e3f0c80
5
5
  SHA512:
6
- metadata.gz: b1c18ff5d58af075601ee3df575a98d8ce56af98e0148d4d3debd5114f30ad1242786d9d8f37880e8ee4a2a40a880cf688fc807f88d227bc3ba3f40d3af5345d
7
- data.tar.gz: 6f4c003666bbce10a3fee68ee17efbdd9c506c8c3654ed6e58e12f7f2fc3804412431fa3934647d806198031fbab9712b8960e874cd795847ebd1f4b6871dd1c
6
+ metadata.gz: 76444316536ac50999142e41abba7dbc4939832a138fb6ad3bf06bf7fb1700b3007f842b874b513789dbeec101ab3c7110818e6f862bd58bd83be06e2cca9251
7
+ data.tar.gz: 3120460c8c7ee45f2be9f38e00dd12150a81e93d36b8bd7a932c16f73b2061e0d0c7c431d50431244cb2e66b9ee4faa11799d96b120716a1a29f0e5b4b68e8b3
data/README.md CHANGED
@@ -51,24 +51,26 @@ end
51
51
  ### Work with settings
52
52
 
53
53
  ```ruby
54
- Fino.value(:model, :openai) #=> "gpt-4o"
55
- Fino.value(:temperature, :openai) #=> 0.7
54
+ Fino.value(:model, at: :openai) #=> "gpt-4o"
55
+ Fino.value(:temperature, at: :openai) #=> 0.7
56
56
 
57
- Fino.set("gpt-5", :model, :openai)
58
- Fino.value(:model, :openai) #=> "gpt-5"
57
+ Fino.values(:model, :temperature, at: :openai) #=> ["gpt-4", 0.7]
58
+
59
+ Fino.set(model: "gpt-5", at: :openai)
60
+ Fino.value(:model, at: :openai) #=> "gpt-5"
59
61
  ```
60
62
 
61
63
  ### Manage settings via UI
62
64
 
63
65
  ```ruby
64
- gem "fino-ui"
66
+ gem "fino-rails"
65
67
  ```
66
68
 
67
- Mount Fino UI in your `config/routes.rb`:
69
+ Mount Fino Rails engine in your `config/routes.rb`:
68
70
 
69
71
  ```ruby
70
72
  Rails.application.routes.draw do
71
- mount Fino::UI::Engine, at: "/fino"
73
+ mount Fino::Rails::Engine, at: "/fino"
72
74
  end
73
75
  ```
74
76
 
@@ -5,18 +5,57 @@ class Fino::Cache::Memory
5
5
 
6
6
  def initialize(expires_in:)
7
7
  @hash = {}
8
- @expirator = Fino::Expirator.new(ttl: expires_in)
8
+ @expirator = Fino::Expirator.new(ttl: expires_in) if expires_in
9
9
  end
10
10
 
11
- def fetch(key, &)
12
- @hash.fetch(key, &)
11
+ def exist?(key)
12
+ hash.key?(key)
13
13
  ensure
14
- @expirator.when_ready do
15
- @hash.clear
16
- end
14
+ expire_if_needed
15
+ end
16
+
17
+ def read(key)
18
+ hash[key]
19
+ ensure
20
+ expire_if_needed
17
21
  end
18
22
 
19
23
  def write(key, value)
20
- @hash[key] = value
24
+ hash[key] = value
25
+ end
26
+
27
+ def fetch(key, &block)
28
+ hash.fetch(key) do
29
+ write(key, block.call)
30
+ end
31
+ ensure
32
+ expire_if_needed
33
+ end
34
+
35
+ def fetch_multi(keys, &block)
36
+ missing_keys = keys - hash.keys
37
+
38
+ if missing_keys.any?
39
+ results = block.call(missing_keys)
40
+
41
+ results.each do |key, value|
42
+ write(key, value)
43
+ end
44
+ end
45
+
46
+ hash.values_at(*keys)
47
+ ensure
48
+ expire_if_needed
49
+ end
50
+
51
+ private
52
+
53
+ attr_reader :hash, :expirator
54
+
55
+ def expire_if_needed
56
+ expirator&.when_ready do
57
+ Fino.logger.debug { "Expiring all cache entries" }
58
+ hash.clear
59
+ end
21
60
  end
22
61
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Fino::Configuration
4
- attr_reader :registry, :adapter_builder_block, :cache_builder_block
4
+ attr_reader :registry, :adapter_builder_block, :cache_builder_block, :pipeline_builder_block
5
5
 
6
6
  def initialize(registry)
7
7
  @registry = registry
@@ -15,6 +15,10 @@ class Fino::Configuration
15
15
  @cache_builder_block = block
16
16
  end
17
17
 
18
+ def pipeline(&block)
19
+ @pipeline_builder_block = block
20
+ end
21
+
18
22
  def settings(&)
19
23
  Fino::Registry::DSL.new(registry).instance_eval(&)
20
24
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Fino::Definition::Section
4
+ attr_reader :name, :options
5
+
6
+ def initialize(name:, **options)
7
+ @name = name
8
+ @options = options
9
+ end
10
+
11
+ def label
12
+ options.fetch(:label, name.to_s.capitalize)
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Fino::Definition::Setting
4
+ attr_reader :setting_name, :section_definition, :type, :options
5
+
6
+ def initialize(type:, setting_name:, section_definition: nil, **options)
7
+ @setting_name = setting_name
8
+ @section_definition = section_definition
9
+ @type = type
10
+ @options = options
11
+ end
12
+
13
+ def type_class # rubocop:disable Metrics/MethodLength
14
+ @type_class ||=
15
+ case type
16
+ when :string
17
+ Fino::Settings::String
18
+ when :integer
19
+ Fino::Settings::Integer
20
+ when :float
21
+ Fino::Settings::Float
22
+ when :boolean
23
+ Fino::Settings::Boolean
24
+ else
25
+ raise "Unknown type #{type}"
26
+ end
27
+ end
28
+
29
+ def default
30
+ return @default if defined?(@default)
31
+
32
+ @default = options[:default]
33
+ end
34
+
35
+ def description
36
+ options[:description]
37
+ end
38
+
39
+ def path
40
+ @path ||= [setting_name, section_definition&.name].compact
41
+ end
42
+
43
+ def key
44
+ @key ||= path.reverse.join("/")
45
+ end
46
+ end
data/lib/fino/library.rb CHANGED
@@ -7,49 +7,76 @@ class Fino::Library
7
7
  @configuration = configuration
8
8
  end
9
9
 
10
- def value(*setting_path)
11
- setting(*setting_path).value
10
+ def value(setting_name, at: nil)
11
+ setting(setting_name, at: at).value
12
12
  end
13
13
 
14
- def setting(*setting_path)
15
- pipeline.read(build_setting_definition(*setting_path))
14
+ def values(*setting_names, at: nil)
15
+ settings(*setting_names, at: at).map(&:value)
16
16
  end
17
17
 
18
- def all
19
- pipeline.read_multi(configuration.registry.setting_definitions)
18
+ def setting(setting_name, at: nil)
19
+ pipeline.read(build_setting_definition(setting_name, at: at))
20
20
  end
21
21
 
22
- def set(value, *setting_path)
23
- setting_definition = build_setting_definition(*setting_path)
22
+ def settings(*setting_names, at: Fino::EMPTINESS)
23
+ setting_definitions =
24
+ if setting_names.empty? && at.equal?(Fino::EMPTINESS)
25
+ configuration.registry.setting_definitions
26
+ elsif at.equal?(Fino::EMPTINESS)
27
+ setting_names.map { |name| build_setting_definition(name) }
28
+ elsif setting_names.empty?
29
+ configuration.registry.setting_definitions(at: at)
30
+ else
31
+ setting_names.map { |name| build_setting_definition(name, at: at) }
32
+ end
24
33
 
25
- pipeline.write(
26
- setting_definition.type_class.deserialize(value),
27
- setting_definition
28
- )
34
+ pipeline.read_multi(setting_definitions)
35
+ end
36
+
37
+ def set(**setting_names_to_values)
38
+ at = setting_names_to_values.delete(:at)
39
+
40
+ setting_names_to_values.each do |setting_name, value|
41
+ setting_definition = build_setting_definition(setting_name, at: at)
42
+
43
+ pipeline.write(
44
+ setting_definition,
45
+ setting_definition.type_class.deserialize(value)
46
+ )
47
+ end
48
+ end
49
+
50
+ def slice(**mapping)
51
+ setting_definitions = mapping.each_with_object([]) do |(section_name, setting_names), memo|
52
+ Array(setting_names).each do |setting_name|
53
+ memo << build_setting_definition(setting_name, at: section_name)
54
+ end
55
+ end
56
+
57
+ pipeline.read_multi(setting_definitions)
29
58
  end
30
59
 
31
60
  private
32
61
 
33
62
  attr_reader :configuration
34
63
 
35
- def build_setting_definition(*setting_path)
36
- configuration.registry.fetch(*setting_path)
64
+ def build_setting_definition(setting_name, at: nil)
65
+ configuration.registry.setting_definition(setting_name.to_s, at&.to_s)
37
66
  end
38
67
 
39
68
  def pipeline
40
- @pipeline ||= Fino::Pipeline.new.tap do |p|
41
- p.use Fino::Pipeline::Cache.new(cache) if cache
42
- p.use Fino::Pipeline::Adapter.new(adapter)
69
+ @pipeline ||= Fino::Pipeline.new(storage).tap do |p|
70
+ p.use Fino::Pipe::Cache, cache if cache
71
+ p.instance_exec(&configuration.pipeline_builder_block) if configuration.pipeline_builder_block
43
72
  end
44
73
  end
45
74
 
46
- def cache
47
- return @cache if defined?(@cache)
48
-
49
- @cache = configuration.cache_builder_block&.call
75
+ def storage
76
+ Fino::Pipe::Storage.new(configuration.adapter_builder_block.call)
50
77
  end
51
78
 
52
- def adapter
53
- @adapter ||= configuration.adapter_builder_block.call
79
+ def cache
80
+ defined?(@cache) ? @cache : @cache = configuration.cache_builder_block&.call
54
81
  end
55
82
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./version"
4
+
5
+ module Fino
6
+ module_function
7
+
8
+ def metadata(spec)
9
+ spec.metadata["source_code_uri"] = spec.homepage
10
+ spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
11
+ spec.metadata["rubygems_mfa_required"] = "true"
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Fino::Pipe::Cache
4
+ include Fino::Pipe
5
+
6
+ def initialize(pipe, cache)
7
+ super(pipe)
8
+ @cache = cache
9
+ end
10
+
11
+ def read(setting_definition)
12
+ cache.fetch(setting_definition.key) do
13
+ pipe.read(setting_definition)
14
+ end
15
+ end
16
+
17
+ def read_multi(setting_definitions)
18
+ cache.fetch_multi(setting_definitions.map(&:key)) do |missing_keys|
19
+ uncached_setting_definitions = setting_definitions.filter { |sd| missing_keys.include?(sd.key) }
20
+
21
+ missing_keys.zip(pipe.read_multi(uncached_setting_definitions))
22
+ end
23
+ end
24
+
25
+ def write(setting_definition, value)
26
+ pipe.write(setting_definition, value)
27
+
28
+ cache.write(
29
+ setting_definition.key,
30
+ setting_definition.type_class.build(setting_definition, value)
31
+ )
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :cache
37
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Fino::Pipeline::Adapter
3
+ class Fino::Pipe::Storage
4
+ include Fino::Pipe
5
+
4
6
  def initialize(adapter)
5
7
  @adapter = adapter
6
8
  end
data/lib/fino/pipe.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fino::Pipe
4
+ def initialize(pipe)
5
+ @pipe = pipe
6
+ end
7
+
8
+ def read(setting_definition)
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def read_multi(setting_definitions)
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def write(setting_definition, value)
17
+ raise NotImplementedError
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :pipe
23
+ end
data/lib/fino/pipeline.rb CHANGED
@@ -1,38 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Fino::Pipeline
4
- def initialize(pipes = [])
5
- @pipes = pipes
6
- end
4
+ extend Forwardable
7
5
 
8
- def use(pipe)
9
- @pipes << pipe
10
- end
6
+ def_delegators :pipeline, *Fino::Pipe.public_instance_methods
11
7
 
12
- def read(setting_definition)
13
- read_pipeline(setting_definition)
8
+ def initialize(storage, pipes = [])
9
+ @storage = storage
10
+ @pipes = pipes
11
+ @pipe_wrapper = ->(pipe) { pipe }
14
12
  end
15
13
 
16
- def read_multi(setting_definitions)
17
- @pipes.each do |pipe|
18
- settings = pipe.read_multi(setting_definitions)
19
- return settings if settings
20
- end
14
+ def use(pipe_class, *args, **kwargs, &block)
15
+ pipes << ->(pipe) { pipe_class.new(pipe, *args, **kwargs, &block) }
16
+ @pipeline = nil
21
17
  end
22
18
 
23
- def write(value, setting_definition)
24
- @pipes.each do |pipe|
25
- pipe.write(setting_definition, value)
26
- end
27
-
28
- value
19
+ def wrap(&block)
20
+ @pipe_wrapper = block
21
+ @pipeline = nil
29
22
  end
30
23
 
31
24
  private
32
25
 
33
- def read_pipeline(setting_definition, pipe_index = 0)
34
- @pipes[pipe_index]&.read(setting_definition) do
35
- read_pipeline(setting_definition, pipe_index + 1)
26
+ attr_reader :storage, :pipes, :pipe_wrapper
27
+
28
+ def pipeline
29
+ @pipeline ||= pipes.inject(pipe_wrapper.call(storage)) do |pipe, builder|
30
+ pipe_wrapper.call(builder.call(pipe))
36
31
  end
37
32
  end
38
33
  end
data/lib/fino/registry.rb CHANGED
@@ -3,17 +3,17 @@
3
3
  class Fino::Registry
4
4
  class DSL
5
5
  class SectionDSL
6
- def initialize(section_name, _options, registry)
7
- @section_name = section_name
6
+ def initialize(section_definition, registry)
7
+ @section_definition = section_definition
8
8
  @registry = registry
9
9
  end
10
10
 
11
11
  def setting(setting_name, type, **)
12
12
  @registry.register(
13
- Fino::SettingDefinition.new(
13
+ Fino::Definition::Setting.new(
14
14
  type: type,
15
15
  setting_name: setting_name,
16
- section_name: @section_name,
16
+ section_definition: @section_definition,
17
17
  **
18
18
  )
19
19
  )
@@ -26,7 +26,7 @@ class Fino::Registry
26
26
 
27
27
  def setting(setting_name, type, **)
28
28
  @registry.register(
29
- Fino::SettingDefinition.new(
29
+ Fino::Definition::Setting.new(
30
30
  type: type,
31
31
  setting_name: setting_name,
32
32
  **
@@ -35,7 +35,14 @@ class Fino::Registry
35
35
  end
36
36
 
37
37
  def section(section_name, options = {}, &)
38
- SectionDSL.new(section_name, options, @registry).instance_eval(&)
38
+ section_definition = Fino::Definition::Section.new(
39
+ name: section_name,
40
+ **options
41
+ )
42
+
43
+ @registry.register_section(section_definition)
44
+
45
+ SectionDSL.new(section_definition, @registry).instance_eval(&)
39
46
  end
40
47
  end
41
48
 
@@ -43,22 +50,45 @@ class Fino::Registry
43
50
 
44
51
  using Fino::Ext::Hash
45
52
 
46
- attr_reader :setting_definitions_by_path, :setting_definitions
53
+ attr_reader :setting_definitions, :section_definitions
47
54
 
48
55
  def initialize
49
- @setting_definitions_by_path = {}
50
56
  @setting_definitions = []
57
+ @setting_definitions_by_path = {}
58
+
59
+ @section_definitions = []
60
+ @section_definitions_by_name = {}
51
61
  end
52
62
 
53
- def fetch(*path)
54
- @setting_definitions_by_path.dig(*path.reverse).tap do |definition|
63
+ def setting_definition(*path)
64
+ @setting_definitions_by_path.dig(*path.compact.reverse).tap do |definition|
55
65
  raise UnknownSetting, "Unknown setting: #{path.compact.join('.')}" unless definition
56
66
  end
57
67
  end
58
68
 
69
+ def setting_definitions(at: Fino::EMPTINESS)
70
+ case at
71
+ when Fino::EMPTINESS
72
+ @setting_definitions
73
+ when nil
74
+ @setting_definitions.select { |d| d.section_definition.nil? }
75
+ else
76
+ @setting_definitions_by_path[at&.to_s]&.values || []
77
+ end
78
+ end
79
+
80
+ def section_definition(section_name)
81
+ @section_definitions_by_name[section_name.to_s]
82
+ end
83
+
59
84
  def register(setting_definition)
60
85
  @setting_definitions << setting_definition
61
86
 
62
- @setting_definitions_by_path.deep_set(setting_definition, *setting_definition.path)
87
+ @setting_definitions_by_path.deep_set(setting_definition, *setting_definition.path.map(&:to_s))
88
+ end
89
+
90
+ def register_section(section_definition)
91
+ @section_definitions << section_definition
92
+ @section_definitions_by_name.deep_set(section_definition, section_definition.name.to_s)
63
93
  end
64
94
  end
data/lib/fino/setting.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fino::Setting
4
- UNSET_VALUE = Object.new.freeze
5
-
6
4
  def self.included(base)
7
5
  base.extend(ClassMethods)
8
6
  end
@@ -19,7 +17,7 @@ module Fino::Setting
19
17
  def build(setting_definition, raw_value, *options)
20
18
  new(
21
19
  setting_definition,
22
- raw_value.equal?(UNSET_VALUE) ? setting_definition.options[:default] : deserialize(raw_value),
20
+ raw_value.equal?(Fino::EMPTINESS) ? setting_definition.options[:default] : deserialize(raw_value),
23
21
  *options
24
22
  )
25
23
  end
@@ -38,11 +36,42 @@ module Fino::Setting
38
36
  definition.setting_name
39
37
  end
40
38
 
39
+ def key
40
+ definition.key
41
+ end
42
+
43
+ def type
44
+ definition.type
45
+ end
46
+
47
+ def type_class
48
+ definition.type_class
49
+ end
50
+
51
+ def section_definition
52
+ definition.section_definition
53
+ end
54
+
41
55
  def section_name
42
- definition.section_name
56
+ definition.section_definition&.name
43
57
  end
44
58
 
45
59
  def default
46
60
  definition.default
47
61
  end
62
+
63
+ def description
64
+ definition.description
65
+ end
66
+
67
+ def inspect
68
+ attributes = [
69
+ "key=#{key.inspect}",
70
+ "type=#{type_class.inspect}",
71
+ "value=#{value.inspect}",
72
+ "default=#{default.inspect}"
73
+ ]
74
+
75
+ "#<#{self.class.name} #{attributes.join(', ')}>"
76
+ end
48
77
  end
@@ -9,7 +9,10 @@ class Fino::Settings::Boolean
9
9
  end
10
10
 
11
11
  def deserialize(raw_value)
12
- raw_value == "1"
12
+ case raw_value
13
+ when "1", 1, true, "true", "t", "yes", "y" then true
14
+ else false
15
+ end
13
16
  end
14
17
  end
15
18
  end
data/lib/fino/version.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fino
4
- VERSION = "1.0.3"
4
+ VERSION = "1.1.0"
5
+ REQUIRED_RUBY_VERSION = ">= 3.0.0"
5
6
  end
data/lib/fino.rb CHANGED
@@ -5,8 +5,8 @@ require "zeitwerk"
5
5
 
6
6
  module Fino
7
7
  module Configurable
8
- def configure(&)
9
- configuration.instance_eval(&)
8
+ def configure(&block)
9
+ configuration.instance_eval(&block)
10
10
  end
11
11
 
12
12
  private
@@ -21,8 +21,10 @@ module Fino
21
21
 
22
22
  def_delegators :library,
23
23
  :value,
24
+ :values,
24
25
  :setting,
25
- :all,
26
+ :settings,
27
+ :slice,
26
28
  :set
27
29
 
28
30
  module_function
@@ -35,6 +37,8 @@ module Fino
35
37
  extend Configurable
36
38
  extend SettingsAccessible
37
39
 
40
+ EMPTINESS = Object.new.freeze
41
+
38
42
  module_function
39
43
 
40
44
  def library
@@ -45,6 +49,20 @@ module Fino
45
49
  @registry ||= Fino::Registry.new
46
50
  end
47
51
 
52
+ def logger
53
+ @logger ||= begin
54
+ require "logger"
55
+
56
+ Logger.new($stdout).tap do |l|
57
+ l.progname = name
58
+ l.level = ENV.fetch("FINO_LOG_LEVEL", "info")
59
+ l.formatter = proc do |severity, datetime, progname, msg|
60
+ "[#{progname}] #{severity}: #{msg}\n"
61
+ end
62
+ end
63
+ end
64
+ end
65
+
48
66
  def root
49
67
  File.expand_path("..", __dir__)
50
68
  end
@@ -55,17 +73,19 @@ Zeitwerk::Loader.for_gem.tap do |l|
55
73
 
56
74
  l.ignore(
57
75
  [
58
- root_relative_path.call("lib/fino-ui.rb"),
59
- root_relative_path.call("lib/fino/ui.rb"),
60
- root_relative_path.call("lib/fino/ui/"),
76
+ # Fino Rails
77
+ root_relative_path.call("lib/fino-rails.rb"),
78
+ root_relative_path.call("lib/fino/rails.rb"),
79
+ root_relative_path.call("lib/fino/rails/"),
61
80
 
81
+ # Fino Redis
62
82
  root_relative_path.call("lib/fino-redis.rb"),
63
83
  root_relative_path.call("lib/fino/redis.rb"),
64
84
  root_relative_path.call("lib/fino/redis/"),
65
85
 
66
- root_relative_path.call("lib/fino/engine.rb")
86
+ # Other
87
+ root_relative_path.call("lib/fino/metadata.rb"),
88
+ root_relative_path.call("lib/fino/railtie.rb")
67
89
  ]
68
90
  )
69
91
  end.setup
70
-
71
- require "fino/engine" if defined?(Rails)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fino
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Egor Iskrenkov
@@ -30,44 +30,36 @@ extensions: []
30
30
  extra_rdoc_files: []
31
31
  files:
32
32
  - README.md
33
- - lib/fino-redis.rb
34
- - lib/fino-ui.rb
35
33
  - lib/fino.rb
36
34
  - lib/fino/adapter.rb
37
35
  - lib/fino/cache.rb
38
36
  - lib/fino/cache/memory.rb
39
- - lib/fino/cache/null.rb
40
37
  - lib/fino/configuration.rb
41
- - lib/fino/engine.rb
38
+ - lib/fino/definition/section.rb
39
+ - lib/fino/definition/setting.rb
42
40
  - lib/fino/error.rb
43
41
  - lib/fino/expirator.rb
44
42
  - lib/fino/ext/hash.rb
45
43
  - lib/fino/library.rb
44
+ - lib/fino/metadata.rb
45
+ - lib/fino/pipe.rb
46
+ - lib/fino/pipe/cache.rb
47
+ - lib/fino/pipe/storage.rb
46
48
  - lib/fino/pipeline.rb
47
- - lib/fino/pipeline/adapter.rb
48
- - lib/fino/pipeline/cache.rb
49
- - lib/fino/redis.rb
50
- - lib/fino/redis/adapter.rb
51
49
  - lib/fino/registry.rb
52
50
  - lib/fino/setting.rb
53
- - lib/fino/setting_definition.rb
54
51
  - lib/fino/settings/boolean.rb
55
52
  - lib/fino/settings/float.rb
56
53
  - lib/fino/settings/integer.rb
57
54
  - lib/fino/settings/section.rb
58
55
  - lib/fino/settings/string.rb
59
- - lib/fino/ui.rb
60
- - lib/fino/ui/app/controllers/fino/ui/application_controller.rb
61
- - lib/fino/ui/app/controllers/fino/ui/settings_controller.rb
62
- - lib/fino/ui/config/initializers/inflections.rb
63
- - lib/fino/ui/config/routes.rb
64
- - lib/fino/ui/engine.rb
65
56
  - lib/fino/version.rb
66
57
  homepage: https://github.com/eiskrenkov/fino
67
- licenses: []
58
+ licenses:
59
+ - MIT
68
60
  metadata:
69
- homepage_uri: https://github.com/eiskrenkov/fino
70
61
  source_code_uri: https://github.com/eiskrenkov/fino
62
+ bug_tracker_uri: https://github.com/eiskrenkov/fino/issues
71
63
  rubygems_mfa_required: 'true'
72
64
  rdoc_options: []
73
65
  require_paths:
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Fino::Cache::Null
4
- include Fino::Cache
5
-
6
- def fetch(_key)
7
- yield
8
- end
9
- end
data/lib/fino/engine.rb DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Fino::Engine < Rails::Engine
4
- isolate_namespace Fino
5
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Fino::Pipeline::Cache
4
- def initialize(cache)
5
- @cache = cache
6
- end
7
-
8
- def read(setting_definition, &)
9
- cache.fetch(setting_definition.key, &)
10
- end
11
-
12
- def read_multi(setting_definitions, &); end
13
-
14
- def write(setting_definition, value)
15
- cache.write(setting_definition.key, setting_definition.type_class.build(setting_definition, value))
16
- end
17
-
18
- private
19
-
20
- attr_reader :cache
21
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Fino::Redis::Adapter
4
- include Fino::Adapter
5
-
6
- DEFAULT_REDIS_NAMESPACE = "fino"
7
- VALUE_KEY = "v"
8
-
9
- def initialize(redis, namespace: DEFAULT_REDIS_NAMESPACE)
10
- @redis = redis
11
- @redis_namespace = namespace
12
- end
13
-
14
- def read(setting_definition)
15
- redis.hgetall(redis_key_for(setting_definition))
16
- end
17
-
18
- def write(setting_definition, value)
19
- redis.hset(redis_key_for(setting_definition), VALUE_KEY, setting_definition.type_class.serialize(value))
20
- end
21
-
22
- def read_multi(setting_definitions)
23
- keys = setting_definitions.map { |definition| redis_key_for(definition) }
24
-
25
- redis.pipelined do |pipeline|
26
- keys.each { |key| pipeline.hgetall(key) }
27
- end
28
- end
29
-
30
- def fetch_value_from(raw_adapter_data)
31
- raw_adapter_data.key?(VALUE_KEY) ? raw_adapter_data.delete(VALUE_KEY) : Fino::Setting::UNSET_VALUE
32
- end
33
-
34
- private
35
-
36
- attr_reader :redis, :redis_namespace
37
-
38
- def redis_key_for(setting_definition)
39
- "#{redis_namespace}:#{setting_definition.path.join(':')}"
40
- end
41
- end
data/lib/fino/redis.rb DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fino"
4
- require "redis"
5
-
6
- module Fino::Redis
7
- end
8
-
9
- require "fino/redis/adapter"
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Fino::SettingDefinition
4
- attr_reader :setting_name, :section_name, :type, :options
5
-
6
- def initialize(type:, setting_name:, section_name: nil, **options)
7
- @setting_name = setting_name
8
- @section_name = section_name
9
- @type = type
10
- @options = options
11
- end
12
-
13
- def type_class
14
- case type
15
- when :string
16
- Fino::Settings::String
17
- when :integer
18
- Fino::Settings::Integer
19
- when :float
20
- Fino::Settings::Float
21
- when :boolean
22
- Fino::Settings::Boolean
23
- else
24
- raise "Unknown type #{type}"
25
- end
26
- end
27
-
28
- def default
29
- options[:default]
30
- end
31
-
32
- def path
33
- @path ||= [setting_name, section_name].compact
34
- end
35
-
36
- def key
37
- path.join("_")
38
- end
39
- end
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Fino::UI::ApplicationController < ActionController::Base
4
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Fino::UI::SettingsController < Fino::UI::ApplicationController
4
- def index
5
- @settings = Fino.library.all
6
- end
7
-
8
- def edit
9
- setting_path = parse_setting_path(params[:key])
10
-
11
- @setting = Fino.setting(*setting_path)
12
- end
13
-
14
- def update
15
- begin
16
- # Parse the key to create the setting path
17
- setting_path = parse_setting_path(params[:key])
18
-
19
- # Update the setting using the correct API
20
- Fino.set(params[:value], *setting_path)
21
-
22
- redirect_to root_path, notice: "Setting updated successfully"
23
- rescue Fino::Registry::UnknownSetting
24
- redirect_to root_path, alert: "Setting not found"
25
- end
26
- end
27
-
28
- private
29
-
30
- def parse_setting_path(key)
31
- key.split('.').map(&:to_sym).reverse
32
- end
33
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ActiveSupport::Inflector.inflections(:en) do |inflect|
4
- inflect.acronym "UI"
5
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Fino::UI::Engine.routes.draw do
4
- root to: "settings#index"
5
-
6
- resources :settings, only: [:index, :edit, :update], param: :key, constraints: { key: /[^\/]+/ }
7
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fino-ui"
4
-
5
- class Fino::UI::Engine < Rails::Engine
6
- isolate_namespace Fino::UI
7
-
8
- paths["app"] << root.join("lib", "fino", "ui", "app")
9
- paths["config/initializers"] << root.join("lib", "fino", "ui", "config", "initializers")
10
-
11
- initializer "fino.ui.append_view_paths" do |_app|
12
- ActiveSupport.on_load :action_controller do
13
- prepend_view_path Fino::UI::Engine.root.join("lib", "fino", "ui", "app", "views")
14
- end
15
- end
16
-
17
- initializer "fino.ui.load_routes", before: :add_routing_paths do |app|
18
- custom_routes = root.join("lib", "fino", "ui", "config", "routes.rb")
19
- app.routes_reloader.paths << custom_routes.to_s
20
- end
21
- end
data/lib/fino/ui.rb DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fino"
4
-
5
- module Fino::UI
6
- end
7
-
8
- require "fino/ui/engine"
data/lib/fino-redis.rb DELETED
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fino/redis"
data/lib/fino-ui.rb DELETED
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fino/ui"