From ed747f6690050b6b181d420a43d55ff68df9cede Mon Sep 17 00:00:00 2001 From: telomelonia Date: Tue, 15 Jul 2025 09:58:00 +0900 Subject: [PATCH 1/2] upgrade the ruby to 3.4.4 --- .github/workflows/ci.yml | 4 ++-- .rubocop.yml | 2 +- .ruby-version | 2 +- microcms.gemspec | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19f96af..079b7de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: - name: Setup Ruby and install gems uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7 + ruby-version: 3.4.4 bundler-cache: true - name: Run linters @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: [2.6, 2.7, 3.0] + ruby-version: [2.6, 2.7, 3.0, 3.4.4] steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/.rubocop.yml b/.rubocop.yml index 2fbb3c9..84aecf4 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,5 @@ AllCops: - TargetRubyVersion: 2.6 + TargetRubyVersion: 3.0 NewCops: enable Metrics/BlockLength: diff --git a/.ruby-version b/.ruby-version index 37c2961..f989260 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.2 +3.4.4 diff --git a/microcms.gemspec b/microcms.gemspec index 9fc6652..cf5b3a0 100644 --- a/microcms.gemspec +++ b/microcms.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |spec| spec.summary = 'microCMS Ruby SDK' spec.description = 'microCMS Ruby SDK' spec.homepage = 'https://github.com/microcmsio/microcms-ruby-sdk' - spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0') + spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0') spec.metadata['homepage_uri'] = spec.homepage spec.metadata['source_code_uri'] = spec.homepage From f91eaf04c921a1a521fa78ee7dc48073282883a1 Mon Sep 17 00:00:00 2001 From: telomelonia Date: Tue, 15 Jul 2025 10:38:09 +0900 Subject: [PATCH 2/2] refactor: replace the openStruct --- .github/workflows/ci.yml | 2 +- .rubocop.yml | 4 -- lib/microcms.rb | 111 ++++++++++++++++++++++++++++++++++++++- microcms.gemspec | 2 +- spec/microcms_spec.rb | 12 ++--- test_response_object.rb | 41 +++++++++++++++ 6 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 test_response_object.rb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 079b7de..0727243 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: [2.6, 2.7, 3.0, 3.4.4] + ruby-version: [3.2, 3.3, 3.4.4] steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/.rubocop.yml b/.rubocop.yml index 84aecf4..2e442bc 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -5,7 +5,3 @@ AllCops: Metrics/BlockLength: Exclude: - 'spec/**/*' - -Style/OpenStructUse: - Exclude: - - 'spec/**/*' diff --git a/lib/microcms.rb b/lib/microcms.rb index a603d59..71fcc36 100644 --- a/lib/microcms.rb +++ b/lib/microcms.rb @@ -20,6 +20,99 @@ def client end end + # ResponseObject: replacement for OpenStruct + class ResponseObject + def initialize(hash = {}) + @data = hash.transform_keys(&:to_sym) + @data.each do |key, value| + @data[key] = convert_value(value) + end + end + + def ==(other) + case other + when ResponseObject + @data == other.instance_variable_get(:@data) + when Hash + @data == other.transform_keys(&:to_sym) + else + false + end + end + + def to_h + @data.transform_values { |value| + case value + when ResponseObject + value.to_h + when Array + value.map { |item| item.is_a?(ResponseObject) ? item.to_h : item } + else + value + end + } + end + + def [](key) + @data[key.to_sym] + end + + def []=(key, value) + @data[key.to_sym] = convert_value(value) + end + + def method_missing(method_name, *args, &block) + method_str = method_name.to_s + + if method_str.end_with?('=') + key = method_str.chomp('=').to_sym + @data[key] = convert_value(args.first) + elsif @data.key?(method_name) + @data[method_name] + else + super + end + end + + def respond_to_missing?(method_name, include_private = false) + method_str = method_name.to_s + method_str.end_with?('=') || @data.key?(method_name) || super + end + + def delete_field(key) + @data.delete(key.to_sym) + end + + def keys + @data.keys + end + + def values + @data.values + end + + def each(&block) + @data.each(&block) + end + + def inspect + "#<#{self.class.name} #{@data.inspect}>" + end + + private + + def convert_value(value) + case value + when Hash + ResponseObject.new(value) + when Array + value.map { |item| convert_value(item) } + else + value + end + end + end + # HttpUtil module HttpUtil def send_http_request(method, endpoint, path, query = nil, body = nil) @@ -30,7 +123,7 @@ def send_http_request(method, endpoint, path, query = nil, body = nil) raise APIError.new(status_code: res.code.to_i, body: res.body) if res.code.to_i >= 400 - JSON.parse(res.body, object_class: OpenStruct) if res.header['Content-Type'].include?('application/json') # rubocop:disable Style/OpenStructUse + parse_json_response(res.body) if res.header['Content-Type'].include?('application/json') end private @@ -75,6 +168,22 @@ def build_http(uri) http end + + def parse_json_response(body) + parsed = JSON.parse(body) + convert_to_object(parsed) + end + + def convert_to_object(obj) + case obj + when Hash + ResponseObject.new(obj) + when Array + obj.map { |item| convert_to_object(item) } + else + obj + end + end end # Client diff --git a/microcms.gemspec b/microcms.gemspec index cf5b3a0..0cf356c 100644 --- a/microcms.gemspec +++ b/microcms.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |spec| spec.summary = 'microCMS Ruby SDK' spec.description = 'microCMS Ruby SDK' spec.homepage = 'https://github.com/microcmsio/microcms-ruby-sdk' - spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0') + spec.required_ruby_version = Gem::Requirement.new('>= 3.4.4') spec.metadata['homepage_uri'] = spec.homepage spec.metadata['source_code_uri'] = spec.homepage diff --git a/spec/microcms_spec.rb b/spec/microcms_spec.rb index 2979202..4880a99 100644 --- a/spec/microcms_spec.rb +++ b/spec/microcms_spec.rb @@ -72,7 +72,7 @@ res = client.list('endpoint') - expect(res.contents).to eq [OpenStruct.new(content)] + expect(res.contents).to eq [MicroCMS::ResponseObject.new(content)] end end @@ -87,7 +87,7 @@ res = client.get('endpoint', 'foo') - expect(res).to eq OpenStruct.new(content) + expect(res).to eq MicroCMS::ResponseObject.new(content) end end @@ -104,7 +104,7 @@ res = client.create('endpoint', { text: 'Hello, new content!' }) - expect(res).to eq OpenStruct.new({ id: 'bar' }) + expect(res).to eq MicroCMS::ResponseObject.new({ id: 'bar' }) end end @@ -122,7 +122,7 @@ res = client.create('endpoint', { id: 'bar', text: 'Hello, new content!' }) - expect(res).to eq OpenStruct.new({ id: 'bar' }) + expect(res).to eq MicroCMS::ResponseObject.new({ id: 'bar' }) end end @@ -140,7 +140,7 @@ res = client.create('endpoint', { text: 'Hello, new content!' }, { status: 'draft' }) - expect(res).to eq OpenStruct.new({ id: 'bar' }) + expect(res).to eq MicroCMS::ResponseObject.new({ id: 'bar' }) end end @@ -158,7 +158,7 @@ res = client.update('endpoint', { id: 'bar', text: 'Hello, new content!' }) - expect(res).to eq OpenStruct.new({ id: 'bar' }) + expect(res).to eq MicroCMS::ResponseObject.new({ id: 'bar' }) end end diff --git a/test_response_object.rb b/test_response_object.rb new file mode 100644 index 0000000..d5fca61 --- /dev/null +++ b/test_response_object.rb @@ -0,0 +1,41 @@ +#!/usr/bin/env ruby + +# Simple test to verify ResponseObject functionality +require_relative 'lib/microcms' + +# Test ResponseObject creation and access +puts "Testing ResponseObject..." + +# Test 1: Basic creation and access +response = MicroCMS::ResponseObject.new({ id: 'test123', name: 'Test Article' }) +puts "✓ Basic creation: #{response.id} - #{response.name}" + +# Test 2: Nested objects +nested_data = { + id: 'article1', + title: 'Hello World', + author: { + id: 'author1', + name: 'John Doe' + }, + tags: ['ruby', 'programming'] +} + +nested_response = MicroCMS::ResponseObject.new(nested_data) +puts "✓ Nested access: #{nested_response.author.name}" +puts "✓ Array access: #{nested_response.tags}" + +# Test 3: Equality comparison +response1 = MicroCMS::ResponseObject.new({ id: 'test' }) +response2 = MicroCMS::ResponseObject.new({ id: 'test' }) +puts "✓ Equality test: #{response1 == response2}" + +# Test 4: Hash conversion +hash_result = nested_response.to_h +puts "✓ Hash conversion: #{hash_result[:author][:name]}" + +# Test 5: delete_field functionality +response.delete_field(:name) +puts "✓ Delete field test: name should be nil: #{response.name.nil?}" + +puts "\nAll ResponseObject tests passed! ✅"