From b2e38c7a6819faa580c12b6d604c88927bc432f0 Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Wed, 28 Jan 2026 22:25:24 +0900 Subject: [PATCH 1/2] Apply rubocop and enable in CI --- .github/workflows/tests.yml | 16 ++ .rubocop.yml | 12 ++ Appraisals | 6 +- Rakefile | 11 +- config.gemspec | 7 +- lib/config/configuration.rb | 2 +- lib/config/dry_validation_requirements.rb | 9 +- lib/config/integrations/heroku.rb | 32 +-- lib/config/integrations/rails/railtie.rb | 3 +- lib/config/integrations/sinatra.rb | 5 +- lib/config/options.rb | 82 +++---- lib/config/rack/reloader.rb | 2 +- lib/config/sources/env_source.rb | 53 ++--- lib/config/sources/yaml_source.rb | 5 +- lib/config/validation/error.rb | 4 +- lib/config/validation/validate.rb | 12 +- lib/generators/config/install_generator.rb | 20 +- .../rails_8.0/config/initializers/assets.rb | 2 +- spec/config_env_spec.rb | 12 +- spec/config_spec.rb | 163 +++++++------- spec/options_spec.rb | 40 ++-- spec/sources/env_source_spec.rb | 188 ++++++++-------- spec/sources/hash_source_spec.rb | 70 +++--- spec/sources/yaml_source_spec.rb | 204 +++++++++--------- spec/spec_helper.rb | 14 +- spec/support/fixture_helper.rb | 2 +- spec/support/rails_helper.rb | 16 +- spec/support/shared_contexts/rake.rb | 2 - spec/tasks/db_spec.rb | 2 +- spec/validation_spec.rb | 16 +- 30 files changed, 519 insertions(+), 493 deletions(-) mode change 100644 => 100755 Rakefile diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9f04025c..b92edcc7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -60,10 +60,26 @@ jobs: with: coverageCommand: bundle exec appraisal rspec + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 4.0.1 + bundler-cache: true + + - name: Lint code for consistent style + run: bundle exec rubocop -f github + all-passed: runs-on: ubuntu-latest if: always() needs: - test + - lint steps: - run: exit ${{ contains(needs.*.result, 'failure') && 1 || 0 }} diff --git a/.rubocop.yml b/.rubocop.yml index 462787d8..b0557728 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,15 @@ +AllCops: + NewCops: disable + Exclude: + - 'spec/app/**/*' + - 'gemfiles/**/*' + +Metrics: + Enabled: false + +Style/Documentation: + Enabled: false + Layout/LineLength: Max: 120 diff --git a/Appraisals b/Appraisals index 1261a151..1f63a369 100644 --- a/Appraisals +++ b/Appraisals @@ -1,8 +1,4 @@ -max_ruby_version = ->(version) { - RUBY_ENGINE == 'ruby' && Gem::Version.new(RUBY_VERSION) <= Gem::Version.new(version) -} - -min_ruby_version = ->(version) { +min_ruby_version = lambda { |version| RUBY_ENGINE == 'ruby' && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new(version) } diff --git a/Rakefile b/Rakefile old mode 100644 new mode 100755 index 224b446d..5bc8f78b --- a/Rakefile +++ b/Rakefile @@ -4,7 +4,6 @@ begin require 'bundler/setup' Bundler::GemHelper.install_tasks - rescue LoadError puts 'You must `gem install bundler` and `bundle install` to run rake tasks' end @@ -12,18 +11,18 @@ end ## # Testing # -require "rspec" -require "rspec/core/rake_task" +require 'rspec' +require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) # Test for multiple Rails scenarios if !ENV['APPRAISAL_INITIALIZED'] && !ENV['GITHUB_ACTIONS'] - require "appraisal" + require 'appraisal' - task :default => :appraisal + task default: :appraisal else - task :default => :spec + task default: :spec end ## diff --git a/config.gemspec b/config.gemspec index b5279d74..b1b5eb53 100644 --- a/config.gemspec +++ b/config.gemspec @@ -1,3 +1,4 @@ +require 'English' require_relative 'lib/config/version' require_relative 'lib/config/dry_validation_requirements' @@ -8,7 +9,7 @@ Gem::Specification.new do |s| s.authors = ['Piotr Kuczynski', 'Fred Wu', 'Jacques Crocker'] s.email = %w[piotr.kuczynski@gmail.com ifredwu@gmail.com railsjedi@gmail.com] s.summary = 'Effortless multi-environment settings in Rails, Sinatra, Padrino and others' - s.description = 'Easiest way to manage multi-environment settings in any ruby project or framework: ' + + s.description = 'Easiest way to manage multi-environment settings in any ruby project or framework: ' \ 'Rails, Sinatra, Padrino and others' s.homepage = 'https://github.com/rubyconfig/config' s.license = 'MIT' @@ -16,12 +17,12 @@ Gem::Specification.new do |s| s.rdoc_options = ['--charset=UTF-8'] s.metadata = { - 'changelog_uri' => "https://github.com/rubyconfig/config/blob/master/CHANGELOG.md", + 'changelog_uri' => 'https://github.com/rubyconfig/config/blob/master/CHANGELOG.md', 'funding_uri' => 'https://opencollective.com/rubyconfig/donate', 'source_code_uri' => 'https://github.com/rubyconfig/config', 'bug_tracker_uri' => 'https://github.com/rubyconfig/config/issues' } - s.files = `git ls-files`.split($/) + s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR) s.files.select! { |file| /(^lib\/|^\w+.md$|\.gemspec$)/ =~ file } s.require_paths = ['lib'] diff --git a/lib/config/configuration.rb b/lib/config/configuration.rb index f1bec017..7b161b4b 100644 --- a/lib/config/configuration.rb +++ b/lib/config/configuration.rb @@ -4,7 +4,7 @@ class Configuration < Module # Accepts configuration options, # initializing a module that can be used to extend # the necessary class with the provided config methods - def initialize(**attributes) + def initialize(**attributes) # rubocop:disable Lint/MissingSuper attributes.each do |name, default| define_reader(name, default) define_writer(name) diff --git a/lib/config/dry_validation_requirements.rb b/lib/config/dry_validation_requirements.rb index 54064ea9..8c4ca6c8 100644 --- a/lib/config/dry_validation_requirements.rb +++ b/lib/config/dry_validation_requirements.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - module Config module DryValidationRequirements VERSIONS = ['~> 1.0', '>= 1.0.0'].freeze @@ -10,11 +8,10 @@ def self.load_dry_validation! begin require 'dry/validation/version' version = Gem::Version.new(Dry::Validation::VERSION) - unless VERSIONS.all? { |req| Gem::Requirement.new(req).satisfied_by?(version) } - raise LoadError - end + raise LoadError unless VERSIONS.all? { |req| Gem::Requirement.new(req).satisfied_by?(version) } rescue LoadError - raise ::Config::Error, "Could not find a dry-validation version matching requirements (#{VERSIONS.map(&:inspect) * ','})" + raise ::Config::Error, + "Could not find a dry-validation version matching requirements (#{VERSIONS.map(&:inspect) * ','})" end require 'dry/validation' diff --git a/lib/config/integrations/heroku.rb b/lib/config/integrations/heroku.rb index b7272fb0..76a4842c 100644 --- a/lib/config/integrations/heroku.rb +++ b/lib/config/integrations/heroku.rb @@ -2,7 +2,7 @@ module Config module Integrations - class Heroku < Struct.new(:app) + Heroku = Struct.new(:app) do def invoke puts 'Setting vars...' heroku_command = "config:set #{vars}" @@ -14,14 +14,14 @@ def invoke def vars # Load only local options to Heroku Config.load_and_set_settings( - Rails.root.join("config", "#{Config.file_name}.local.yml").to_s, - Rails.root.join("config", Config.dir_name, "#{environment}.local.yml").to_s, - Rails.root.join("config", "environments", "#{environment}.local.yml").to_s + Rails.root.join('config', "#{Config.file_name}.local.yml").to_s, + Rails.root.join('config', Config.dir_name, "#{environment}.local.yml").to_s, + Rails.root.join('config', 'environments', "#{environment}.local.yml").to_s ) out = '' dotted_hash = to_dotted_hash Kernel.const_get(Config.const_name).to_hash, {}, Config.const_name - dotted_hash.each {|key, value| out += " #{key}=#{value} "} + dotted_hash.each { |key, value| out += " #{key}=#{value} " } out end @@ -30,7 +30,7 @@ def environment end def heroku(command) - with_app = app ? " --app #{app}" : "" + with_app = app ? " --app #{app}" : '' `heroku #{command}#{with_app}` end @@ -41,16 +41,16 @@ def `(command) def to_dotted_hash(source, target = {}, namespace = nil) prefix = "#{namespace}." if namespace case source - when Hash - source.each do |key, value| - to_dotted_hash(value, target, "#{prefix}#{key}") - end - when Array - source.each_with_index do |value, index| - to_dotted_hash(value, target, "#{prefix}#{index}") - end - else - target[namespace] = source + when Hash + source.each do |key, value| + to_dotted_hash(value, target, "#{prefix}#{key}") + end + when Array + source.each_with_index do |value, index| + to_dotted_hash(value, target, "#{prefix}#{index}") + end + else + target[namespace] = source end target end diff --git a/lib/config/integrations/rails/railtie.rb b/lib/config/integrations/rails/railtie.rb index 6748c116..d8e0d379 100644 --- a/lib/config/integrations/rails/railtie.rb +++ b/lib/config/integrations/rails/railtie.rb @@ -9,7 +9,8 @@ def preload # Parse the settings before any of the initializers Config.load_and_set_settings( - Config.setting_files(::Rails.root.join('config'), Config.environment.nil? ? ::Rails.env : Config.environment.to_sym) + Config.setting_files(::Rails.root.join('config'), + Config.environment.nil? ? ::Rails.env : Config.environment.to_sym) ) end diff --git a/lib/config/integrations/sinatra.rb b/lib/config/integrations/sinatra.rb index ccacd1e6..3d160184 100644 --- a/lib/config/integrations/sinatra.rb +++ b/lib/config/integrations/sinatra.rb @@ -1,4 +1,4 @@ -require "config/rack/reloader" +require 'config/rack/reloader' module Config # provide helper to register within your Sinatra app @@ -8,8 +8,7 @@ module Config # def self.registered(app) app.configure do |inner_app| - - env = inner_app.environment || ENV["RACK_ENV"] + env = inner_app.environment || ENV['RACK_ENV'] root = inner_app.root # use Padrino settings if applicable diff --git a/lib/config/options.rb b/lib/config/options.rb index cba24bd1..c94a8372 100644 --- a/lib/config/options.rb +++ b/lib/config/options.rb @@ -16,16 +16,16 @@ def empty? def add_source!(source) # handle yaml file paths - source = (Sources::YAMLSource.new(source)) if source.is_a?(String) || source.is_a?(Pathname) - source = (Sources::HashSource.new(source)) if source.is_a?(Hash) + source = Sources::YAMLSource.new(source) if source.is_a?(String) || source.is_a?(Pathname) + source = Sources::HashSource.new(source) if source.is_a?(Hash) @config_sources ||= [] @config_sources << source end def prepend_source!(source) - source = (Sources::YAMLSource.new(source)) if source.is_a?(String) || source.is_a?(Pathname) - source = (Sources::HashSource.new(source)) if source.is_a?(Hash) + source = Sources::YAMLSource.new(source) if source.is_a?(String) || source.is_a?(Pathname) + source = Sources::HashSource.new(source) if source.is_a?(Hash) @config_sources ||= [] @config_sources.unshift(source) @@ -41,14 +41,14 @@ def reload! conf = source_conf else DeepMerge.deep_merge!( - source_conf, - conf, - preserve_unmergeables: false, - knockout_prefix: Config.knockout_prefix, - overwrite_arrays: Config.overwrite_arrays, - merge_nil_values: Config.merge_nil_values, - merge_hash_arrays: Config.merge_hash_arrays - ) + source_conf, + conf, + preserve_unmergeables: false, + knockout_prefix: Config.knockout_prefix, + overwrite_arrays: Config.overwrite_arrays, + merge_nil_values: Config.merge_nil_values, + merge_hash_arrays: Config.merge_hash_arrays + ) end end @@ -60,7 +60,7 @@ def reload! self end - alias :load! :reload! + alias load! reload! def reload_from_files(*files) Config.load_and_set_settings(files) @@ -70,25 +70,29 @@ def reload_from_files(*files) def to_hash result = {} marshal_dump.each do |k, v| - if v.instance_of? Config::Options - result[k] = v.to_hash - elsif v.instance_of? Array - result[k] = descend_array(v) - else - result[k] = v - end + result[k] = if v.instance_of? Config::Options + v.to_hash + elsif v.instance_of? Array + descend_array(v) + else + v + end end result end - alias :to_h :to_hash + alias to_h to_hash def each(*args, &block) marshal_dump.each(*args, &block) end + def each_key(*args, &block) + marshal_dump.each_key(*args, &block) + end + def to_json(*args) - require "json" unless defined?(JSON) + require 'json' unless defined?(JSON) to_hash.to_json(*args) end @@ -99,14 +103,14 @@ def as_json(options = nil) def merge!(hash) current = to_hash DeepMerge.deep_merge!( - hash.dup, - current, - preserve_unmergeables: false, - knockout_prefix: Config.knockout_prefix, - overwrite_arrays: Config.overwrite_arrays, - merge_nil_values: Config.merge_nil_values, - merge_hash_arrays: Config.merge_hash_arrays - ) + hash.dup, + current, + preserve_unmergeables: false, + knockout_prefix: Config.knockout_prefix, + overwrite_arrays: Config.overwrite_arrays, + merge_nil_values: Config.merge_nil_values, + merge_hash_arrays: Config.merge_hash_arrays + ) marshal_load(__convert(current).marshal_dump) self end @@ -122,7 +126,8 @@ def merge!(hash) def [](param) return super if SETTINGS_RESERVED_NAMES.include?(param) return super if RAILS_RESERVED_NAMES.include?(param) - public_send("#{param}") + + public_send(param.to_s) end def []=(param, value) @@ -145,14 +150,15 @@ def key?(key) @table.key?(key) end - def has_key?(key) - @table.has_key?(key) + def has_key?(key) # rubocop:disable Naming/PredicatePrefix + @table.has_key?(key) # rubocop:disable Style/PreferredHashMethods end def method_missing(method_name, *args) - if Config.fail_on_missing && !method_name.to_s.end_with?('=') - raise KeyError, "key not found: #{method_name.inspect}" unless key?(method_name) + if Config.fail_on_missing && !method_name.to_s.end_with?('=') && !key?(method_name) + raise KeyError, "key not found: #{method_name.inspect}" end + super end @@ -175,14 +181,14 @@ def descend_array(array) end # Recursively converts Hashes to Options (including Hashes inside Arrays) - def __convert(h) #:nodoc: + def __convert(hash) # :nodoc: s = self.class.new - h.each do |k, v| + hash.each do |k, v| k = k.to_s if !k.respond_to?(:to_sym) && k.respond_to?(:to_s) if v.is_a?(Hash) - v = v["type"] == "hash" ? v["contents"] : __convert(v) + v = v['type'] == 'hash' ? v['contents'] : __convert(v) elsif v.is_a?(Array) v = v.collect { |e| e.instance_of?(Hash) ? __convert(e) : e } end diff --git a/lib/config/rack/reloader.rb b/lib/config/rack/reloader.rb index a98c0038..d7f5e00a 100644 --- a/lib/config/rack/reloader.rb +++ b/lib/config/rack/reloader.rb @@ -12,4 +12,4 @@ def call(env) end end end -end \ No newline at end of file +end diff --git a/lib/config/sources/env_source.rb b/lib/config/sources/env_source.rb index ea527db4..475987f3 100644 --- a/lib/config/sources/env_source.rb +++ b/lib/config/sources/env_source.rb @@ -2,11 +2,7 @@ module Config module Sources # Allows settings to be loaded from a "flat" hash with string keys, like ENV. class EnvSource - attr_reader :prefix - attr_reader :separator - attr_reader :converter - attr_reader :parse_values - attr_reader :parse_arrays + attr_reader :prefix, :separator, :converter, :parse_values, :parse_arrays def initialize(env, prefix: Config.env_prefix || Config.const_name, @@ -25,27 +21,27 @@ def initialize(env, def load return {} if @env.nil? || @env.empty? - hash = Hash.new + hash = {} @env.each do |variable, value| keys = variable.to_s.split(separator) next if keys.shift(prefix.size) != prefix - keys.map! { |key| + keys.map! do |key| case converter - when :downcase then - key.downcase - when nil then - key - else - raise "Invalid ENV variables name converter: #{converter}" + when :downcase + key.downcase + when nil + key + else + raise "Invalid ENV variables name converter: #{converter}" end - } + end - leaf = keys[0...-1].inject(hash) { |h, key| + leaf = keys[0...-1].inject(hash) do |h, key| h[key] ||= {} - } + end unless leaf.is_a?(Hash) conflicting_key = (prefix + keys[0...-1]).join(separator) @@ -59,15 +55,16 @@ def load end private + def convert_hashes_to_arrays(hash) hash.each_with_object({}) do |(key, value), new_hash| if value.is_a?(Hash) value = convert_hashes_to_arrays(value) - if consecutive_numeric_keys?(value.keys) - new_hash[key] = value.keys.sort_by(&:to_i).map { |k| value[k] } - else - new_hash[key] = value - end + new_hash[key] = if consecutive_numeric_keys?(value.keys) + value.keys.sort_by(&:to_i).map { |k| value[k] } + else + value + end else new_hash[key] = value end @@ -79,14 +76,22 @@ def consecutive_numeric_keys?(keys) end # Try to convert string to a correct type - def __value(v) - case v + def __value(string) + case string when 'false' false when 'true' true else - Integer(v) rescue Float(v) rescue v + begin + begin + Integer(string) + rescue StandardError + Float(string) + end + rescue StandardError + string + end end end end diff --git a/lib/config/sources/yaml_source.rb b/lib/config/sources/yaml_source.rb index 68ff7207..3c9763bb 100644 --- a/lib/config/sources/yaml_source.rb +++ b/lib/config/sources/yaml_source.rb @@ -14,17 +14,16 @@ def initialize(path, evaluate_erb: Config.evaluate_erb_in_yaml) # returns a config hash from the YML file def load - if @path and File.exist?(@path) + if @path && File.exist?(@path) file_contents = File.read(@path) file_contents = ERB.new(file_contents).result if evaluate_erb result = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(file_contents) : YAML.load(file_contents) end result || {} - rescue Psych::SyntaxError => e raise "YAML syntax error occurred while parsing #{@path}. " \ - "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \ + 'Please note that YAML must be consistently indented using spaces. Tabs are not allowed. ' \ "Error: #{e.message}" end end diff --git a/lib/config/validation/error.rb b/lib/config/validation/error.rb index cc523c43..49f1f742 100644 --- a/lib/config/validation/error.rb +++ b/lib/config/validation/error.rb @@ -1,15 +1,13 @@ -require_relative "../error" +require_relative '../error' module Config module Validation class Error < ::Config::Error - def self.format(v_res) v_res.errors.group_by(&:path).map do |path, messages| "#{' ' * 2}#{path.join('.')}: #{messages.map(&:text).join('; ')}" end.join("\n") end - end end end diff --git a/lib/config/validation/validate.rb b/lib/config/validation/validate.rb index d0f892be..b7a1b458 100644 --- a/lib/config/validation/validate.rb +++ b/lib/config/validation/validate.rb @@ -15,14 +15,14 @@ def validate! private def validate_using!(validator) - if validator - result = validator.call(to_hash) + return unless validator - return if result.success? + result = validator.call(to_hash) - error = Config::Validation::Error.format(result) - raise Config::Validation::Error, "Config validation failed:\n\n#{error}" - end + return if result.success? + + error = Config::Validation::Error.format(result) + raise Config::Validation::Error, "Config validation failed:\n\n#{error}" end end end diff --git a/lib/generators/config/install_generator.rb b/lib/generators/config/install_generator.rb index 3b183731..91c352f5 100644 --- a/lib/generators/config/install_generator.rb +++ b/lib/generators/config/install_generator.rb @@ -1,30 +1,30 @@ module Config module Generators class InstallGenerator < ::Rails::Generators::Base - desc "Generates a custom Rails Config initializer file." + desc 'Generates a custom Rails Config initializer file.' def self.source_root - @_config_source_root ||= File.expand_path("../templates", __FILE__) + @source_root ||= File.expand_path('templates', __dir__) end def copy_initializer - template "config.rb", "config/initializers/config.rb" + template 'config.rb', 'config/initializers/config.rb' end def copy_settings - template "settings.yml", "config/#{Config.file_name}.yml" - template "settings.local.yml", "config/#{Config.file_name}.local.yml" - directory "settings", "config/#{Config.dir_name}" + template 'settings.yml', "config/#{Config.file_name}.yml" + template 'settings.local.yml', "config/#{Config.file_name}.local.yml" + directory 'settings', "config/#{Config.dir_name}" end def modify_gitignore create_file '.gitignore' unless File.exist? '.gitignore' append_to_file '.gitignore' do - "\n" + - "config/#{Config.file_name}.local.yml\n" + - "config/#{Config.dir_name}/*.local.yml\n" + - "config/environments/*.local.yml\n" + "\n" \ + "config/#{Config.file_name}.local.yml\n" \ + "config/#{Config.dir_name}/*.local.yml\n" \ + "config/environments/*.local.yml\n" end end end diff --git a/spec/app/rails_8.0/config/initializers/assets.rb b/spec/app/rails_8.0/config/initializers/assets.rb index 48732442..68fd3a0a 100644 --- a/spec/app/rails_8.0/config/initializers/assets.rb +++ b/spec/app/rails_8.0/config/initializers/assets.rb @@ -1,7 +1,7 @@ # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = "1.0" +# Rails.application.config.assets.version = "1.0" # Add additional assets to the asset load path. # Rails.application.config.assets.paths << Emoji.images_path diff --git a/spec/config_env_spec.rb b/spec/config_env_spec.rb index 5ca3109f..3489b5fd 100644 --- a/spec/config_env_spec.rb +++ b/spec/config_env_spec.rb @@ -58,35 +58,35 @@ ENV['Settings.new_var'] = 'false' expect(config.new_var).to eq(false) - expect(config.new_var.is_a? FalseClass).to eq(true) + expect(config.new_var.is_a?(FalseClass)).to eq(true) end it 'should recognize "true" and expose as Boolean' do ENV['Settings.new_var'] = 'true' expect(config.new_var).to eq(true) - expect(config.new_var.is_a? TrueClass).to eq(true) + expect(config.new_var.is_a?(TrueClass)).to eq(true) end it 'should recognize numbers and expose them as integers' do ENV['Settings.new_var'] = '123' expect(config.new_var).to eq(123) - expect(config.new_var.is_a? Integer).to eq(true) + expect(config.new_var.is_a?(Integer)).to eq(true) end it 'should recognize fixed point numbers and expose them as float' do ENV['Settings.new_var'] = '1.9' expect(config.new_var).to eq(1.9) - expect(config.new_var.is_a? Float).to eq(true) + expect(config.new_var.is_a?(Float)).to eq(true) end it 'should leave strings intact' do ENV['Settings.new_var'] = 'foobar' expect(config.new_var).to eq('foobar') - expect(config.new_var.is_a? String).to eq(true) + expect(config.new_var.is_a?(String)).to eq(true) end end @@ -111,7 +111,7 @@ ENV['Settings.SomeConfig.0'] = 'first' ENV['Settings.SomeConfig.1'] = 'second' - expect(config.someconfig).to eq(['first', 'second']) + expect(config.someconfig).to eq(%w[first second]) end end diff --git a/spec/config_spec.rb b/spec/config_spec.rb index 79f8c4e2..fe08ce00 100644 --- a/spec/config_spec.rb +++ b/spec/config_spec.rb @@ -5,8 +5,8 @@ Config.reset end - it "should get setting files" do - config = Config.setting_files("root/config", "staging") + it 'should get setting files' do + config = Config.setting_files('root/config', 'staging') expect(config).to eq([ 'root/config/settings.yml', 'root/config/settings/staging.yml', @@ -17,8 +17,8 @@ ]) end - it "should ignore local config in test environment" do - config = Config.setting_files("root/config", "test") + it 'should ignore local config in test environment' do + config = Config.setting_files('root/config', 'test') expect(config).to eq([ 'root/config/settings.yml', 'root/config/settings/test.yml', @@ -28,17 +28,17 @@ ]) end - it "should load a basic config file" do + it 'should load a basic config file' do config = Config.load_files("#{fixture_path}/settings.yml") expect(config.size).to eq(1) - expect(config.server).to eq("google.com") + expect(config.server).to eq('google.com') expect(config['1']).to eq('one') expect(config.photo_sizes.avatar).to eq([60, 60]) expect(config.root['yahoo.com']).to eq(2) expect(config.root['google.com']).to eq(3) end - it "should load extra_sources and support different types" do + it 'should load extra_sources and support different types' do test_hash = { 'extra_key' => 'extra_value' } object_source = double 'source' @@ -58,15 +58,15 @@ expect(Settings.size).to eq(1) expect(Settings.extra_key).to eq('extra_value') - expect(Settings.another).to eq("something") + expect(Settings.another).to eq('something') expect(Settings.server).to eq('google.com') end - it "should load 2 basic config files" do + it 'should load 2 basic config files' do config = Config.load_files("#{fixture_path}/settings.yml", "#{fixture_path}/settings2.yml") expect(config.size).to eq(1) - expect(config.server).to eq("google.com") - expect(config.another).to eq("something") + expect(config.server).to eq('google.com') + expect(config.another).to eq('something') end it 'should load config files specified as Pathname objects' do @@ -98,36 +98,36 @@ expect(config.size).to eq(12) end - it "should load empty config for a missing file path" do + it 'should load empty config for a missing file path' do config = Config.load_files("#{fixture_path}/some_file_that_doesnt_exist.yml") expect(config).to be_empty end - it "should load an empty config for multiple missing file paths" do + it 'should load an empty config for multiple missing file paths' do files = ["#{fixture_path}/doesnt_exist1.yml", "#{fixture_path}/doesnt_exist2.yml"] config = Config.load_files(files) expect(config).to be_empty end - it "should load empty config for an empty setting file" do + it 'should load empty config for an empty setting file' do config = Config.load_files("#{fixture_path}/empty1.yml") expect(config).to be_empty end - it "should convert to a hash" do + it 'should convert to a hash' do config = Config.load_files("#{fixture_path}/development.yml").to_hash expect(config[:section][:servers]).to be_kind_of(Array) - expect(config[:section][:servers][0][:name]).to eq("yahoo.com") - expect(config[:section][:servers][1][:name]).to eq("amazon.com") + expect(config[:section][:servers][0][:name]).to eq('yahoo.com') + expect(config[:section][:servers][1][:name]).to eq('amazon.com') end - it "should convert to a hash (We Need To Go Deeper)" do + it 'should convert to a hash (We Need To Go Deeper)' do config = Config.load_files("#{fixture_path}/development.yml").to_hash servers = config[:section][:servers] - expect(servers).to eq([{ name: "yahoo.com" }, { name: "amazon.com" }]) + expect(servers).to eq([{ name: 'yahoo.com' }, { name: 'amazon.com' }]) end - it "should convert to a hash without modifying nested settings" do + it 'should convert to a hash without modifying nested settings' do config = Config.load_files("#{fixture_path}/development.yml") config.to_hash expect(config).to be_kind_of(Config::Options) @@ -136,7 +136,7 @@ expect(config[:section][:servers][1]).to be_kind_of(Config::Options) end - it "should convert to a hash without modifying nested settings" do + it 'should convert to a hash without modifying nested settings' do config = Config.load_files("#{fixture_path}/development.yml") config.to_h expect(config).to be_kind_of(Config::Options) @@ -145,106 +145,103 @@ expect(config[:section][:servers][1]).to be_kind_of(Config::Options) end - it "should convert to a json" do + it 'should convert to a json' do config = Config.load_files("#{fixture_path}/development.yml").to_json - expect(JSON.parse(config)["section"]["servers"]).to be_kind_of(Array) + expect(JSON.parse(config)['section']['servers']).to be_kind_of(Array) end - it "should load an empty config for multiple missing file paths" do + it 'should load an empty config for multiple missing file paths' do files = ["#{fixture_path}/empty1.yml", "#{fixture_path}/empty2.yml"] config = Config.load_files(files) expect(config).to be_empty end - it "should allow overrides" do + it 'should allow overrides' do files = ["#{fixture_path}/settings.yml", "#{fixture_path}/development.yml"] config = Config.load_files(files) - expect(config.server).to eq("google.com") + expect(config.server).to eq('google.com') expect(config.size).to eq(2) end - it "should allow full reload of the settings files" do + it 'should allow full reload of the settings files' do files = ["#{fixture_path}/settings.yml"] Config.load_and_set_settings(files) - expect(Settings.server).to eq("google.com") + expect(Settings.server).to eq('google.com') expect(Settings.size).to eq(1) files = ["#{fixture_path}/settings.yml", "#{fixture_path}/development.yml"] Settings.reload_from_files(files) - expect(Settings.server).to eq("google.com") + expect(Settings.server).to eq('google.com') expect(Settings.size).to eq(2) end - - - context "Nested Settings" do + context 'Nested Settings' do let(:config) do Config.load_files("#{fixture_path}/development.yml") end - it "should allow nested sections" do + it 'should allow nested sections' do expect(config.section.size).to eq(3) end - it "should allow configuration collections (arrays)" do - expect(config.section.servers[0].name).to eq("yahoo.com") - expect(config.section.servers[1].name).to eq("amazon.com") + it 'should allow configuration collections (arrays)' do + expect(config.section.servers[0].name).to eq('yahoo.com') + expect(config.section.servers[1].name).to eq('amazon.com') end end - context "Settings with ERB tags" do + context 'Settings with ERB tags' do let(:config) do Config.load_files("#{fixture_path}/with_erb.yml") end - it "should evaluate ERB tags" do + it 'should evaluate ERB tags' do expect(config.computed).to eq(6) end - it "should evaluated nested ERB tags" do + it 'should evaluated nested ERB tags' do expect(config.section.computed1).to eq(1) expect(config.section.computed2).to eq(2) end end - - context "Boolean Overrides" do + context 'Boolean Overrides' do let(:config) do files = ["#{fixture_path}/bool_override/config1.yml", "#{fixture_path}/bool_override/config2.yml"] Config.load_files(files) end - it "should allow overriding of bool settings" do + it 'should allow overriding of bool settings' do expect(config.override_bool).to eq(false) expect(config.override_bool_opposite).to eq(true) end end - context "Custom Configuration" do + context 'Custom Configuration' do it "should have the default settings constant as 'Settings'" do - expect(Config.const_name).to eq("Settings") + expect(Config.const_name).to eq('Settings') end - it "should be able to assign a different settings constant" do - Config.setup { |config| config.const_name = "Settings2" } + it 'should be able to assign a different settings constant' do + Config.setup { |config| config.const_name = 'Settings2' } - expect(Config.const_name).to eq("Settings2") + expect(Config.const_name).to eq('Settings2') end - context "filename and directory" do - it "should allow to use custom names" do + context 'filename and directory' do + it 'should allow to use custom names' do Config.setup do |config| - config.file_name = "custom_file" - config.dir_name = "custom_dir" + config.file_name = 'custom_file' + config.dir_name = 'custom_dir' end - expect(Config.file_name).to eq("custom_file") - expect(Config.dir_name).to eq("custom_dir") + expect(Config.file_name).to eq('custom_file') + expect(Config.dir_name).to eq('custom_dir') end - it "should have default values" do - expect(Config.file_name).to eq("settings") - expect(Config.dir_name).to eq("settings") + it 'should have default values' do + expect(Config.file_name).to eq('settings') + expect(Config.dir_name).to eq('settings') end end end @@ -255,11 +252,11 @@ Config.load_files(files) end - it "should turn that setting into a Real Hash" do + it 'should turn that setting into a Real Hash' do expect(config.prices).to be_kind_of(Hash) end - it "should map the hash values correctly" do + it 'should map the hash values correctly' do expect(config.prices[1]).to eq(2.99) expect(config.prices[5]).to eq(9.99) expect(config.prices[15]).to eq(19.99) @@ -267,16 +264,16 @@ end end - context "Merging hash at runtime" do + context 'Merging hash at runtime' do let(:config) { Config.load_files("#{fixture_path}/settings.yml") } - let(:hash) { { :options => { :suboption => 'value' }, :server => 'amazon.com' } } + let(:hash) { { options: { suboption: 'value' }, server: 'amazon.com' } } it 'should be chainable' do expect(config.merge!({})).to eq(config) end it 'should preserve existing keys' do - expect { config.merge!({}) }.to_not change { config.keys } + expect { config.merge!({}) }.to_not(change { config.keys }) end it 'should recursively merge keys' do @@ -289,13 +286,13 @@ end end - context "Merging nested hash at runtime" do + context 'Merging nested hash at runtime' do let(:config) { Config.load_files("#{fixture_path}/deep_merge/config1.yml") } let(:hash) { { inner: { something1: 'changed1', something3: 'changed3' } } } let(:hash_with_nil) { { inner: { something1: nil } } } it 'should preserve first level keys' do - expect { config.merge!(hash) }.to_not change { config.keys } + expect { config.merge!(hash) }.to_not(change { config.keys }) end it 'should preserve nested key' do @@ -362,58 +359,58 @@ end end - context "[] accessors" do + context '[] accessors' do let(:config) do files = ["#{fixture_path}/development.yml"] Config.load_files(files) end - it "should access attributes using []" do + it 'should access attributes using []' do expect(config.section['size']).to eq(3) expect(config.section[:size]).to eq(3) expect(config[:section][:size]).to eq(3) end - it "should set values using []=" do + it 'should set values using []=' do config.section[:foo] = 'bar' expect(config.section.foo).to eq('bar') end end - context "enumerable" do + context 'enumerable' do let(:config) do files = ["#{fixture_path}/development.yml"] Config.load_files(files) end - it "should enumerate top level parameters" do + it 'should enumerate top level parameters' do keys = [] - config.each { |key, value| keys << key } - expect(keys).to eq([:size, :section]) + config.each_key { |key| keys << key } + expect(keys).to eq(%i[size section]) end - it "should enumerate inner parameters" do + it 'should enumerate inner parameters' do keys = [] - config.section.each { |key, value| keys << key } - expect(keys).to eq([:size, :servers]) + config.section.each_key { |key| keys << key } + expect(keys).to eq(%i[size servers]) end - it "should have methods defined by Enumerable" do - expect(config.map { |key, value| key }).to eq([:size, :section]) + it 'should have methods defined by Enumerable' do + expect(config.map { |key, _value| key }).to eq(%i[size section]) end end - context "keys" do + context 'keys' do let(:config) do files = ["#{fixture_path}/development.yml"] Config.load_files(files) end - it "should return array of keys" do + it 'should return array of keys' do expect(config.keys).to contain_exactly(:size, :section) end - it "should return array of keys for nested entry" do + it 'should return array of keys for nested entry' do expect(config.section.keys).to contain_exactly(:size, :servers) end end @@ -442,8 +439,8 @@ end it 'should remove elements from settings' do - expect(config.array1).to eq(['item4', 'item5', 'item6']) - expect(config.array2.inner).to eq(['item4', 'item5', 'item6']) + expect(config.array1).to eq(%w[item4 item5 item6]) + expect(config.array2.inner).to eq(%w[item4 item5 item6]) expect(config.array3).to eq('') expect(config.string1).to eq('') expect(config.string2).to eq('') @@ -478,13 +475,12 @@ end it 'should remove elements from settings' do - expect(config.array1).to eq(['item4', 'item5', 'item6']) - expect(config.array2.inner).to eq(['item4', 'item5', 'item6']) + expect(config.array1).to eq(%w[item4 item5 item6]) + expect(config.array2.inner).to eq(%w[item4 item5 item6]) expect(config.array3).to eq([]) end end - context 'merging' do let(:config) do Config.overwrite_arrays = false @@ -502,7 +498,6 @@ expect(config.arraylist2.inner.size).to eq(6) end end - end end end diff --git a/spec/options_spec.rb b/spec/options_spec.rb index 03f7b94b..4a068523 100644 --- a/spec/options_spec.rb +++ b/spec/options_spec.rb @@ -114,12 +114,11 @@ it 'should overwrite the previous values' do expect(config['tvrage']['service_url']).to eq('http://url2') end - end context 'overwrite with Hash' do before do - config.add_source!({tvrage: {service_url: 'http://url3'}}) + config.add_source!({ tvrage: { service_url: 'http://url3' } }) config.reload! end @@ -159,9 +158,9 @@ end context 'source is a hash' do - let(:hash_source) { + let(:hash_source) do { tvrage: { service_url: 'http://url3' }, meaning_of_life: 42 } - } + end before do config.prepend_source!(hash_source) config.reload! @@ -213,7 +212,7 @@ end context '#key? and #has_key? methods' do - let(:config) { + let(:config) do config = Config.load_files("#{fixture_path}/empty1.yml") config.existing = nil config.send('complex_value=', nil) @@ -221,7 +220,7 @@ config.nested = Config.load_files("#{fixture_path}/empty2.yml") config.nested.existing = nil config - } + end it 'should test if a value exists for a given key' do expect(config.key?(:not_existing)).to eq(false) @@ -240,35 +239,38 @@ context 'when merge_hash_arrays options' do context 'is set to true' do - before { Config.setup { |cfg| - cfg.overwrite_arrays = false - cfg.merge_hash_arrays = true - } } + before do + Config.setup do |cfg| + cfg.overwrite_arrays = false + cfg.merge_hash_arrays = true + end + end it 'should merge the arrays' do config = Config.load_files("#{fixture_path}/deep_merge3/config1.yml", "#{fixture_path}/deep_merge3/config2.yml") expect(config.array.length).to eq(1) - expect(config.array[0].a).to eq("one") - expect(config.array[0].b).to eq("two") + expect(config.array[0].a).to eq('one') + expect(config.array[0].b).to eq('two') end end context 'is set to false' do - before { Config.setup { |cfg| - cfg.overwrite_arrays = false - cfg.merge_hash_arrays = false - } } + before do + Config.setup do |cfg| + cfg.overwrite_arrays = false + cfg.merge_hash_arrays = false + end + end it 'should merge the arrays' do config = Config.load_files("#{fixture_path}/deep_merge3/config1.yml", "#{fixture_path}/deep_merge3/config2.yml") expect(config.array.length).to eq(2) expect(config.array[0].b).to eq(nil) - expect(config.array[1].b).to eq("two") + expect(config.array[1].b).to eq('two') end end - end context 'when calling #as_json' do @@ -297,7 +299,7 @@ end it 'should return string when number specified with quotes' do - expect(config['number_in_quotes']).to eq("2.56") + expect(config['number_in_quotes']).to eq('2.56') end end end diff --git a/spec/sources/env_source_spec.rb b/spec/sources/env_source_spec.rb index 08511a30..5dccc82a 100644 --- a/spec/sources/env_source_spec.rb +++ b/spec/sources/env_source_spec.rb @@ -1,120 +1,122 @@ require 'spec_helper' -module Config::Sources - describe EnvSource do - context 'configuration options' do - before :each do - Config.reset - Config.env_prefix = nil - Config.env_separator = '.' - Config.env_converter = :downcase - Config.env_parse_values = true - end - - context 'default configuration' do - it 'should use global prefix configuration by default' do - Config.env_prefix = 'MY_CONFIG' - - source = EnvSource.new({ 'MY_CONFIG.ACTION_MAILER' => 'enabled' }) - results = source.load - expect(results['action_mailer']).to eq('enabled') - end - - it 'should use global separator configuration by default' do - Config.env_separator = '__' - - source = EnvSource.new({ 'Settings__ACTION_MAILER__ENABLED' => 'yes' }) - results = source.load - expect(results['action_mailer']['enabled']).to eq('yes') +module Config + module Sources + describe EnvSource do + context 'configuration options' do + before :each do + Config.reset + Config.env_prefix = nil + Config.env_separator = '.' + Config.env_converter = :downcase + Config.env_parse_values = true end - it 'should use global converter configuration by default' do - Config.env_converter = nil + context 'default configuration' do + it 'should use global prefix configuration by default' do + Config.env_prefix = 'MY_CONFIG' - source = EnvSource.new({ 'Settings.ActionMailer.Enabled' => 'yes' }) - results = source.load - expect(results['ActionMailer']['Enabled']).to eq('yes') - end + source = EnvSource.new({ 'MY_CONFIG.ACTION_MAILER' => 'enabled' }) + results = source.load + expect(results['action_mailer']).to eq('enabled') + end - it 'should use global parse_values configuration by default' do - Config.env_parse_values = false + it 'should use global separator configuration by default' do + Config.env_separator = '__' - source = EnvSource.new({ 'Settings.ACTION_MAILER.ENABLED' => 'true' }) - results = source.load - expect(results['action_mailer']['enabled']).to eq('true') - end - - describe 'arrays' do - before(:each) do - Config.env_parse_arrays = true + source = EnvSource.new({ 'Settings__ACTION_MAILER__ENABLED' => 'yes' }) + results = source.load + expect(results['action_mailer']['enabled']).to eq('yes') end - let(:source) do + it 'should use global converter configuration by default' do Config.env_converter = nil - EnvSource.new({ - 'Settings.SomeConfig.0.0' => 'value1', - 'Settings.SomeConfig.0.1' => 'value2', - 'Settings.SomeConfig.1.1' => 'value3', - 'Settings.SomeConfig.1.2' => 'value4', - 'Settings.MixedConfig.1.0' => 'value5', - 'Settings.MixedConfig.1.1' => 'value6', - 'Settings.MixedConfig.1.custom' => 'value7' - }) + + source = EnvSource.new({ 'Settings.ActionMailer.Enabled' => 'yes' }) + results = source.load + expect(results['ActionMailer']['Enabled']).to eq('yes') end - let(:results) { source.load } + it 'should use global parse_values configuration by default' do + Config.env_parse_values = false - context 'when loading nested configurations' do - it 'converts numeric-keyed hashes to arrays' do - expect(results['SomeConfig']).to be_an Array - expect(results['SomeConfig'][0]).to be_an Array - expect(results['SomeConfig'][0][0]).to eq('value1') - expect(results['SomeConfig'][0][1]).to eq('value2') + source = EnvSource.new({ 'Settings.ACTION_MAILER.ENABLED' => 'true' }) + results = source.load + expect(results['action_mailer']['enabled']).to eq('true') + end + + describe 'arrays' do + before(:each) do + Config.env_parse_arrays = true end - it 'retains hashes for non-sequential numeric keys' do - expect(results['SomeConfig'][1]).to be_a Hash - expect(results['SomeConfig'][1]['1']).to eq('value3') - expect(results['SomeConfig'][1]['2']).to eq('value4') + let(:source) do + Config.env_converter = nil + EnvSource.new({ + 'Settings.SomeConfig.0.0' => 'value1', + 'Settings.SomeConfig.0.1' => 'value2', + 'Settings.SomeConfig.1.1' => 'value3', + 'Settings.SomeConfig.1.2' => 'value4', + 'Settings.MixedConfig.1.0' => 'value5', + 'Settings.MixedConfig.1.1' => 'value6', + 'Settings.MixedConfig.1.custom' => 'value7' + }) end - it 'retains hashes for mixed types' do - expect(results['MixedConfig']['1']).to be_a Hash - expect(results['MixedConfig']['1']['0']).to eq('value5') - expect(results['MixedConfig']['1']['1']).to eq('value6') - expect(results['MixedConfig']['1']['custom']).to eq('value7') + let(:results) { source.load } + + context 'when loading nested configurations' do + it 'converts numeric-keyed hashes to arrays' do + expect(results['SomeConfig']).to be_an Array + expect(results['SomeConfig'][0]).to be_an Array + expect(results['SomeConfig'][0][0]).to eq('value1') + expect(results['SomeConfig'][0][1]).to eq('value2') + end + + it 'retains hashes for non-sequential numeric keys' do + expect(results['SomeConfig'][1]).to be_a Hash + expect(results['SomeConfig'][1]['1']).to eq('value3') + expect(results['SomeConfig'][1]['2']).to eq('value4') + end + + it 'retains hashes for mixed types' do + expect(results['MixedConfig']['1']).to be_a Hash + expect(results['MixedConfig']['1']['0']).to eq('value5') + expect(results['MixedConfig']['1']['1']).to eq('value6') + expect(results['MixedConfig']['1']['custom']).to eq('value7') + end end end end - end - context 'configuration overrides' do - it 'should allow overriding prefix configuration' do - source = EnvSource.new({ 'MY_CONFIG.ACTION_MAILER' => 'enabled' }, - prefix: 'MY_CONFIG') - results = source.load - expect(results['action_mailer']).to eq('enabled') - end + context 'configuration overrides' do + it 'should allow overriding prefix configuration' do + source = EnvSource.new({ 'MY_CONFIG.ACTION_MAILER' => 'enabled' }, + prefix: 'MY_CONFIG') + results = source.load + expect(results['action_mailer']).to eq('enabled') + end - it 'should allow overriding separator configuration' do - source = EnvSource.new({ 'Settings__ACTION_MAILER__ENABLED' => 'yes' }, - separator: '__') - results = source.load - expect(results['action_mailer']['enabled']).to eq('yes') - end + it 'should allow overriding separator configuration' do + source = EnvSource.new({ 'Settings__ACTION_MAILER__ENABLED' => 'yes' }, + separator: '__') + results = source.load + expect(results['action_mailer']['enabled']).to eq('yes') + end - it 'should allow overriding converter configuration' do - source = EnvSource.new({ 'Settings.ActionMailer.Enabled' => 'yes' }, - converter: nil) - results = source.load - expect(results['ActionMailer']['Enabled']).to eq('yes') - end + it 'should allow overriding converter configuration' do + source = EnvSource.new({ 'Settings.ActionMailer.Enabled' => 'yes' }, + converter: nil) + results = source.load + expect(results['ActionMailer']['Enabled']).to eq('yes') + end - it 'should allow overriding parse_values configuration' do - source = EnvSource.new({ 'Settings.ACTION_MAILER.ENABLED' => 'true' }, - parse_values: false) - results = source.load - expect(results['action_mailer']['enabled']).to eq('true') + it 'should allow overriding parse_values configuration' do + source = EnvSource.new({ 'Settings.ACTION_MAILER.ENABLED' => 'true' }, + parse_values: false) + results = source.load + expect(results['action_mailer']['enabled']).to eq('true') + end end end end diff --git a/spec/sources/hash_source_spec.rb b/spec/sources/hash_source_spec.rb index c6d22958..b7fda3e5 100644 --- a/spec/sources/hash_source_spec.rb +++ b/spec/sources/hash_source_spec.rb @@ -1,46 +1,48 @@ require 'spec_helper' -module Config::Sources - describe HashSource do - it "should take a hash as initializer" do - source = HashSource.new(foo: 5) - expect(source.hash).to eq(foo: 5) - end +module Config + module Sources + describe HashSource do + it 'should take a hash as initializer' do + source = HashSource.new(foo: 5) + expect(source.hash).to eq(foo: 5) + end - context "basic hash" do - let(:source) do - HashSource.new( - { - "size" => 2, - "section" => { - "size" => 3, - "servers" => [ {"name" => "yahoo.com"}, {"name" => "amazon.com"} ] + context 'basic hash' do + let(:source) do + HashSource.new( + { + 'size' => 2, + 'section' => { + 'size' => 3, + 'servers' => [{ 'name' => 'yahoo.com' }, { 'name' => 'amazon.com' }] + } } - } - ) - end + ) + end - it "should properly read the settings" do - results = source.load - expect(results["size"]).to eq(2) - end + it 'should properly read the settings' do + results = source.load + expect(results['size']).to eq(2) + end - it "should properly read nested settings" do - results = source.load - expect(results["section"]["size"]).to eq(3) - expect(results["section"]["servers"]).to be_instance_of(Array) - expect(results["section"]["servers"].size).to eq(2) + it 'should properly read nested settings' do + results = source.load + expect(results['section']['size']).to eq(3) + expect(results['section']['servers']).to be_instance_of(Array) + expect(results['section']['servers'].size).to eq(2) + end end - end - context "parameter is not a hash" do - let(:source) do - HashSource.new "hello world" - end + context 'parameter is not a hash' do + let(:source) do + HashSource.new 'hello world' + end - it "should return an empty hash" do - results = source.load - expect(results).to eq({}) + it 'should return an empty hash' do + results = source.load + expect(results).to eq({}) + end end end end diff --git a/spec/sources/yaml_source_spec.rb b/spec/sources/yaml_source_spec.rb index 429dd9a7..c7a24d98 100644 --- a/spec/sources/yaml_source_spec.rb +++ b/spec/sources/yaml_source_spec.rb @@ -1,142 +1,144 @@ require 'spec_helper' -module Config::Sources - describe YAMLSource do - it "should take a path as initializer" do - source = YAMLSource.new "somepath" - expect(source.path).to eq("somepath") - end - - context "basic yml file" do - let(:source) do - YAMLSource.new "#{fixture_path}/development.yml" - end - - it "should properly read the settings" do - results = source.load - expect(results["size"]).to eq(2) - end - - it "should properly read nested settings" do - results = source.load - expect(results["section"]["size"]).to eq(3) - expect(results["section"]["servers"]).to be_instance_of(Array) - expect(results["section"]["servers"].size).to eq(2) - end - end - - context "yml file with erb tags" do - let(:source) do - YAMLSource.new("#{fixture_path}/with_erb.yml") - end - - it "should properly evaluate the erb" do - results = source.load - expect(results["computed"]).to eq(6) +module Config + module Sources + describe YAMLSource do + it 'should take a path as initializer' do + source = YAMLSource.new 'somepath' + expect(source.path).to eq('somepath') end - it "should properly evaluate the nested erb settings" do - results = source.load - expect(results["section"]["computed1"]).to eq(1) - expect(results["section"]["computed2"]).to eq(2) - end - - context "with malformed erb tags" do + context 'basic yml file' do let(:source) do - YAMLSource.new("#{fixture_path}/with_malformed_erb.yml") + YAMLSource.new "#{fixture_path}/development.yml" end - it "should properly evaluate the erb" do - expect { - source.load - }.to raise_error(SyntaxError) + it 'should properly read the settings' do + results = source.load + expect(results['size']).to eq(2) end - end - end - - context "yaml file with erb tags but erb disabled" do - let(:source) do - YAMLSource.new("#{fixture_path}/with_erb.yml", evaluate_erb: false) - end - it "should load the file and leave the erb without being evaluated" do - results = source.load - expect(results["computed"]).to eq("<%= 1 + 2 + 3 %>") - expect(results["section"]["computed1"]).to eq("<%= \"1\" %>") + it 'should properly read nested settings' do + results = source.load + expect(results['section']['size']).to eq(3) + expect(results['section']['servers']).to be_instance_of(Array) + expect(results['section']['servers'].size).to eq(2) + end end - context "with global config" do + context 'yml file with erb tags' do let(:source) do YAMLSource.new("#{fixture_path}/with_erb.yml") end - around do |example| - original_evaluate_erb_in_yaml = Config.evaluate_erb_in_yaml - Config.evaluate_erb_in_yaml = false - example.run - Config.evaluate_erb_in_yaml = original_evaluate_erb_in_yaml + it 'should properly evaluate the erb' do + results = source.load + expect(results['computed']).to eq(6) end - it "should load the file and leave the erb without being evaluated" do + it 'should properly evaluate the nested erb settings' do results = source.load - expect(results["computed"]).to eq("<%= 1 + 2 + 3 %>") - expect(results["section"]["computed1"]).to eq("<%= \"1\" %>") + expect(results['section']['computed1']).to eq(1) + expect(results['section']['computed2']).to eq(2) + end + + context 'with malformed erb tags' do + let(:source) do + YAMLSource.new("#{fixture_path}/with_malformed_erb.yml") + end + + it 'should properly evaluate the erb' do + expect do + source.load + end.to raise_error(SyntaxError) + end end end - context "with malformed erb tags" do + context 'yaml file with erb tags but erb disabled' do let(:source) do - YAMLSource.new("#{fixture_path}/with_malformed_erb.yml", evaluate_erb: false) + YAMLSource.new("#{fixture_path}/with_erb.yml", evaluate_erb: false) + end + + it 'should load the file and leave the erb without being evaluated' do + results = source.load + expect(results['computed']).to eq('<%= 1 + 2 + 3 %>') + expect(results['section']['computed1']).to eq('<%= "1" %>') end - it "should properly evaluate the erb" do - expect { + context 'with global config' do + let(:source) do + YAMLSource.new("#{fixture_path}/with_erb.yml") + end + + around do |example| + original_evaluate_erb_in_yaml = Config.evaluate_erb_in_yaml + Config.evaluate_erb_in_yaml = false + example.run + Config.evaluate_erb_in_yaml = original_evaluate_erb_in_yaml + end + + it 'should load the file and leave the erb without being evaluated' do results = source.load - expect(results["malformed_erb"]).to eq("<%= = %>") - }.to_not raise_error + expect(results['computed']).to eq('<%= 1 + 2 + 3 %>') + expect(results['section']['computed1']).to eq('<%= "1" %>') + end end - end - end - context "missing yml file" do - let(:source) do - YAMLSource.new "somewhere_that_doesnt_exist.yml" + context 'with malformed erb tags' do + let(:source) do + YAMLSource.new("#{fixture_path}/with_malformed_erb.yml", evaluate_erb: false) + end + + it 'should properly evaluate the erb' do + expect do + results = source.load + expect(results['malformed_erb']).to eq('<%= = %>') + end.to_not raise_error + end + end end - it "should return an empty hash" do - results = source.load - expect(results).to eq({}) - end - end + context 'missing yml file' do + let(:source) do + YAMLSource.new 'somewhere_that_doesnt_exist.yml' + end - context "blank yml file" do - let(:source) do - YAMLSource.new "#{fixture_path}/empty1.yml" + it 'should return an empty hash' do + results = source.load + expect(results).to eq({}) + end end - it "should return an empty hash" do - results = source.load - expect(results).to eq({}) - end - end + context 'blank yml file' do + let(:source) do + YAMLSource.new "#{fixture_path}/empty1.yml" + end - context "malformed yml file" do - let(:source) do - YAMLSource.new "#{fixture_path}/malformed.yml" + it 'should return an empty hash' do + results = source.load + expect(results).to eq({}) + end end - it "should raise an useful exception" do - expect { source.load }.to raise_error(/malformed\.yml/) - end - end + context 'malformed yml file' do + let(:source) do + YAMLSource.new "#{fixture_path}/malformed.yml" + end - context "unsafe yml file" do - let(:source) do - YAMLSource.new "#{fixture_path}/unsafe_load.yml" + it 'should raise an useful exception' do + expect { source.load }.to raise_error(/malformed\.yml/) + end end - it "should load without any exception" do - expect { source.load }.not_to raise_error + context 'unsafe yml file' do + let(:source) do + YAMLSource.new "#{fixture_path}/unsafe_load.yml" + end + + it 'should load without any exception' do + expect { source.load }.not_to raise_error + end end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ed84b4cf..9a5b7d80 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -22,13 +22,13 @@ if ENV['APPRAISAL_INITIALIZED'] || ENV['GITHUB_ACTIONS'] app_name = File.basename(ENV['BUNDLE_GEMFILE'], '.gemfile') else - /.*?(?rails.*?)\.gemfile/ =~ Dir["gemfiles/rails*.gemfile"].sort.last + /.*?(?rails.*?)\.gemfile/ =~ Dir['gemfiles/rails*.gemfile'].max end ## # Load dummy application and Rspec # -app_framework = %w{rails sinatra}.find { |f| app_name.to_s.include?(f) } +app_framework = %w[rails sinatra].find { |f| app_name.to_s.include?(f) } case app_framework when 'rails' @@ -81,11 +81,10 @@ def fixture_path config.before(:suite) do Config.module_eval do - # Extend Config module with ability to reset configuration to the default values def self.reset # Clear any existing Settings constant and its sources to prevent mock leakage - current_const_name = self.const_name + current_const_name = const_name if Object.const_defined?(current_const_name) settings_instance = Object.const_get(current_const_name) # Clear the config sources to prevent mock doubles from leaking @@ -121,9 +120,10 @@ def self.reset puts "Gemfile: #{ENV['BUNDLE_GEMFILE']}" puts 'Version:' -Gem.loaded_specs.each { |name, spec| - puts "\t#{name}-#{spec.version}" if %w{rails activerecord-jdbcsqlite3-adapter sqlite3 rspec-rails sinatra}.include?(name) -} +Gem.loaded_specs.each do |name, spec| + puts "\t#{name}-#{spec.version}" if %w[rails activerecord-jdbcsqlite3-adapter sqlite3 rspec-rails + sinatra].include?(name) +end puts "\tpsych-#{Psych::VERSION}" puts diff --git a/spec/support/fixture_helper.rb b/spec/support/fixture_helper.rb index 739d07d2..6a020b0e 100644 --- a/spec/support/fixture_helper.rb +++ b/spec/support/fixture_helper.rb @@ -3,7 +3,7 @@ # module FixtureHelper - FIXTURE_PATH = File.expand_path('../../fixtures', __FILE__) + FIXTURE_PATH = File.expand_path('../fixtures', __dir__) # Provide fixture path as same way as rspec-rails def fixture_path diff --git a/spec/support/rails_helper.rb b/spec/support/rails_helper.rb index 2a3028b0..84570833 100644 --- a/spec/support/rails_helper.rb +++ b/spec/support/rails_helper.rb @@ -4,19 +4,15 @@ # Loads ENV vars from a yaml file def load_env(filename) - if filename and File.exist?(filename.to_s) - result = YAML.load(ERB.new(File.read(filename.to_s)).result) - end - result.each { |key, value| ENV[key.to_s] = value.to_s } unless result.nil? + result = YAML.load(ERB.new(File.read(filename.to_s)).result) if filename && File.exist?(filename.to_s) + result&.each { |key, value| ENV[key.to_s] = value.to_s } end # Checks if (default) Config const is already available def config_available? - where = caller[0].split(':')[0].gsub(File.expand_path(File.dirname(__FILE__)), '') + where = caller[0].split(':')[0].gsub(__dir__, '') - if defined?(::Settings) - puts "Config available in #{where}" - else - raise "Config not available in #{where}" - end + raise "Config not available in #{where}" unless defined?(::Settings) + + puts "Config available in #{where}" end diff --git a/spec/support/shared_contexts/rake.rb b/spec/support/shared_contexts/rake.rb index 72844110..1d171b27 100644 --- a/spec/support/shared_contexts/rake.rb +++ b/spec/support/shared_contexts/rake.rb @@ -1,9 +1,7 @@ shared_context 'rake' do - # include rails rake tasks before do require 'rake' load 'rails/tasks/engine.rake' end - end diff --git a/spec/tasks/db_spec.rb b/spec/tasks/db_spec.rb index aac87f9b..c9cea892 100644 --- a/spec/tasks/db_spec.rb +++ b/spec/tasks/db_spec.rb @@ -6,4 +6,4 @@ it 'has access to Settings object and can read databases from settings.yml file' do Rake::Task['db:create'].invoke end -end \ No newline at end of file +end diff --git a/spec/validation_spec.rb b/spec/validation_spec.rb index d04fd6a0..a2473efa 100644 --- a/spec/validation_spec.rb +++ b/spec/validation_spec.rb @@ -26,8 +26,8 @@ msg += " youtube.nonexist_field: is missing\n" msg += ' youtube.multiple_requirements: must be an integer' - expect { Config.load_files("#{fixture_path}/validation/config.yml") }. - to raise_error(Config::Validation::Error, Regexp.new(msg)) + expect { Config.load_files("#{fixture_path}/validation/config.yml") } + .to raise_error(Config::Validation::Error, Regexp.new(msg)) end it 'should work if validation passes' do @@ -41,8 +41,8 @@ config.validation_contract = contract.new end - expect { Config.load_files("#{fixture_path}/validation/config.yml") }. - to_not raise_error + expect { Config.load_files("#{fixture_path}/validation/config.yml") } + .to_not raise_error end end @@ -61,8 +61,8 @@ msg += " youtube.nonexist_field: is missing\n" msg += ' youtube.multiple_requirements: must be an integer' - expect { Config.load_files("#{fixture_path}/validation/config.yml") }. - to raise_error(Config::Validation::Error, Regexp.new(msg)) + expect { Config.load_files("#{fixture_path}/validation/config.yml") } + .to raise_error(Config::Validation::Error, Regexp.new(msg)) end it 'should work if validation passes' do @@ -74,8 +74,8 @@ end end - expect { Config.load_files("#{fixture_path}/validation/config.yml") }. - to_not raise_error + expect { Config.load_files("#{fixture_path}/validation/config.yml") } + .to_not raise_error end end end From 99c7e72a4aa76ef73e6e356282becff4021717f8 Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Wed, 28 Jan 2026 22:33:53 +0900 Subject: [PATCH 2/2] rubocop is installed properly --- config.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.gemspec b/config.gemspec index b1b5eb53..4f0cf6f9 100644 --- a/config.gemspec +++ b/config.gemspec @@ -32,6 +32,7 @@ Gem::Specification.new do |s| s.add_dependency 'ostruct' s.add_development_dependency 'rake', '~> 13.0', '>= 13.0.0' + s.add_development_dependency 'rubocop', '~> 1.84' # Testing s.add_development_dependency 'appraisal', '~> 2.5', '>= 2.5.0' @@ -58,6 +59,5 @@ Gem::Specification.new do |s| else # Static code analysis to be used locally s.add_development_dependency 'mdl', '~> 0.15', '>= 0.15.0' - s.add_development_dependency 'rubocop', '~> 1.84' end end