Skip to content
This repository has been archived by the owner on Dec 8, 2020. It is now read-only.

Commit

Permalink
Fix adding custom context to current context (#54)
Browse files Browse the repository at this point in the history
* Fix adding custom context to current context

* The data hash would lose custom context information
  since merging was not happening in place.

* Add CurrentContext specs
  • Loading branch information
austenito authored and binarylogic committed Mar 4, 2017
1 parent ea41997 commit 7ebff4e
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 22 deletions.
61 changes: 39 additions & 22 deletions lib/timber/current_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ def add(*args)
instance.add(*args)
end

def hash(*args)
instance.hash(*args)
end

# Convenience method for {#remove}. See {#remove} for full details and examples.
def remove(*args)
instance.remove(*args)
end

def hash(*args)
instance.hash(*args)
def reset(*args)
instance.reset(*args)
end
end

Expand All @@ -56,18 +60,11 @@ def hash(*args)
#
# @example Adding multiple contexts
# Timber::CurrentContext.with(context1, context2) { ... }
def with(*contexts)
add(*contexts)
def with(*objects)
add(*objects)
yield
ensure
contexts.each do |context|
if context.keyspace == :custom
# Custom contexts are merged and should be removed the same
hash[context.keyspace].delete(context.type)
else
remove(context)
end
end
remove(*objects)
end

# Adds contexts but does not remove them. See {#with} for automatic maintenance and {#remove}
Expand All @@ -83,31 +80,51 @@ def add(*objects)
if key == :custom
# Custom contexts are merged into the space
hash[key] ||= {}
hash[key].merge(json)
hash[key].merge!(json)
else
hash[key] = json
end
end
end

# Removes a context. This must be a {Timber::Context} type. See {Timber::Contexts} for a list.
# If you wish to remove by key, or some other way, use {#hash} and modify the hash accordingly.
def remove(*contexts)
contexts.each do |context|
hash.delete(context.keyspace)
end
end

# The internal hash that is maintained. It is recommended that you use {#with} and {#add}
# for hash maintenance.
def hash
Thread.current[THREAD_NAMESPACE] ||= {}
end

# Removes a context. If you wish to remove by key, or some other way, use {#hash} and
# modify the hash accordingly.
def remove(*objects)
objects.each do |object|
if object.is_a?(Symbol)
hash.delete(object)
else
context = Contexts.build(object)

if context.keyspace == :custom
# Custom contexts are merged and should be removed the same
hash[context.keyspace].delete(context.type)
if hash[context.keyspace] == {}
hash.delete(context.keyspace)
end
else
hash.delete(context.keyspace)
end
end
end
end

# Resets the context to be blank. Use this carefully! This will remove *any* context,
# include context that is automatically included with Timber.
def reset
hash.clear
end

# Snapshots the current context so that you get a moment in time representation of the context,
# since the context can change as execution proceeds.
def snapshot
hash.clone
end
end
end
end
57 changes: 57 additions & 0 deletions spec/timber/current_context_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
require "spec_helper"

describe Timber::CurrentContext, :rails_23 => true do
describe ".add" do
after(:each) do
described_class.reset
end

it "should add the context" do
expect(described_class.hash).to eq({})

described_class.add({build: {version: "1.0.0"}})
expect(described_class.hash).to eq({:custom=>{:build=>{:version=>"1.0.0"}}})

described_class.add({testing: {key: "value"}})
expect(described_class.hash).to eq({:custom=>{:build=>{:version=>"1.0.0"}, :testing=>{:key=>"value"}}})
end
end

describe ".remove" do
it "should remove the context by object" do
context = {:build=>{:version=>"1.0.0"}}
described_class.add(context)
expect(described_class.hash).to eq({:custom => context})

described_class.remove(context)
expect(described_class.hash).to eq({})
end

it "should remove context by key" do
context = {:build=>{:version=>"1.0.0"}}
described_class.add(context)
expect(described_class.hash).to eq({:custom => context})

described_class.remove(:custom)
expect(described_class.hash).to eq({})
end
end

describe ".with" do
it "should merge the context and cleanup on block exit" do
expect(described_class.hash).to eq({})

described_class.with({build: {version: "1.0.0"}}) do
expect(described_class.hash).to eq({:custom=>{:build=>{:version=>"1.0.0"}}})

described_class.with({testing: {key: "value"}}) do
expect(described_class.hash).to eq({:custom=>{:build=>{:version=>"1.0.0"}, :testing=>{:key=>"value"}}})
end

expect(described_class.hash).to eq({:custom=>{:build=>{:version=>"1.0.0"}}})
end

expect(described_class.hash).to eq({})
end
end
end

0 comments on commit 7ebff4e

Please sign in to comment.