diff --git a/.gitignore b/.gitignore index f1d7f5e..b3f02c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.gem .DS_Store +.idea diff --git a/lib/global_call.rb b/lib/global_call.rb new file mode 100644 index 0000000..6621ebf --- /dev/null +++ b/lib/global_call.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Rk + # Anonymous module for including +rk+ to global namespace (class Object). + class GlobalCall < Module + def initialize(rk_instance) + rk_name = if rk_instance.rk_name.to_s.empty? + "rk" + else + "#{rk_instance.rk_name}_rk" + end + + $_rk ||= {} + $_rk[rk_name] = rk_instance + + super() do + define_method rk_name do |*elements| + if elements.empty? + $_rk[rk_name] + else + $_rk[rk_name].rk(elements) + end + end + end + end + end +end diff --git a/lib/rk.rb b/lib/rk.rb index bf72964..5f4a5ce 100644 --- a/lib/rk.rb +++ b/lib/rk.rb @@ -1,10 +1,24 @@ -# Module for including +rk+ to global namespace (class Object). +# frozen_string_literal: true + +require_relative "../lib/global_call" + module Rk + # Create a rk-configuration + # * name - : optional for creating named configurations + # * block - : optional for setting configurations for details see Rk#initialize + def self.configure(name = nil) + instance = Rk.new + instance.rk_name = name + yield(instance) if block_given? + + Object.include(GlobalCall.new(instance)) + end + # Build Redis keys of several elements. # rk("user", 10) => "user:10" class Rk - attr_accessor :separator, :prefix, :suffix, :keys + attr_accessor :separator, :prefix, :suffix, :keys, :rk_name # Set defaults # * separator - : @@ -12,9 +26,10 @@ class Rk # * suffix - empty # * keys - empty def initialize - @separator = ":" - @prefix = "" - @suffix = "" + self.separator = ":" + self.prefix = "" + self.suffix = "" + # attr_accessor is overwritten to create methods for keys @keys = {} end @@ -28,7 +43,9 @@ def rk(*elements) # rk(rk.user, 10) => "user:10" def method_missing(method, *arg) # Raise an error if a method gets accessed which was not defined before - raise RuntimeError, "'rk.#{method.to_s}' is undefined" unless method.to_s.include?("=") + unless method.to_s.include?("=") + return super + end # Define a method to return a value as set, for example rk.settings = 'set' defines # a method called "settings" which returns the string "set" @@ -58,27 +75,10 @@ def keys=(h) self.send("#{key}=", val) end end - end # class Rk - - # Create and call a global instance of Rk to either build a key or set/get attributes. - def rk(*elements) - $_rk = Rk.new unless $_rk - - # Differ between calling "rk" without/with params - if elements.empty? - # Return instance of Rk for calling methods like "rk.separator" - $_rk - else - # Return key build by Rk.rk - $_rk.rk(elements) - end - end - end # module Rk +# Create a default rk to use it without configuring anything # We could use +extend Rk+ to extend only +main+, but we would have to +include Rk+ in -# any class, hence we include Rk to the global object. -class Object - include Rk -end +# any class, hence we include Rk to the global object +Object.include(Rk::GlobalCall.new(Rk::Rk.new)) diff --git a/rk.gemspec b/rk.gemspec index 6e67d63..e2b7cb6 100644 --- a/rk.gemspec +++ b/rk.gemspec @@ -1,12 +1,13 @@ Gem::Specification.new do |g| g.name = "rk" g.version = "1.1.0" - g.date = "2016-12-21" g.summary = "Redis key builder" g.description = "Ruby helper to generate keys for Redis" g.authors = ["Oliver Mensinger"] g.email = "oliver.mensinger@gmail.com" - g.files = ["lib/rk.rb"] + g.files = %w[lib/global_call.rb lib/rk.rb] g.homepage = "https://github.com/omensinger/rk" g.license = "MIT" + + g.add_development_dependency "minitest" end diff --git a/test/test_rk.rb b/test/test_rk.rb index 7a1ed4a..5bdfa4f 100644 --- a/test/test_rk.rb +++ b/test/test_rk.rb @@ -18,9 +18,11 @@ def key let(:keys) { { user: "user", "statistics" => "stats", "session" => :sess } } def setup - rk.separator = ":" - rk.prefix = "" - rk.suffix = "" + Rk.configure do |config| + config.separator = ":" + config.prefix = "" + config.suffix = "" + end end def test_simple_key @@ -60,7 +62,7 @@ def test_use_defined_key_element end def test_use_undefined_key_element - assert_raises RuntimeError do + assert_raises NoMethodError do rk.something end end @@ -86,4 +88,33 @@ def test_get_keys assert_equal keys_as_strings, rk.keys end + def test_can_access_config_attributes + Rk.configure("test") do |config| + config.separator = ":" + config.prefix = "pre" + config.suffix = "suf" + end + + assert_equal ":", test_rk.separator + assert_equal "pre", test_rk.prefix + assert_equal "suf", test_rk.suffix + assert_equal "test", test_rk.rk_name + end + + def test_allow_second_setting + Rk.configure("foo") do |config| + config.separator = "-" + end + + assert_equal "-", foo_rk.separator + assert_equal ":", rk.separator + end + + def test_named_rk_creates_key + Rk.configure("foo") do |config| + config.prefix = "foo" + config.separator = "-" + end + assert_equal "foo-bar", foo_rk("bar") + end end