ssm_config 0.1.1 → 1.1.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: 62ee2af26eb305962b5a1c4f019b5a16b847de0b5b4b482bb7c077c958a8cf32
4
- data.tar.gz: c7665892a5d0900d5923549dd9c08196adeb8fb854879f13f46e44a038158b25
3
+ metadata.gz: a7509632dfae2aa08f269331ae52ec1e645da5c3777a772721866147f4e25c46
4
+ data.tar.gz: 146883e2ee8cde2946de40d3ee49ba2ab1dc0f9ad529425a2970bf6bb0baf8ec
5
5
  SHA512:
6
- metadata.gz: ba9d0c438b9147d33d95ad07eee3224f05b1a77a4e3b930e15c476b98a1a4a38dfbad6797491e648c213f0ed231e22f11c59a2b84809c6424f05f6c078e4b58f
7
- data.tar.gz: 768c01d819f2af815c1788359870a3626257a39021129bc460b50850d9161f600d0de2c92ee0f52303af54523a845a3b2097bfd52c9cb8850999a62c6ebe7137
6
+ metadata.gz: c18bf507eda6a9f668325376d7ac0a28d0ceee717ef73909019493cb8b91aac3fc0c51e4eae8b60077674565b25fbd0505bab97f32588a5a6ed456bd8da395a9
7
+ data.tar.gz: 91bd9725e9ca01cc512c434db801998887fe248ed8720eeaab7e4cafde50a1d3cb2d8873700e2f5411c2e2c1f3a76457a74db801f05f22824451bc4ec7b056ef
data/.gitignore CHANGED
@@ -10,3 +10,6 @@
10
10
 
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
+ .DS_Store
14
+ ./spec/rails_app/log/**
15
+
data/.rubocop.yml ADDED
@@ -0,0 +1,13 @@
1
+ require:
2
+ - rubocop-rspec
3
+ - rubocop-rails
4
+
5
+ inherit_gem:
6
+ snap-style:
7
+ - "rubocop/rubocop.yml"
8
+
9
+ Security/YAMLLoad:
10
+ Enabled: false
11
+
12
+ Metrics/BlockLength:
13
+ Max: 100
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.6.7
data/Gemfile CHANGED
@@ -2,3 +2,17 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in ssm_config.gemspec
4
4
  gemspec
5
+
6
+ group :development, :test do
7
+ gem 'pry-byebug'
8
+ gem 'rubocop', '~> 0.92', :require => false
9
+ gem 'rubocop-rails', :require => false
10
+ gem 'rubocop-rspec', :require => false
11
+ gem 'timecop'
12
+ end
13
+
14
+ source 'https://rubygems.pkg.github.com/bodyshopbidsdotcom' do
15
+ group :development do
16
+ gem 'snap-style'
17
+ end
18
+ end
data/README.md CHANGED
@@ -1,9 +1,13 @@
1
1
  # SsmConfig
2
2
 
3
- Any config YAML in the config directory can be accessed by calling `SsmConfig.config_name`.
4
- For example, if you wish to access `config/foo.yml`, just call `SsmConfig.foo` from anywhere in the app. The YAML will be parsed
5
- into a hash.
6
-
3
+ * ActiveRecord
4
+ - Any file in ActiveRecord with model name `SsmConfigRecord` can be accessed by calling `SsmConfig.file_name`
5
+ - All rows with the corresponding file name will be parsed into a hash
6
+ * `config` directory
7
+ - If file is not found in `SsmConfigRecord` (or the ActiveRecord doesn't exist), `SsmConfig` looks in the `config` directory
8
+ - Any YAML file in the directory with the corresponding file name will be parsed into a hash
9
+
10
+ These two are exclusive, with the former prioritized: i.e., the gem will look in the ActiveRecord model first, and then in the `config` directory if no such file is found.
7
11
  ## Installation
8
12
 
9
13
  Add this line to your application's Gemfile:
@@ -20,27 +24,78 @@ Or install it yourself as:
20
24
 
21
25
  $ gem install ssm_config
22
26
 
27
+ ## Setup
28
+
29
+ To utilize ActiveRecords, create the following model:
30
+ ```
31
+ rails generate model SsmConfigRecord file:string:index accessor_keys:string value:string datatype:string
32
+ ```
33
+
34
+ The supported datatypes are `[string, integer, boolean, float]`. The field `datatype` should contain the character that corresponds to the first character of the datatype (so one of `[s, i, b, f]`). This field is not case-sensitive (the gem also only checks the first character of `datatype`). Booleans should also be one of `[t, f]`, corresponding to `true` and `false`. Similarly, this is not case-sensitive and only the first character of the value (given the datatype is a boolean) will be checked.
35
+
36
+ An invalid entry will throw an exception (as well as an invalid boolean entry).
37
+
38
+ When migrating a file to the ActiveRecord, it is important to correctly input the accessor keys. The field `accessor_keys` represents a hashkey corresponding to a value in the hash: for the sequence of keys used to access a value, the corresponding accessor key will be the keys concatentated with a comma delimiter. For example, if `hash[:key1][:key2][:key3] = value`, the corresponding accessor key would be the string `"key1,key2,key3"`. In the case that there is an array, we include the index embraced by brackets. Consider the following hash:
39
+
40
+ ```yml
41
+ any:
42
+ build:
43
+ docker:
44
+ - image: value1
45
+ steps:
46
+ - value2
47
+ - run: value3
48
+ ```
49
+ The accessor keys for `value1`, `value2`, and `value3` would be `"build,docker,[0],image"`, `"build,steps,[0]"`, and `"build,steps,[1],run"`, respectively.
50
+
51
+ ⚠️ **NOTE:** ⚠️ There should be no file name called `cache`, as this will call a method of the `SsmConfig` class. Also, all values read from the table will be strings.
23
52
  ## Usage
24
53
 
25
- Given `config/eft.yml`:
54
+
55
+ Given the following rows in `SsmConfigRecord`:
56
+
57
+ | file | accessor_keys | value |
58
+ | :---: | :------------: | :---: |
59
+ | eft | days_to_enter_bank_account,default | 3 |
60
+ | eft | days_to_enter_bank_account,company1,[0] | 2 |
61
+ | eft | days_to_enter_bank_account,company2 | 4|
62
+
63
+ ```ruby
64
+ SsmConfig.eft
65
+ => {"days_to_enter_bank_account"=>{"default"=>3, "company1"=>[2], "company2"=>4}}
66
+ ```
67
+ `SsmConfig` will always reconstruct the hash using all the rows with the corresponding file name. In the case that no such row exists, `SsmConfig` will look for `config/foo.yml`. For example, given `config/eft.yml`,
68
+
26
69
  ```yml
27
70
  any:
28
71
  days_to_enter_bank_account:
29
72
  default: 3
30
- company1: 2
73
+ company1:
74
+ - 2
31
75
  company2: 4
32
76
  ```
33
-
34
77
  ```ruby
35
78
  SsmConfig.eft
36
- => {"days_to_enter_bank_account"=>{"default"=>3, "company1"=>2, "company2"=>4}}
79
+ => {"days_to_enter_bank_account"=>{"default"=>3, "company1"=>[2], "company2"=>4}}
37
80
  ```
38
81
 
82
+ This search will be exclusive: i.e., if any row exists in the table then the gem will not look in `config`.
39
83
  ## Development
40
84
 
41
85
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
42
86
 
43
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
87
+ To install this gem onto your local machine, run `bundle exec rake install`.
88
+
89
+ To develop and test locally, include a path for your gem in the Gemfile of the desired application, i.e.,
90
+ ```
91
+ gem 'ssm_config', path: 'path'
92
+ ```
93
+
94
+ ## Release to RubyGems
95
+
96
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
97
+ To do so, you need a RubyGems account and [to be listed as an owner](https://rubygems.org/gems/ssm_config/owners).
98
+ In the process, after pushing the tag, the console will hang. You will need to enter your RubyGems login and then its password.
44
99
 
45
100
  ## Contributing
46
101
 
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require File.expand_path('../spec/rails_app/config/application', __FILE__)
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
6
  task :default => :spec
7
+ # YouApp::Application.load_tasks
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "ssm_config"
3
+ require 'bundler/setup'
4
+ require 'ssm_config'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,6 @@ require "ssm_config"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
+ require 'byebug'
14
15
  IRB.start(__FILE__)
@@ -0,0 +1,13 @@
1
+ module SsmConfig
2
+ # Generic SsmConfig exception.
3
+ class Error < StandardError
4
+ end
5
+
6
+ # An unexpected option, perhaps a typo, was passed to the value in the case of a boolean datatype
7
+ class InvalidBoolean < Error
8
+ end
9
+
10
+ # The datatype entered is unsupported in SsmConfigRecord
11
+ class UnsupportedDatatype < Error
12
+ end
13
+ end
@@ -0,0 +1,93 @@
1
+ module SsmConfig
2
+ module SsmStorage
3
+ class Db
4
+ TABLE_NAME = 'ssm_config_records'.freeze
5
+ ACTIVE_RECORD_MODEL = 'SsmConfigRecord'.freeze
6
+ def initialize(file_name)
7
+ @file_name = file_name
8
+ end
9
+
10
+ def table_exists?
11
+ return active_record_model_exists? if active_record_exists? && constant_exists?
12
+ false
13
+ end
14
+
15
+ def hash
16
+ match_file = ACTIVE_RECORD_MODEL.constantize.where(:file => @file_name.to_s).order(:accessor_keys)
17
+ hashes = match_file.each_with_object({}) { |row, hash| hash[row.accessor_keys] = transform_class(row.value, row.datatype); }
18
+ insert_arrays(reconstruct_hash(hashes)).try(:with_indifferent_access)
19
+ end
20
+
21
+ private
22
+
23
+ def active_record_exists?
24
+ ActiveRecord::Base.connection.table_exists? TABLE_NAME
25
+ end
26
+
27
+ def active_record_model_exists?
28
+ ACTIVE_RECORD_MODEL.constantize.exists?(:file => @file_name.to_s)
29
+ end
30
+
31
+ def constant_exists?
32
+ Object.const_defined? ACTIVE_RECORD_MODEL
33
+ end
34
+
35
+ def convert_boolean(value)
36
+ value = value.to_s.downcase
37
+ return true if value[0] == 't'
38
+ return false if value[0] == 'f'
39
+ raise SsmConfig::InvalidBoolean, 'Not a valid boolean: must be one of true or false'
40
+ end
41
+
42
+ def transform_class(value, type)
43
+ possible_types = ['s', 'i', 'b', 'f']
44
+ raise SsmConfig::UnsupportedDatatype, 'Not a valid class: must be one of string, integer, boolean, or float' unless possible_types.include? type.to_s.downcase[0]
45
+ return value.send("to_#{type.to_s.downcase[0]}") unless type[0] == 'b'
46
+ convert_boolean(value)
47
+ end
48
+
49
+ def add_flag_for_array_index(key)
50
+ return "#{key}flag" if key[0] == '['
51
+ key
52
+ end
53
+
54
+ # given a hash from hashkey (sequence of keys delimited by comma) to value, reconstruct hash
55
+ # arrays will not be formed properly, see insert_arrays
56
+ def reconstruct_hash(hash)
57
+ hash.each_with_object({}) do |(key, value), final_hash| # key will represent sequence of keys needed to get down to value
58
+ curr_hash = final_hash
59
+ delimited = key.split(',')
60
+ delimited[0..-2].each do |curr_key|
61
+ curr_key = add_flag_for_array_index(curr_key) # if bracket, indicates array index, add a flag indicating this is for an array index, and not some key name that had a bracket in it
62
+ curr_hash[curr_key] = {} unless curr_hash.key?(curr_key) # if key doesn't exist, initialize it
63
+ curr_hash = curr_hash[curr_key] # move into next level of hash
64
+ end
65
+ curr_hash[add_flag_for_array_index(delimited[-1])] = value # insert value
66
+ end
67
+ end
68
+
69
+ def array_index_flagged?(hash)
70
+ hash.all? do |key, _value|
71
+ key[0] == '[' && key[-4..-1] == 'flag'
72
+ end
73
+ end
74
+
75
+ # reconstruct_hash is unable to create arrays where needed, so parse through
76
+ # result and convert to arrays where needed
77
+ def insert_arrays(hash)
78
+ return hash unless hash.class == Hash
79
+ return hash if hash.keys.size.zero? # if there are no keys, return
80
+ if array_index_flagged?(hash) # if key has bracket + flag, it is an array index
81
+ hash = hash.values # convert hash to just the array of values
82
+ hash.each_with_index do |element, index|
83
+ hash[index] = insert_arrays(element) # recurse on each value
84
+ end
85
+ else # no change needed, recurse on next level of hash
86
+ hash.each do |key, value|
87
+ hash[key] = insert_arrays(value)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,9 @@
1
+ module SsmConfig
2
+ module SsmStorage
3
+ class Empty
4
+ def hash
5
+ {}
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module SsmConfig
2
+ module SsmStorage
3
+ class Yml
4
+ CONFIG_PATH = 'config'.freeze
5
+ def initialize(file_name)
6
+ @file_name = file_name
7
+ end
8
+
9
+ def file_exists?
10
+ File.exist?(file_path)
11
+ end
12
+
13
+ def hash
14
+ yaml_loaded = YAML.load(ERB.new(File.read((file_path).to_s)).result)
15
+ (yaml_loaded[Rails.env] || yaml_loaded['any']).try(:with_indifferent_access)
16
+ end
17
+
18
+ private
19
+
20
+ def file_path
21
+ Rails.root.join(CONFIG_PATH, "#{@file_name}.yml")
22
+ end
23
+ end
24
+ end
25
+ end
data/lib/ssm_config.rb CHANGED
@@ -1,37 +1,56 @@
1
- class SsmConfig
2
- VERSION = "0.1.1"
1
+ require './lib/ssm_config/ssm_storage/db.rb'
2
+ require './lib/ssm_config/ssm_storage/yml.rb'
3
+ require './lib/ssm_config/ssm_storage/empty.rb'
4
+ require 'active_support/core_ext/hash/indifferent_access'
5
+ require 'active_support/time'
6
+ require './lib/ssm_config/errors.rb'
3
7
 
4
- class << self
8
+ module SsmConfig
9
+ VERSION = '1.1.0'.freeze
10
+ REFRESH_TIME = (30.minutes).freeze
5
11
 
12
+ class << self
6
13
  def method_missing(meth, *args, &block)
7
- config_file = Rails.root.join('config', "#{meth}.yml")
14
+ result = populate(meth)
15
+ super if result == false
16
+ result
17
+ end
8
18
 
9
- if File.exists?(config_file)
10
- write_config_accessor_for(meth)
11
- self.send(meth)
12
- else
13
- super
14
- end
19
+ def respond_to_missing?(meth, *_args)
20
+ determine_query(meth).present?
21
+ end
22
+
23
+ def last_processed_time
24
+ @last_processed_time ||= ActiveSupport::HashWithIndifferentAccess.new
15
25
  end
16
26
 
17
27
  private
18
28
 
19
- def parse_config_file(filename)
20
- YAML.load(ERB.new(File.read("#{Rails.root}/config/#{filename}")).result).symbolize_keys
29
+ def determine_query(meth)
30
+ query_database = SsmConfig::SsmStorage::Db.new(meth)
31
+ query_yml = SsmConfig::SsmStorage::Yml.new(meth)
32
+ return query_database if query_database.table_exists?
33
+ return query_yml if query_yml.file_exists?
34
+ nil
21
35
  end
22
36
 
23
- def parse_config_file_with_env(filename)
24
- yaml_loaded = YAML.load(ERB.new(File.read("#{Rails.root}/config/#{filename}")).result)
25
- (yaml_loaded[Rails.env] || yaml_loaded['any']).try(:with_indifferent_access)
37
+ def populate(meth)
38
+ query = determine_query(meth)
39
+
40
+ return false if query.blank?
41
+ self.last_processed_time[meth] = Time.zone.now
42
+ write_config_accessor_for(meth) unless method_defined?(meth.to_sym)
43
+ instance_variable_set("@#{meth}".to_sym, nil)
44
+ self.send(meth, query)
26
45
  end
27
46
 
28
47
  def write_config_accessor_for(meth)
29
- self.instance_eval %Q{
30
- def #{meth}
31
- @#{meth} ||= parse_config_file_with_env('#{meth}.yml')
32
- end
33
- }
48
+ self.instance_eval %{
49
+ def #{meth}(obj = SsmConfig::SsmStorage::Empty.new)
50
+ return self.send(:populate, "#{meth}") if self.last_processed_time["#{meth}".to_sym] < Time.zone.now - REFRESH_TIME
51
+ @#{meth} ||= obj&.hash
52
+ end
53
+ }, __FILE__, __LINE__ - 5
34
54
  end
35
-
36
55
  end
37
56
  end
data/ssm_config.gemspec CHANGED
@@ -1,34 +1,36 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'ssm_config'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "ssm_config"
6
+ spec.name = 'ssm_config'
8
7
  spec.version = SsmConfig::VERSION
9
- spec.authors = ["Santiago Herrera"]
10
- spec.email = ["santiago@snapsheet.me"]
8
+ spec.authors = ['Santiago Herrera']
9
+ spec.email = ['santiago@snapsheet.me']
11
10
 
12
- spec.summary = %q{YML file loader and parser for Rails}
13
- spec.homepage = "https://github.com/bodyshopbidsdotcom/ssm_config"
14
- spec.license = "MIT"
11
+ spec.summary = 'YML file loader and parser for Rails'
12
+ spec.homepage = 'https://github.com/bodyshopbidsdotcom/ssm_config'
13
+ spec.license = 'MIT'
15
14
 
16
15
  if spec.respond_to?(:metadata)
17
- spec.metadata['allowed_push_host'] = "https://rubygems.org"
16
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
18
17
  else
19
- raise "RubyGems 2.0 or newer is required to protect against " \
20
- "public gem pushes."
18
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
19
+ 'public gem pushes.'
21
20
  end
22
21
 
23
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
22
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
24
23
  f.match(%r{^(test|spec|features)/})
25
24
  end
26
- spec.bindir = "exe"
25
+ spec.bindir = 'exe'
27
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
- spec.require_paths = ["lib"]
27
+ spec.require_paths = ['lib']
29
28
 
30
- spec.add_development_dependency "bundler", "~> 1.14"
31
- spec.add_development_dependency "rake", "~> 10.0"
32
- spec.add_development_dependency "rspec", "~> 3.0"
33
- spec.add_dependency "rails", ">= 3", "< 7"
29
+ spec.add_development_dependency 'bundler', '~> 1.14'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rspec', '~> 3.0'
32
+ spec.add_development_dependency 'rspec-rails'
33
+ spec.add_dependency 'rails', '>= 3', '< 7'
34
+ spec.add_development_dependency 'sqlite3', '1.4'
35
+ spec.required_ruby_version = '>=2.6'
34
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ssm_config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Santiago Herrera
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-15 00:00:00.000000000 Z
11
+ date: 2023-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rails
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +86,20 @@ dependencies:
72
86
  - - "<"
73
87
  - !ruby/object:Gem::Version
74
88
  version: '7'
89
+ - !ruby/object:Gem::Dependency
90
+ name: sqlite3
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '='
94
+ - !ruby/object:Gem::Version
95
+ version: '1.4'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '='
101
+ - !ruby/object:Gem::Version
102
+ version: '1.4'
75
103
  description:
76
104
  email:
77
105
  - santiago@snapsheet.me
@@ -81,6 +109,8 @@ extra_rdoc_files: []
81
109
  files:
82
110
  - ".gitignore"
83
111
  - ".rspec"
112
+ - ".rubocop.yml"
113
+ - ".ruby-version"
84
114
  - ".travis.yml"
85
115
  - CODE_OF_CONDUCT.md
86
116
  - Gemfile
@@ -90,6 +120,10 @@ files:
90
120
  - bin/console
91
121
  - bin/setup
92
122
  - lib/ssm_config.rb
123
+ - lib/ssm_config/errors.rb
124
+ - lib/ssm_config/ssm_storage/db.rb
125
+ - lib/ssm_config/ssm_storage/empty.rb
126
+ - lib/ssm_config/ssm_storage/yml.rb
93
127
  - ssm_config.gemspec
94
128
  homepage: https://github.com/bodyshopbidsdotcom/ssm_config
95
129
  licenses:
@@ -104,14 +138,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
104
138
  requirements:
105
139
  - - ">="
106
140
  - !ruby/object:Gem::Version
107
- version: '0'
141
+ version: '2.6'
108
142
  required_rubygems_version: !ruby/object:Gem::Requirement
109
143
  requirements:
110
144
  - - ">="
111
145
  - !ruby/object:Gem::Version
112
146
  version: '0'
113
147
  requirements: []
114
- rubygems_version: 3.2.33
148
+ rubygems_version: 3.0.9
115
149
  signing_key:
116
150
  specification_version: 4
117
151
  summary: YML file loader and parser for Rails