Skip to content

Commit

Permalink
feat: Add hash access and equality support to LDContext (#241)
Browse files Browse the repository at this point in the history
  • Loading branch information
keelerm84 authored Jan 3, 2024
1 parent 3eee921 commit 1ba6bde
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/ldclient-rb/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,18 @@ def individual_context(kind)
nil
end

#
# An LDContext can be compared to other LDContexts or to a hash object. If
# a hash is provided, it is first converted to an LDContext using the
# `LDContext.create` method.
#
# @param other [LDContext, Hash]
# @return [Boolean]
#
def ==(other)
other = LDContext.create(other) if other.is_a? Hash
return false unless other.is_a? LDContext

return false unless self.kind == other.kind
return false unless self.valid? == other.valid?
return false unless self.error == other.error
Expand All @@ -308,6 +319,21 @@ def ==(other)
end
alias eql? ==

#
# For a single-kind context, the provided key will return the attribute value specified. This is the same as calling
# `LDCotnext.get_value`.
#
# For multi-kind contexts, the key will be interpreted as a context kind. If the multi-kind context has an
# individual context of that kind, it will be returned. Otherwise, this method will return nil. This behaves the
# same as calling `LDContext.individual_context`.
#
# @param key [Symbol, String]
#
def [](key)
return nil unless key.is_a? Symbol or key.is_a? String
multi_kind? ? individual_context(key.to_s) : get_value(key)
end

#
# Retrieve the value of any top level, addressable attribute.
#
Expand Down
70 changes: 70 additions & 0 deletions spec/context_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,44 @@ module LaunchDarkly
end
end

describe "hash-like behavior" do
it "multi-kind contexts return nested contexts" do
user_context = subject.create({ key: "user-key", kind: "user" })
org_context = subject.create({ key: "org-key", kind: "org" })
multi_context = subject.create_multi([user_context, org_context])

expect(multi_context.valid?).to be true
expect(multi_context["user"]).to eq(user_context)
expect(multi_context["org"]).to eq(org_context)
expect(multi_context["no-such-type"]).to be_nil
end

describe "single-kind contexts" do
it "can retrieve the correct simple attribute value" do
context = subject.create({ key: "my-key", kind: "org", name: "x", :"my-attr" => "y", :"/starts-with-slash" => "z" })

expect(context["kind"]).to eq("org")
expect(context["key"]).to eq("my-key")
expect(context["name"]).to eq("x")
expect(context["my-attr"]).to eq("y")
expect(context["/starts-with-slash"]).to eq("z")
expect(context["a-value-that-is-not-set"]).to be_nil
end

it "cannot query subpath/elements" do
object_value = { a: 1 }
array_value = [1]

context = subject.create({ key: "my-key", kind: "org", :"obj-attr" => object_value, :"array-attr" => array_value })
expect(context["obj-attr"]).to eq(object_value)
expect(context[:"array-attr"]).to eq(array_value)

expect(context[:"/obj-attr/a"]).to be_nil
expect(context[:"/array-attr/0"]).to be_nil
end
end
end

describe "value retrieval" do
describe "supports simple attribute retrieval" do
it "can retrieve the correct simple attribute value" do
Expand Down Expand Up @@ -298,6 +336,38 @@ module LaunchDarkly
end

describe "equality comparisons" do
it "wrong types are not equal" do
context = subject.create({ key: 'context-key', kind: 'user' })
expect(context).to_not eq(true)
expect(context).to_not eq(3)
end

it "single-kind context can compare with hash" do
hash = { key: 'context-key', kind: 'user', name: 'Example name', groups: ['test', 'it', 'here'], address: {street: '123 Easy St', city: 'Every Town'},
_meta: { privateAttributes: ['name', 'out of order attribute'] }
}
context = subject.create(hash)
expect(context).to eq(hash)
end

it "multi-kind context can compare with hash" do
hash = {
kind: "multi",
org: { key: 'org-key', kind: 'org' },
user: { key: 'user-key', kind: 'user' },
device: { key: 'device-key', kind: 'device' },
}
org_context = subject.create(hash[:org])
user_context = subject.create(hash[:user])
device_context = subject.create(hash[:device])
context = subject.create(hash)

expect(context).to eq(hash)
expect(context["org"]).to eq(hash[:org])
expect(context["user"]).to eq(hash[:user])
expect(context["device"]).to eq(hash[:device])
end

it "single kind contexts are equal" do
original_context = subject.create(
{ key: 'context-key', kind: 'user', name: 'Example name', groups: ['test', 'it', 'here'], address: {street: '123 Easy St', city: 'Every Town'},
Expand Down

0 comments on commit 1ba6bde

Please sign in to comment.