After reading this article, I decided to deepen my knowledge of Ruby while reading the code. https://blog.freedom-man.com/try-rubygem-codereading
$ bundle init
Stumble from the beginning ..
$ gem install settingslogic
ERROR: Loading command: install (LoadError)
dlopen(/Users/XXXX/.rbenv/versions/2.4.2/lib/ruby/2.4.0/x86_64-darwin16/openssl.bundle, 9): Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
Referenced from: /Users/XXXX/.rbenv/versions/2.4.2/lib/ruby/2.4.0/x86_64-darwin16/openssl.bundle
Reason: image not found - /Users/XXXX/.rbenv/versions/2.4.2/lib/ruby/2.4.0/x86_64-darwin16/openssl.bundle
ERROR: While executing gem ... (NoMethodError)
undefined method `invoke_with_build_args' for nil:NilClass
It seems that the openssl link is wrong, so fix it by referring to this article https://qiita.com/Capotasto/items/16be7620c4eed42efccb https://qiita.com/YoshiyukiKato/items/e4f67c588d2943c1253d
$ brew uninstall --force --ignore-dependencies openssl
$ brew install openssl
$ brew link openssl
$ rbenv uninstall 2.4.2
$ rbenv install 2.4.2
I was able to go with this.
$ echo 'source "https://rubygems.org"' >> ./Gemfile
$ echo 'gem "settingslogic"' >> ./Gemfile
$ echo 'gem "pry"' >> ./Gemfile
$ bundle config set --local path 'vendor/bundle'
$ bundle install
file is only one file [settingslogic.rb] (https://github.com/binarylogic/settingslogic/blob/master/lib/settingslogic.rb)
class Settingslogic < Hash
It seems that it inherits the Hash class
Is it easy to insert the key and value?
def [](key)
instance.fetch(key.to_s, nil)
end
def []=(key, val)
# Setting[:key][:key2] = 'value' for dynamic settings
val = new(val, source) if val.is_a? Hash
instance.store(key.to_s, val)
instance.create_accessor_for(key, val)
end
This area seems to be an override of the Hash class
new(val, source)
You can write new like this. Here, initialize in the class is called (initialization), and it is added to the current instance with the specified key.
Or rather, you can override the behavior of the operator as a method.
def initialize(hash_or_file = self.class.source, section = nil)
#puts "new! #{hash_or_file}"
case hash_or_file
when nil
raise Errno::ENOENT, "No file specified as Settingslogic source"
when Hash
self.replace hash_or_file
else
file_contents = open(hash_or_file).read
hash = file_contents.empty? ? {} : YAML.load(ERB.new(file_contents).result).to_hash
if self.class.namespace
hash = hash[self.class.namespace] or return missing_key("Missing setting '#{self.class.namespace}' in #{hash_or_file}")
end
self.replace hash
end
@section = section || self.class.source # so end of error says "in application.yml"
create_accessors!
end
It seems to read yaml here. In this
if self.class.namespace
hash = hash[self.class.namespace] or return missing_key("Missing setting '#{self.class.namespace}' in #{hash_or_file}")
end
I wonder if only the data in the specified namespace is used as hash here
settings.yaml
defaults: &defaults
cool:
saweet: nested settings
neat_setting: 24
awesome_setting: <%= "Did you know 5 + 5 = #{5 + 5}?" %>
development:
<<: *defaults
neat_setting: 800
test:
<<: *defaults
production:
<<: *defaults
setting.rb
require 'settingslogic'
class Settings < Settingslogic
source File.expand_path("../settings.yml", __FILE__)
namespace ENV['ENV']
end
sample.rb
require File.expand_path("../settings.rb", __FILE__)
puts Settings.neat_setting
puts Settings.awesome_setting
puts Settings.cool.saweet
\w $ ENV=production ruby sample.rb
24
Did you know 5 + 5 = 10?
nested settings
For the time being, I was chased roughly. It's good to put it in rails and then try it, but I wanted to make it easier, so I output it a little.
Officially, there are dynamic binding etc. If you execute it directly, an error will occur. ..
Next, let's chase the code a little more while putting it in Rails.
Since there are not 200 lines, it is relatively easy to get along with.