blueprint_config 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cec591307b09bd72ebe07601ae537938479fa70561e82127a468b7e0028e4df8
4
- data.tar.gz: 4ac393929bbf592a95e4196cbb195cd7d463e80f4ba6df4fce8c99b74967e330
3
+ metadata.gz: c15d3fbdfef9100c4ea913ea334e54121af90b9a3d1a8ebebadf058e3e6332cb
4
+ data.tar.gz: 58bb317972ccb61b627973e957fc03f966d233312a45572b438e37ca61925c7f
5
5
  SHA512:
6
- metadata.gz: 17467c0fd7172bf30880be1a40c1564c7f4271df3f388537f31986682f950766cea2ef3969061d5e7e2f68b1935dcddc930bff9151815be09be6ffcc1cca6bc8
7
- data.tar.gz: 890305e747d5314fcd1d9fc13e0eeaec4d931930483ef39898f44df9105f17f5e4e191b5a1f76eb907bc00647668ceb42b2ded7dc6051c476e43fc37d458b200
6
+ metadata.gz: 9fc44988632c85c5d085b86fe6409577de935c781910d754edda255948e1a340951116fd130d0313c8a2390b837e47db3def437e4210fb566c00ebde60021e86
7
+ data.tar.gz: d070bfcbe59fa94f9720721c85d76b1d9074f9e55d78b6f2e1eb8164f88921c7237ee3a3d4c49327a9e5d8b596b33811e4d4c2d1bf56d74fa99ebbbe75dbbb83
@@ -11,11 +11,22 @@ module BlueprintConfig
11
11
  =======================================================================
12
12
  Settings table not found. Please add the configuration table by running:
13
13
 
14
- rails generate blueprint_config:install
15
- rake db:migrate
14
+ bundle exec rails generate blueprint_config:install
15
+ bundle exec rake db:migrate
16
16
  =======================================================================
17
17
  WARNING
18
18
 
19
+ MISSING_ATTRIBUTES_WARNING = <<-WARNING.gsub(/^ */, '')
20
+ =======================================================================
21
+ Settings table is missing required attributes: %s
22
+
23
+ You can create a migration and adjust it to your needs by running:
24
+ bundle exec rails generate blueprint_config:install
25
+ =======================================================================
26
+ WARNING
27
+
28
+ REQUIRED_ATTRIBUTES = %w[key value type updated_at].freeze
29
+
19
30
  def initialize(options = {})
20
31
  @options = options
21
32
  @updated_at = nil
@@ -26,23 +37,64 @@ module BlueprintConfig
26
37
 
27
38
  def load_keys
28
39
  @configured = true
40
+
41
+ return {} unless table_exist?
42
+ return {} unless has_required_attributes?
43
+
29
44
  update_timestamp
30
45
 
31
46
  data = Setting.all.map { |s| { s.key => s.parsed_value } }.reduce(:merge) || {}
32
47
  return data.transform_keys(&:to_sym) unless @options[:nest]
33
48
 
34
49
  nest_hash(data, @options[:nest_separator] || '.')
35
- rescue ::ActiveRecord::NoDatabaseError => e
50
+ rescue ::ActiveRecord::NoDatabaseError, ::ActiveRecord::ConnectionNotEstablished
36
51
  # database is not created yet
37
52
  @configured = false
38
53
  {}
39
54
  rescue ::ActiveRecord::StatementInvalid => e
40
55
  @configured = false
41
- Rails.logger.warn(e.message)
42
- Rails.logger.warn(MISSING_TABLE_WARNING)
56
+ unless @options[:silence_warnings]
57
+ puts "Failed to load seetings from database: #{e.message}"
58
+ Rails.logger.warn(e.message) if defined?(Rails)
59
+ end
43
60
  {}
44
61
  end
45
62
 
63
+ def table_exist?
64
+ Setting.reset_column_information
65
+ return true if Setting.table_exists?
66
+
67
+ @configured = false
68
+
69
+ unless @options[:silence_warnings]
70
+ puts MISSING_TABLE_WARNING
71
+ if defined?(Rails)
72
+ Rails.logger.warn(e.message)
73
+ Rails.logger.warn(MISSING_TABLE_WARNING)
74
+ end
75
+ end
76
+
77
+ false
78
+ end
79
+
80
+ def has_required_attributes?
81
+ Setting.reset_column_information
82
+ return true if REQUIRED_ATTRIBUTES - Setting.attribute_names == []
83
+
84
+ @configured = false
85
+
86
+ missing = (REQUIRED_ATTRIBUTES - Setting.attribute_names).join(', ')
87
+ unless @options[:silence_warnings]
88
+ puts MISSING_ATTRIBUTES_WARNING % missing
89
+ if defined?(Rails)
90
+ Rails.logger.warn(e.message)
91
+ Rails.logger.warn(MISSING_TABLE_WARNING)
92
+ end
93
+ end
94
+
95
+ false
96
+ end
97
+
46
98
  def update_timestamp
47
99
  @mutex.synchronize do
48
100
  @updated_at = Setting.maximum(:updated_at)
@@ -51,13 +103,18 @@ module BlueprintConfig
51
103
 
52
104
  def fresh?
53
105
  # if database is not create/configured yet - don't try to refresh settings from it
54
- return true if !@configured
106
+ return true unless @configured
55
107
  return true if @last_checked_at.present? && @last_checked_at > 1.second.ago
56
108
 
57
109
  @mutex.synchronize do
58
110
  @last_checked_at = Time.now
59
111
  end
60
- @updated_at.present? && @updated_at >= Setting.maximum(:updated_at)
112
+ max_updated_at = Setting.maximum(:updated_at)
113
+
114
+ # if there is no settings in the database - don't try to refresh settings from it'
115
+ return true if max_updated_at.blank?
116
+
117
+ @updated_at.present? && @updated_at >= max_updated_at
61
118
  end
62
119
  end
63
120
  end
@@ -16,7 +16,7 @@ module BlueprintConfig
16
16
  reload! unless backends&.fresh?
17
17
  config.#{method}(...)
18
18
  rescue KeyError => e
19
- raise KeyError, e.message, caller[1..], cause: nil
19
+ raise KeyError, e.message, caller[1..], cause: nil#{' '}
20
20
  end
21
21
  RUBY
22
22
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BlueprintConfig
4
- VERSION = '1.1.0'
4
+ VERSION = '1.3.0'
5
5
  end
@@ -9,14 +9,18 @@ require 'blueprint_config/backend_collection'
9
9
  module BlueprintConfig
10
10
  class << self
11
11
  attr_accessor :root, :env, :before_initialize, :after_initialize
12
- attr_writer :shortcut_name, :env_options
12
+ attr_writer :shortcut_name, :env_backend_options, :active_record_backend_options
13
13
 
14
14
  def shortcut_name
15
15
  @shortcut_name || 'AppConfig'
16
16
  end
17
17
 
18
- def env_options
19
- @env_options || {}
18
+ def env_backend_options
19
+ @env_backend_options ||= {}
20
+ end
21
+
22
+ def active_record_backend_options
23
+ @active_record_backend_options ||= { nest: true }
20
24
  end
21
25
 
22
26
  def define_shortcut
@@ -46,8 +50,6 @@ module BlueprintConfig
46
50
  end
47
51
  end
48
52
 
49
- BlueprintConfig.env_options ||= {}
50
-
51
53
  BlueprintConfig.before_initialize ||= proc do
52
54
  require 'blueprint_config/backend/credentials'
53
55
  require 'blueprint_config/backend/active_record'
@@ -55,17 +57,19 @@ BlueprintConfig.before_initialize ||= proc do
55
57
  BlueprintConfig.instance.init do |backends|
56
58
  backends.use :app, BlueprintConfig::Backend::YAML.new('config/app.yml')
57
59
  backends.use :credentials, BlueprintConfig::Backend::Credentials.new
58
- backends.use :env, BlueprintConfig::Backend::ENV.new(BlueprintConfig.env_options)
60
+ backends.use :env, BlueprintConfig::Backend::ENV.new(BlueprintConfig.env_backend_options)
59
61
  backends.use :app_local, BlueprintConfig::Backend::YAML.new('config/app.local.yml')
60
62
  end
61
63
  end
62
64
 
63
65
  BlueprintConfig.after_initialize ||= proc do
64
66
  BlueprintConfig.instance.refine do |backends|
67
+ ar_backend = BlueprintConfig::Backend::ActiveRecord.new(BlueprintConfig.active_record_backend_options)
68
+
65
69
  if backends[:env]
66
- backends.insert_after :env, :db, BlueprintConfig::Backend::ActiveRecord.new
70
+ backends.insert_after :env, :db, ar_backend
67
71
  else
68
- backends.push :db, BlueprintConfig::Backend::ActiveRecord.new
72
+ backends.push :db, ar_backend
69
73
  end
70
74
  end
71
75
  end
@@ -3,39 +3,119 @@
3
3
  require 'active_record'
4
4
  require 'blueprint_config/backend/active_record'
5
5
 
6
- ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
7
-
8
- ActiveRecord::Base.connection.create_table :settings do |t|
9
- t.string :key, null: false, index: { unique: true }
10
- t.integer :type, null: false, default: 0
11
- t.string :value
12
- t.timestamps
13
- end
14
-
15
6
  describe BlueprintConfig::Backend::ActiveRecord do
16
7
  let(:options) { {} }
17
8
  let(:subject) { described_class.new(options).load_keys }
18
- around do |example|
19
- ActiveRecord::Base.transaction do
9
+
10
+ context 'Database is correctly setup' do
11
+ around do |example|
12
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
13
+
14
+ ActiveRecord::Base.connection.create_table :settings do |t|
15
+ t.string :key, null: false, index: { unique: true }
16
+ t.integer :type, null: false, default: 0
17
+ t.string :value
18
+ t.timestamps
19
+ end
20
+
20
21
  BlueprintConfig::Setting.create(key: 'foo', type: :string, value: 'bar')
21
22
  BlueprintConfig::Setting.create(key: 'x', type: :integer, value: '1')
22
23
  BlueprintConfig::Setting.create(key: 'a.b', type: :string, value: '1')
23
24
 
24
25
  example.run
25
- raise ActiveRecord::Rollback
26
+ ActiveRecord::Base.remove_connection
27
+ end
28
+
29
+ context 'with default options' do
30
+ it 'loads all keys' do
31
+ expect(subject).to eq({ foo: 'bar', "a.b": '1', x: 1 })
32
+ end
33
+ end
34
+
35
+ context 'when nesting enabled' do
36
+ let(:options) { { nest: true } }
37
+ it 'loads all keys' do
38
+ expect(subject).to eq({ foo: 'bar', a: { b: '1' }, x: 1 })
39
+ end
26
40
  end
27
41
  end
28
42
 
29
- context 'with default options' do
30
- it 'loads all keys' do
31
- expect(subject).to eq({ foo: 'bar', "a.b": '1', x: 1 })
43
+ context 'Database is not configured' do
44
+ it 'returns empty hash' do
45
+ expect(subject).to eq({})
32
46
  end
33
47
  end
34
48
 
35
- context 'when nesting enabled' do
36
- let(:options) { { nest: true } }
37
- it 'loads all keys' do
38
- expect(subject).to eq({ foo: 'bar', a: { b: '1' }, x: 1 })
49
+ context 'Database does not have proper table' do
50
+ around do |example|
51
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
52
+
53
+ example.run
54
+ ActiveRecord::Base.remove_connection
55
+ end
56
+
57
+ it 'returns empty hash' do
58
+ expect(subject).to eq({})
59
+ end
60
+ it 'prints warning in console' do
61
+ expect { subject }.to output(a_string_including('blueprint_config:install'))
62
+ .to_stdout_from_any_process
63
+ end
64
+ context 'when silencing enabled' do
65
+ let(:options) { { silence_warnings: true } }
66
+ it 'prints nothing in console' do
67
+ expect { subject }.to_not output.to_stdout_from_any_process
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'Database does table does not have correct attributes' do
73
+ around do |example|
74
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
75
+ ActiveRecord::Base.connection.create_table :settings do |t|
76
+ t.string :alias, null: false, index: { unique: true }
77
+ t.integer :type, null: false, default: 0
78
+ t.string :string
79
+ end
80
+ BlueprintConfig::Setting.reset_column_information
81
+ BlueprintConfig::Setting.create(alias: 'foo', type: :string, string: 'bar')
82
+ BlueprintConfig::Setting.create(alias: 'x', type: :integer, string: '1')
83
+ BlueprintConfig::Setting.create(alias: 'a.b', type: :integer, string: '1')
84
+
85
+ example.run
86
+ ActiveRecord::Base.remove_connection
87
+ end
88
+
89
+ it 'returns empty hash' do
90
+ expect(subject).to eq({})
91
+ end
92
+ it 'prints warning in console' do
93
+ expect { subject }.to output(a_string_including('blueprint_config:install'))
94
+ .to_stdout_from_any_process
95
+ end
96
+ context 'when silencing enabled' do
97
+ let(:options) { { silence_warnings: true } }
98
+ it 'prints nothing in console' do
99
+ expect { subject }.to_not output.to_stdout_from_any_process
100
+ end
101
+ end
102
+ end
103
+
104
+ context 'Database does not have any records' do
105
+ around do |example|
106
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
107
+ ActiveRecord::Base.connection.create_table :settings do |t|
108
+ t.string :key, null: false, index: { unique: true }
109
+ t.integer :type, null: false, default: 0
110
+ t.string :value
111
+ t.timestamps
112
+ end
113
+ example.run
114
+ ActiveRecord::Base.remove_connection
115
+ end
116
+
117
+ it 'returns empty hash' do
118
+ expect(subject).to eq({})
39
119
  end
40
120
  end
41
121
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blueprint_config
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Elchinov
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-01-08 00:00:00.000000000 Z
12
+ date: 2024-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord