diff --git a/lib/ruber.rb b/lib/ruber.rb index 24282f7..6f76433 100644 --- a/lib/ruber.rb +++ b/lib/ruber.rb @@ -10,6 +10,7 @@ module Ruber autoload :Client, "ruber/client" autoload :Error, "ruber/error" autoload :Authenticator, "ruber/authenticator" + autoload :Object, "ruber/object" DEFAULT_API_BASE = "https://api.uber.com/v1" diff --git a/lib/ruber/object.rb b/lib/ruber/object.rb new file mode 100644 index 0000000..f358af9 --- /dev/null +++ b/lib/ruber/object.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Ruber + class Object + def initialize(attributes) + @data = to_data_object(attributes) + end + + def to_data_object(obj) + if obj.is_a?(Hash) + wrapped = obj.transform_values do |val| + result = to_data_object(val) + + result.is_a?(Data) ? self.class.new(result.to_h) : result + end + + Data.define(*wrapped.keys).new(**wrapped) + elsif obj.is_a?(Array) + obj.map { |o| to_data_object(o) } + else + obj + end + end + + private + + def method_missing(name, *args) + super unless @data.respond_to?(name) + + @data.public_send(name, *args) + end + + def respond_to_missing?(name, *args) = @data.respond_to?(name) || super + end +end diff --git a/test/ruber/object_test.rb b/test/ruber/object_test.rb new file mode 100644 index 0000000..06ec3ca --- /dev/null +++ b/test/ruber/object_test.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require File.expand_path("../test_helper", __dir__) + +module Ruber + class ObjectTest < Minitest::Test + def test_creating_object_from_hash + assert_equal "bar", Ruber::Object.new(foo: "bar").foo + end + + def test_nested_hash + assert_equal "foobar", Ruber::Object.new(foo: { bar: { baz: "foobar" } }).foo.bar.baz + end + + def test_nested_number + assert_equal 1, Ruber::Object.new(foo: { bar: 1 }).foo.bar + end + + def test_array + object = Ruber::Object.new(foo: [{ bar: :baz }]) + assert_equal :baz, object.foo.first.bar + end + + def test_respond_to_missing + assert_respond_to Ruber::Object.new(foo: "bar"), :foo + end + + def test_invalid_method + assert_raises(NoMethodError) { Ruber::Object.new(foo: "bar").invalid } + end + + def test_respond_with_ruber_object + assert_instance_of Ruber::Object, Ruber::Object.new(foo: { bar: "baz" }).foo + end + end +end