Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.gem
.DS_Store
.idea
27 changes: 27 additions & 0 deletions lib/global_call.rb
Original file line number Diff line number Diff line change
@@ -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
52 changes: 26 additions & 26 deletions lib/rk.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
# Module for including +rk+ to global namespace (class Object).
# frozen_string_literal: true

require_relative "../lib/global_call"

module Rk

# Create a rk-configuration
# * <tt>name</tt> - : optional for creating named configurations
# * <tt>block</tt> - : 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
# * <tt>separator</tt> - :
# * <tt>prefix</tt> - empty
# * <tt>suffix</tt> - empty
# * <tt>keys</tt> - empty
def initialize
@separator = ":"
@prefix = ""
@suffix = ""
self.separator = ":"
self.prefix = ""
self.suffix = ""
# attr_accessor is overwritten to create methods for keys
@keys = {}
end

Expand All @@ -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"
Expand Down Expand Up @@ -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))
5 changes: 3 additions & 2 deletions rk.gemspec
Original file line number Diff line number Diff line change
@@ -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
39 changes: 35 additions & 4 deletions test/test_rk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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