From 006914ac8b69e36e8410c4a6a695d516af0bf59b Mon Sep 17 00:00:00 2001 From: Bruno Costanzo Date: Thu, 13 Feb 2025 19:11:51 +0100 Subject: [PATCH 1/2] object class implementation --- lib/ruber.rb | 1 + lib/ruber/object.rb | 41 +++++++++++++++++++++++++++++++++++++++ test/ruber/object_test.rb | 36 ++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 lib/ruber/object.rb create mode 100644 test/ruber/object_test.rb 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..c7f9fcb --- /dev/null +++ b/lib/ruber/object.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Ruber + class Object + attr_reader :data + + def initialize(attributes) + @data = to_data_object(attributes) + end + + def to_data_object(obj) + if obj.is_a?(Hash) + wrapped = obj.transform_values { |val| to_data_object(val) } + + 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(name) + super unless @data.respond_to?(name) + + @data.public_send(name) + end + + def method_missing(name, *args) + super unless @data.respond_to?(name) + + result = @data.public_send(name, *args) + + result.is_a?(Data) ? self.class.new(result.to_h) : result + 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 From 31c07d600a9b10421d43b81510b4f0224adacb6e Mon Sep 17 00:00:00 2001 From: Bruno Costanzo Date: Fri, 14 Feb 2025 13:55:23 +0100 Subject: [PATCH 2/2] code suggestions --- lib/ruber/object.rb | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/ruber/object.rb b/lib/ruber/object.rb index c7f9fcb..f358af9 100644 --- a/lib/ruber/object.rb +++ b/lib/ruber/object.rb @@ -2,15 +2,17 @@ module Ruber class Object - attr_reader :data - def initialize(attributes) @data = to_data_object(attributes) end def to_data_object(obj) if obj.is_a?(Hash) - wrapped = obj.transform_values { |val| to_data_object(val) } + 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) @@ -22,18 +24,10 @@ def to_data_object(obj) private - def method(name) - super unless @data.respond_to?(name) - - @data.public_send(name) - end - def method_missing(name, *args) super unless @data.respond_to?(name) - result = @data.public_send(name, *args) - - result.is_a?(Data) ? self.class.new(result.to_h) : result + @data.public_send(name, *args) end def respond_to_missing?(name, *args) = @data.respond_to?(name) || super