Skip to content

Conversation

@bolom
Copy link
Contributor

@bolom bolom commented Nov 15, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Added customer management operations: create, retrieve, list, and update customers.
    • Added wallet and virtual account operations accessible through customer resources.
    • Enabled simplified resource accessor patterns for streamlined API interactions.
  • Improvements

    • Enhanced API response handling with improved object transformation and nested item conversion.
    • Improved datetime parsing across resources for consistency.
  • Dependencies

    • Added environment configuration support via new dependency.

✏️ Tip: You can customize this high-level summary in your review settings.

bolom and others added 2 commits November 12, 2025 08:37
- Reduced Util module from 113+ lines to under 100 lines to satisfy rubocop Metrics/ModuleLength
- Fixed assignment in condition warnings by using proper parentheses
- Replaced method-based constants with frozen constants for better performance
- Removed redundant methods and consolidated logic for better maintainability
- Used Object.const_get() to properly handle resource constant loading
- Improved code efficiency with transform_keys and transform_values
- Organized bridge_api.rb to properly load service files

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
…f response wrapper

- Updated CustomerService#retrieve to return a Customer object directly when successful
- Modified example script to handle the new direct Customer object return behavior
- Preserved error handling to still return Response object for error cases
@coderabbitai
Copy link

coderabbitai bot commented Nov 15, 2025

Warning

Rate limit exceeded

@bolom has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 58 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 698e38e and 94c0f56.

📒 Files selected for processing (1)
  • lib/bridge_api/services/webhook_service.rb (1 hunks)

Walkthrough

This pull request introduces a service layer architecture for Bridge API operations, refactors resource object conversion logic with pattern-matching in util.rb, adds dynamic resource accessors to the client for per-resource CRUD operations, implements multiple new service classes (customer, wallet, virtual account, KYC link, external account, webhook), and adds datetime parsing helpers across resource classes.

Changes

Cohort / File(s) Summary
Service Layer Foundation
lib/bridge_api.rb, lib/bridge_api/services/base_service.rb
Added requires for new service classes; introduced BaseService as parent class with client storage and protected request delegation supporting idempotency keys.
CRUD Service Implementations
lib/bridge_api/services/customer_service.rb, lib/bridge_api/services/kyc_link_service.rb, lib/bridge_api/services/wallet_service.rb, lib/bridge_api/services/external_account_service.rb, lib/bridge_api/services/virtual_account_service.rb, lib/bridge_api/services/webhook_service.rb
Added six new service classes inheriting from BaseService; each encapsulates resource-specific operations (create, retrieve, list, get, update) with HTTP verb delegation.
Client Resource Accessor Pattern
lib/bridge_api/client.rb
Introduced ResourceAccessor nested class to encapsulate per-resource operations; added dynamic resource accessor methods for each RESOURCE with list/get/retrieve/create/update/delete workflows; added private define_resource_accessor class method.
Object Conversion & Utility Refactoring
lib/bridge_api/util.rb
Replaced object_classes lookup with frozen OBJECT_CLASS_NAMES and RESOURCE_PATTERNS constants; refactored public convert_to_bridged_object; added convert_list_object, detect_resource_type_from_object_field, detect_resource_type, construct_resource; introduced private symbolize_keys helper.
List Operation Response Transformation
lib/bridge_api/api_operations.rb
Modified List::ClassMethods to convert successful responses via BridgeApi::Util.convert_to_bridged_object with resource_hint instead of returning raw response.
Resource Datetime Parsing Helpers
lib/bridge_api/resources/customer.rb, lib/bridge_api/resources/kyc_link.rb, lib/bridge_api/resources/reward_rate.rb, lib/bridge_api/resources/transaction_history.rb, lib/bridge_api/resources/webhook_event.rb, lib/bridge_api/resources/webhook_event_delivery_log.rb
Added private parse_datetime helper method across multiple resource files for safe Time parsing with nil handling and ArgumentError rescue.
Resource Method Enhancements
lib/bridge_api/resources/customer.rb
Removed explicit id/email/first_name/last_name accessors; added created_at/updated_at datetime accessors; added wallet/virtual_account operation methods (wallets, create_wallet, get_wallet, virtual_accounts, get_virtual_account, create_virtual_account).
Webhook Resource Refactoring
lib/bridge_api/resources/webhook.rb
Changed create class method to delegate to super instead of direct client.create_webhook call; added private parse_datetime helper.
Base Resource Dynamic Access
lib/bridge_api/base_resource.rb
Introduced method_missing for dynamic attribute access from @values; added respond_to_missing?; enhanced convert_value to recursively process Hash values with symbol key conversion.
Formatting & Structural Updates
lib/bridge_api/resources/virtual_account.rb, lib/bridge_api/resources/wallet.rb
Added blank lines before private sections; no functional changes.
Dependency & Configuration
Gemfile
Added dotenv gem with version constraint ~> 3.1.
Cleanup
exe/bridge_api
Removed executable script that previously printed version and usage URL.
Ignore Rules
.gitignore
Added duplicate /exemples entries to ignore rules.

Sequence Diagram(s)

sequenceDiagram
    participant Client as BridgeApi::Client
    participant ResourceAccessor as ResourceAccessor
    participant Service as Service (e.g., CustomerService)
    participant Util as BridgeApi::Util
    participant Resource as Resource Object

    Note over Client,Resource: New Service-based Flow
    Client->>ResourceAccessor: client.customers.list()
    ResourceAccessor->>Service: service.list(params)
    Service->>Client: request(:get, endpoint, params)
    Client->>Client: HTTP request
    Client-->>Service: response
    Service-->>ResourceAccessor: response
    ResourceAccessor-->>Client: response
    Client->>Util: convert_to_bridged_object(response)
    Util->>Util: detect_resource_type(data)
    Util->>Util: construct_resource(type, data)
    Util->>Resource: instantiate resource
    Resource-->>Util: resource object
    Util-->>Client: converted object/list
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • lib/bridge_api/util.rb: Significant refactoring with new pattern-matching logic (OBJECT_CLASS_NAMES, RESOURCE_PATTERNS, detect_resource_type, construct_resource); requires verification that all resource types map correctly and conversion edge cases are handled.
  • lib/bridge_api/client.rb: New ResourceAccessor pattern introduces dynamic method generation and fallback delegation; verify resource accessor instantiation and method delegation chains work correctly.
  • Service implementations (customer_service.rb, wallet_service.rb, etc.): Multiple similar service classes with subtle differences; ensure each service correctly delegates to parent BaseService and handles idempotency keys consistently.
  • lib/bridge_api/resources/customer.rb: Removal of explicit accessors in favor of dynamic access via base_resource.rb method_missing; verify backward compatibility and that related resource operations (wallets, virtual_accounts) integrate properly with client accessor pattern.
  • lib/bridge_api/base_resource.rb: New method_missing and recursive convert_value logic; test dynamic attribute access and nested hash conversion edge cases.
  • Cross-component integration: api_operations.rb List flow now depends on util.rb conversion; verify response transformation doesn't break existing consumers.

Poem

🐰 A service layer blooms, clean and bright,
Resource accessors dance through the night,
Pattern-matched objects, datetime parsed with care,
Dynamic attributes floating in air!
The Bridge API hops toward tomorrow,
No longer any backward sorrow!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat: Add customer service with retrieve method' is partially related to the changeset. While it accurately describes the addition of a CustomerService class with retrieve functionality, the changeset encompasses substantially more changes including new service classes (KycLink, Wallet, ExternalAccount, VirtualAccount, Webhook), resource updates, utility refactoring, client accessor patterns, and infrastructure changes that are not mentioned in the title.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@bolom bolom changed the title Customer retrieve returns object feat: Make customer retrieve Nov 15, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
exemples/customer_retrieve.rb (1)

80-81: Adjust comment annotation to satisfy RuboCop.

RuboCop’s Style/CommentAnnotation prefers annotation keywords in all caps. To avoid the warning, update this comment to:

# NOTE: the customer object might have other attributes not covered by explicit methods
lib/bridge_api/services/customer_service.rb (1)

9-15: retrieve behavior is good; consider centralizing resource construction.

retrieve now returns a BridgeApi::Resources::Customer on success and a Client::Response on error, which matches the stated goal. To keep resource construction consistent with other code paths, you could optionally delegate to BridgeApi::Util.convert_to_bridged_object(response, resource_hint: 'customer') here instead of calling Customer.construct_from directly. That would reuse the same detection/instantiation pipeline used elsewhere.

Not urgent, but worth considering if you later want create, list, and update to also return resource objects instead of raw responses.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b661a67 and 976070b.

📒 Files selected for processing (4)
  • exemples/customer_retrieve.rb (1 hunks)
  • lib/bridge_api.rb (1 hunks)
  • lib/bridge_api/services/customer_service.rb (1 hunks)
  • lib/bridge_api/util.rb (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
exemples/customer_retrieve.rb (3)
lib/bridge_api.rb (2)
  • config (39-41)
  • base_url (43-45)
lib/bridge_api/services/customer_service.rb (1)
  • retrieve (9-15)
lib/bridge_api/resources/customer.rb (2)
  • first_name (64-66)
  • last_name (68-70)
lib/bridge_api/services/customer_service.rb (3)
lib/bridge_api/client.rb (2)
  • request (64-74)
  • success? (242-242)
lib/bridge_api/base_resource.rb (1)
  • construct_from (112-114)
lib/bridge_api/list_object.rb (1)
  • data (12-14)
lib/bridge_api/util.rb (2)
lib/bridge_api/list_object.rb (2)
  • data (12-14)
  • each (32-34)
lib/bridge_api/base_resource.rb (2)
  • each (87-89)
  • construct_from (112-114)
🪛 GitHub Actions: Tests
lib/bridge_api.rb

[error] 76-76: cannot load such file -- bridge_api/services/base_service (LoadError). This occurred while requiring dependent files during 'bundle exec rake test'.

🪛 RuboCop (1.81.7)
exemples/customer_retrieve.rb

[convention] 80-80: Annotation keywords like Note should be all upper case, followed by a colon, and a space, then a note describing the problem.

(Style/CommentAnnotation)

bolom and others added 2 commits November 15, 2025 17:00
- Add wallet_service.rb, external_account_service.rb, virtual_account_service.rb,
  and webhook_service.rb that were being required but missing
- Add proper module structure (BridgeApi::Services) to match BaseService
- Update service classes to inherit from BaseService and call super in initialize
- This fixes the LoadError when requiring the bridge_api gem

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@bolom bolom changed the title feat: Make customer retrieve feat: Add customer service with retrieve method Nov 15, 2025
- Add webhook pattern to RESOURCE_PATTERNS in util.rb to properly convert webhook hashes to Webhook objects
- Add Response unwrapping in convert_to_bridged_object to handle Client::Response objects
- Fix ResourceAccessor methods to use send(:request) for private method access
- Update Webhook.create to use super for consistent API operation handling
- Update list operation to convert response to proper resource objects
- Add webhook examples: create_webhook_example.rb and list_webhooks_example.rb
- Add dotenv dependency for environment variable management in examples
- Add update_webhook_example.rb to activate webhooks
- Fix build_request_options to exclude Idempotency-Key for PUT requests
- Update ResourceAccessor.update to use PUT for webhooks instead of PATCH
- Webhooks require PUT without idempotency keys per Bridge API spec

The example script lists webhooks, gets the most recent one, and activates it.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

♻️ Duplicate comments (3)
lib/bridge_api/resources/kyc_link.rb (1)

72-83: Duplicate: Extract duplicated dynamic attribute pattern to base class.

This is the same method_missing/respond_to_missing? pattern already flagged in lib/bridge_api/resources/wallet.rb. Please see the earlier comment for details on extracting this to the base class.

lib/bridge_api/services/external_account_service.rb (1)

18-28: Code duplication with other service classes.

This service duplicates the same get and list pattern as WalletService and VirtualAccountService. See the refactoring suggestion in WalletService to extract the common pattern to BaseService.

lib/bridge_api/services/virtual_account_service.rb (1)

18-28: Code duplication with other service classes.

This service duplicates the same get and list pattern as WalletService and ExternalAccountService. See the refactoring suggestion in WalletService to extract the common pattern to BaseService.

🧹 Nitpick comments (7)
lib/bridge_api/resources/transaction_history.rb (1)

39-50: Dynamic attribute access looks correct and consistent with other resources

The method_missing / respond_to_missing? pair cleanly exposes @values keys as methods and matches the pattern used in other resources, so behavior should be predictable for callers. Longer‑term, you might consider lifting this pattern into BaseResource to avoid repeating the same logic across every resource class, but it’s not blocking for this change.

lib/bridge_api/services/base_service.rb (1)

1-20: BaseService correctly centralizes client request handling

The initializer and protected request helper are straightforward and correctly route to @client.request_with_idempotency when an idempotency_key is provided, otherwise to @client.request. Using send is reasonable here if those client methods are intentionally non‑public.

As a minor style nit, RuboCop notes a missing final newline at EOF; adding one will keep linters happy but doesn’t affect behavior.

exemples/update_webhook_example.rb (1)

5-8: Extract boolean parsing helper for reusability.

The boolean parsing logic ENV['BRIDGE_SANDBOX_MODE'] ? ENV['BRIDGE_SANDBOX_MODE'].downcase == 'true' : true is duplicated across multiple example files (create_webhook_example.rb, list_webhooks_example.rb, webhook_example.rb). Consider extracting this to a shared helper method or module to reduce duplication and improve maintainability.

For example, create a helper in a shared location:

# exemples/support/env_helper.rb
module EnvHelper
  def self.parse_boolean(env_var, default: true)
    value = ENV[env_var]
    value ? value.downcase == 'true' : default
  end
end

Then use it as:

config.sandbox_mode = EnvHelper.parse_boolean('BRIDGE_SANDBOX_MODE', default: true)
exemples/webhook_example.rb (1)

1-1: Consider adding execute permission if intended as a standalone script.

The file has a shebang (#!/usr/bin/env ruby) suggesting it's meant to be executable, but RuboCop reports missing execute permission. If this is intended to be run as ./exemples/webhook_example.rb, add execute permission.

chmod +x exemples/webhook_example.rb

Otherwise, remove the shebang if it's only meant to be run via ruby exemples/webhook_example.rb.

lib/bridge_api/resources/webhook.rb (1)

52-63: Consider removing redundant explicit accessors.

With method_missing now handling all attributes in @values, the explicit accessor methods (lines 28-50) become redundant. You could remove them to reduce code duplication, or keep them for documentation purposes if they represent the public API contract.

lib/bridge_api/services/wallet_service.rb (1)

18-21: Consider extracting common get pattern to BaseService.

The get method follows an identical pattern across WalletService, ExternalAccountService, and VirtualAccountService. Consider extracting this to BaseService to reduce duplication:

# In BaseService
def get_resource(id)
  resource = @resource_class.new(@client)
  resource.retrieve(id)
end

Then service classes can simply call get_resource(wallet_id).

lib/bridge_api/resources/virtual_account.rb (1)

55-66: Extract method_missing pattern to a shared module.

This exact method_missing/respond_to_missing? pattern is duplicated across multiple resource classes (Webhook, Customer, KycLink, Wallet, TotalBalance, TransactionHistory, WebhookEvent, WebhookEventDeliveryLog, RewardRate, and now VirtualAccount). Consider extracting this to a shared module:

module BridgeApi
  module DynamicAttributes
    def method_missing(method_name, *args)
      if @values.key?(method_name)
        @values[method_name]
      else
        super
      end
    end

    def respond_to_missing?(method_name, include_private = false)
      @values.key?(method_name) || super
    end
  end
end

Then include it in the resource classes:

class VirtualAccount < APIResource
  include DynamicAttributes
  # ...
end
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 976070b and f60814e.

📒 Files selected for processing (26)
  • Gemfile (1 hunks)
  • exe/bridge_api (0 hunks)
  • exemples/Gemfile (1 hunks)
  • exemples/create_webhook_example.rb (1 hunks)
  • exemples/list_webhooks_example.rb (1 hunks)
  • exemples/update_webhook_example.rb (1 hunks)
  • exemples/webhook_example.rb (1 hunks)
  • lib/bridge_api/api_operations.rb (1 hunks)
  • lib/bridge_api/client.rb (4 hunks)
  • lib/bridge_api/resources/customer.rb (3 hunks)
  • lib/bridge_api/resources/kyc_link.rb (1 hunks)
  • lib/bridge_api/resources/reward_rate.rb (1 hunks)
  • lib/bridge_api/resources/total_balance.rb (1 hunks)
  • lib/bridge_api/resources/transaction_history.rb (1 hunks)
  • lib/bridge_api/resources/virtual_account.rb (1 hunks)
  • lib/bridge_api/resources/wallet.rb (1 hunks)
  • lib/bridge_api/resources/webhook.rb (2 hunks)
  • lib/bridge_api/resources/webhook_event.rb (1 hunks)
  • lib/bridge_api/resources/webhook_event_delivery_log.rb (1 hunks)
  • lib/bridge_api/services/base_service.rb (1 hunks)
  • lib/bridge_api/services/external_account_service.rb (1 hunks)
  • lib/bridge_api/services/kyc_link_service.rb (1 hunks)
  • lib/bridge_api/services/virtual_account_service.rb (1 hunks)
  • lib/bridge_api/services/wallet_service.rb (1 hunks)
  • lib/bridge_api/services/webhook_service.rb (1 hunks)
  • lib/bridge_api/util.rb (1 hunks)
💤 Files with no reviewable changes (1)
  • exe/bridge_api
✅ Files skipped from review due to trivial changes (1)
  • lib/bridge_api/api_operations.rb
🧰 Additional context used
🧬 Code graph analysis (15)
exemples/create_webhook_example.rb (4)
lib/bridge_api.rb (1)
  • config (39-41)
lib/bridge_api/api_operations.rb (1)
  • create (31-36)
lib/bridge_api/resources/webhook.rb (7)
  • create (23-25)
  • id (28-30)
  • url (32-34)
  • status (36-38)
  • event_categories (44-46)
  • created_at (48-50)
  • public_key (40-42)
lib/bridge_api/list_object.rb (2)
  • data (12-14)
  • first (48-50)
lib/bridge_api/resources/reward_rate.rb (10)
lib/bridge_api/client.rb (2)
  • method_missing (151-158)
  • respond_to_missing? (160-162)
lib/bridge_api/resources/webhook.rb (2)
  • method_missing (53-59)
  • respond_to_missing? (61-63)
lib/bridge_api/resources/customer.rb (2)
  • method_missing (83-89)
  • respond_to_missing? (91-93)
lib/bridge_api/resources/kyc_link.rb (2)
  • method_missing (73-79)
  • respond_to_missing? (81-83)
lib/bridge_api/resources/total_balance.rb (2)
  • method_missing (30-36)
  • respond_to_missing? (38-40)
lib/bridge_api/resources/transaction_history.rb (2)
  • method_missing (40-46)
  • respond_to_missing? (48-50)
lib/bridge_api/resources/virtual_account.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/wallet.rb (2)
  • method_missing (59-65)
  • respond_to_missing? (67-69)
lib/bridge_api/resources/webhook_event.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/webhook_event_delivery_log.rb (2)
  • method_missing (28-34)
  • respond_to_missing? (36-38)
lib/bridge_api/services/external_account_service.rb (4)
lib/bridge_api/services/base_service.rb (2)
  • initialize (4-18)
  • initialize (5-7)
lib/bridge_api/services/virtual_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/wallet_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/kyc_link_service.rb (2)
  • retrieve (9-11)
  • list (13-15)
lib/bridge_api/services/base_service.rb (4)
lib/bridge_api/services/external_account_service.rb (2)
  • initialize (9-29)
  • initialize (10-13)
lib/bridge_api/services/virtual_account_service.rb (2)
  • initialize (9-29)
  • initialize (10-13)
lib/bridge_api/services/wallet_service.rb (2)
  • initialize (9-29)
  • initialize (10-13)
lib/bridge_api/services/webhook_service.rb (2)
  • initialize (9-29)
  • initialize (10-13)
lib/bridge_api/resources/virtual_account.rb (11)
lib/bridge_api/client.rb (2)
  • method_missing (151-158)
  • respond_to_missing? (160-162)
lib/bridge_api/resources/webhook.rb (2)
  • method_missing (53-59)
  • respond_to_missing? (61-63)
lib/bridge_api/resources/customer.rb (2)
  • method_missing (83-89)
  • respond_to_missing? (91-93)
lib/bridge_api/resources/kyc_link.rb (2)
  • method_missing (73-79)
  • respond_to_missing? (81-83)
lib/bridge_api/resources/reward_rate.rb (2)
  • method_missing (24-30)
  • respond_to_missing? (32-34)
lib/bridge_api/resources/total_balance.rb (2)
  • method_missing (30-36)
  • respond_to_missing? (38-40)
lib/bridge_api/resources/transaction_history.rb (2)
  • method_missing (40-46)
  • respond_to_missing? (48-50)
lib/bridge_api/resources/wallet.rb (2)
  • method_missing (59-65)
  • respond_to_missing? (67-69)
lib/bridge_api/resources/webhook_event.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/webhook_event_delivery_log.rb (2)
  • method_missing (28-34)
  • respond_to_missing? (36-38)
lib/bridge_api/base_resource.rb (1)
  • key? (92-94)
exemples/update_webhook_example.rb (4)
lib/bridge_api.rb (1)
  • config (39-41)
lib/bridge_api/client.rb (2)
  • list (108-110)
  • update (129-138)
lib/bridge_api/list_object.rb (3)
  • data (12-14)
  • last (52-54)
  • first (48-50)
lib/bridge_api/resources/webhook.rb (1)
  • event_categories (44-46)
exemples/list_webhooks_example.rb (5)
lib/bridge_api.rb (1)
  • config (39-41)
lib/bridge_api/client.rb (1)
  • list (108-110)
lib/bridge_api/api_operations.rb (1)
  • list (12-20)
lib/bridge_api/resources/webhook.rb (6)
  • list (15-17)
  • id (28-30)
  • url (32-34)
  • status (36-38)
  • event_categories (44-46)
  • created_at (48-50)
lib/bridge_api/list_object.rb (1)
  • data (12-14)
lib/bridge_api/resources/transaction_history.rb (11)
lib/bridge_api/client.rb (2)
  • method_missing (151-158)
  • respond_to_missing? (160-162)
lib/bridge_api/resources/webhook.rb (2)
  • method_missing (53-59)
  • respond_to_missing? (61-63)
lib/bridge_api/resources/customer.rb (2)
  • method_missing (83-89)
  • respond_to_missing? (91-93)
lib/bridge_api/resources/kyc_link.rb (2)
  • method_missing (73-79)
  • respond_to_missing? (81-83)
lib/bridge_api/resources/reward_rate.rb (2)
  • method_missing (24-30)
  • respond_to_missing? (32-34)
lib/bridge_api/resources/total_balance.rb (2)
  • method_missing (30-36)
  • respond_to_missing? (38-40)
lib/bridge_api/resources/virtual_account.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/wallet.rb (2)
  • method_missing (59-65)
  • respond_to_missing? (67-69)
lib/bridge_api/resources/webhook_event.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/webhook_event_delivery_log.rb (2)
  • method_missing (28-34)
  • respond_to_missing? (36-38)
lib/bridge_api/base_resource.rb (1)
  • key? (92-94)
lib/bridge_api/resources/kyc_link.rb (11)
lib/bridge_api/client.rb (2)
  • method_missing (151-158)
  • respond_to_missing? (160-162)
lib/bridge_api/resources/webhook.rb (2)
  • method_missing (53-59)
  • respond_to_missing? (61-63)
lib/bridge_api/resources/customer.rb (2)
  • method_missing (83-89)
  • respond_to_missing? (91-93)
lib/bridge_api/resources/reward_rate.rb (2)
  • method_missing (24-30)
  • respond_to_missing? (32-34)
lib/bridge_api/resources/total_balance.rb (2)
  • method_missing (30-36)
  • respond_to_missing? (38-40)
lib/bridge_api/resources/transaction_history.rb (2)
  • method_missing (40-46)
  • respond_to_missing? (48-50)
lib/bridge_api/resources/virtual_account.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/wallet.rb (2)
  • method_missing (59-65)
  • respond_to_missing? (67-69)
lib/bridge_api/resources/webhook_event.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/webhook_event_delivery_log.rb (2)
  • method_missing (28-34)
  • respond_to_missing? (36-38)
lib/bridge_api/base_resource.rb (1)
  • key? (92-94)
lib/bridge_api/services/virtual_account_service.rb (5)
lib/bridge_api/services/base_service.rb (2)
  • initialize (4-18)
  • initialize (5-7)
lib/bridge_api/services/external_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/wallet_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/webhook_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/kyc_link_service.rb (2)
  • retrieve (9-11)
  • list (13-15)
lib/bridge_api/services/wallet_service.rb (4)
lib/bridge_api/services/base_service.rb (2)
  • initialize (4-18)
  • initialize (5-7)
lib/bridge_api/services/external_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/virtual_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/webhook_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/resources/total_balance.rb (11)
lib/bridge_api/client.rb (2)
  • method_missing (151-158)
  • respond_to_missing? (160-162)
lib/bridge_api/resources/webhook.rb (2)
  • method_missing (53-59)
  • respond_to_missing? (61-63)
lib/bridge_api/resources/customer.rb (2)
  • method_missing (83-89)
  • respond_to_missing? (91-93)
lib/bridge_api/resources/kyc_link.rb (2)
  • method_missing (73-79)
  • respond_to_missing? (81-83)
lib/bridge_api/resources/reward_rate.rb (2)
  • method_missing (24-30)
  • respond_to_missing? (32-34)
lib/bridge_api/resources/transaction_history.rb (2)
  • method_missing (40-46)
  • respond_to_missing? (48-50)
lib/bridge_api/resources/virtual_account.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/wallet.rb (2)
  • method_missing (59-65)
  • respond_to_missing? (67-69)
lib/bridge_api/resources/webhook_event.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/webhook_event_delivery_log.rb (2)
  • method_missing (28-34)
  • respond_to_missing? (36-38)
lib/bridge_api/base_resource.rb (1)
  • key? (92-94)
lib/bridge_api/services/webhook_service.rb (4)
lib/bridge_api/services/base_service.rb (2)
  • initialize (4-18)
  • initialize (5-7)
lib/bridge_api/services/external_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/virtual_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/wallet_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/resources/customer.rb (9)
lib/bridge_api/client.rb (2)
  • method_missing (151-158)
  • respond_to_missing? (160-162)
lib/bridge_api/resources/webhook.rb (2)
  • method_missing (53-59)
  • respond_to_missing? (61-63)
lib/bridge_api/resources/kyc_link.rb (2)
  • method_missing (73-79)
  • respond_to_missing? (81-83)
lib/bridge_api/resources/reward_rate.rb (2)
  • method_missing (24-30)
  • respond_to_missing? (32-34)
lib/bridge_api/resources/total_balance.rb (2)
  • method_missing (30-36)
  • respond_to_missing? (38-40)
lib/bridge_api/resources/transaction_history.rb (2)
  • method_missing (40-46)
  • respond_to_missing? (48-50)
lib/bridge_api/resources/virtual_account.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/wallet.rb (2)
  • method_missing (59-65)
  • respond_to_missing? (67-69)
lib/bridge_api/resources/webhook_event.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/services/kyc_link_service.rb (5)
lib/bridge_api/services/base_service.rb (1)
  • request (11-17)
lib/bridge_api/services/external_account_service.rb (1)
  • list (26-28)
lib/bridge_api/services/virtual_account_service.rb (1)
  • list (26-28)
lib/bridge_api/services/wallet_service.rb (1)
  • list (26-28)
lib/bridge_api/services/webhook_service.rb (1)
  • list (26-28)
🪛 RuboCop (1.81.7)
exemples/create_webhook_example.rb

[convention] 1-1: Missing frozen string literal comment.

(Style/FrozenStringLiteralComment)


[convention] 23-23: Put a comma after the last item of a multiline array.

(Style/TrailingCommaInArrayLiteral)


[convention] 24-24: Put a comma after the last item of a multiline hash.

(Style/TrailingCommaInHashLiteral)


[convention] 43-43: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)

lib/bridge_api/services/external_account_service.rb

[convention] 31-31: Final newline missing.

(Layout/TrailingEmptyLines)

lib/bridge_api/services/base_service.rb

[convention] 20-20: Final newline missing.

(Layout/TrailingEmptyLines)

exemples/update_webhook_example.rb

[convention] 1-1: Missing frozen string literal comment.

(Style/FrozenStringLiteralComment)


[convention] 33-33: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 43-43: Put a comma after the last item of a multiline hash.

(Style/TrailingCommaInHashLiteral)

exemples/list_webhooks_example.rb

[convention] 1-1: Missing frozen string literal comment.

(Style/FrozenStringLiteralComment)


[convention] 7-7: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 12-13: Indent the first argument one step more than the start of the previous line.

(Layout/FirstArgumentIndentation)


[convention] 15-15: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 16-16: Inconsistent indentation detected.

(Layout/IndentationConsistency)


[convention] 17-17: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 18-18: Inconsistent indentation detected.

(Layout/IndentationConsistency)


[convention] 19-19: Inconsistent indentation detected.

(Layout/IndentationConsistency)


[convention] 20-27: Inconsistent indentation detected.

(Layout/IndentationConsistency)

lib/bridge_api/services/virtual_account_service.rb

[convention] 31-31: Final newline missing.

(Layout/TrailingEmptyLines)

lib/bridge_api/services/wallet_service.rb

[convention] 31-31: Final newline missing.

(Layout/TrailingEmptyLines)

lib/bridge_api/services/webhook_service.rb

[convention] 31-31: Final newline missing.

(Layout/TrailingEmptyLines)

exemples/Gemfile

[convention] 1-1: Missing frozen string literal comment.

(Style/FrozenStringLiteralComment)


[convention] 1-1: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 3-3: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 3-3: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 4-4: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem bridge_api should appear before dotenv.

(Bundler/OrderedGems)


[convention] 4-4: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 4-4: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)

exemples/webhook_example.rb

[warning] 1-1: Script file webhook_example.rb doesn't have execute permission.

(Lint/ScriptPermission)


[convention] 41-41: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 42-42: Put a comma after the last item of a multiline array.

(Style/TrailingCommaInArrayLiteral)


[convention] 44-44: Put a comma after the last item of a multiline hash.

(Style/TrailingCommaInHashLiteral)


[convention] 47-47: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 65-65: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 67-67: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 80-80: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 82-82: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 84-84: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 86-86: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 87-87: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 90-90: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 91-91: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 92-92: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 93-93: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 95-95: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 97-97: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 109-109: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 114-114: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 116-116: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 119-119: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 133-133: Trailing whitespace detected.

(Layout/TrailingWhitespace)


[convention] 136-136: Final newline missing.

(Layout/TrailingEmptyLines)

lib/bridge_api/client.rb

[convention] 121-121: Line is too long. [130/120]

(Layout/LineLength)


[convention] 130-130: Line is too long. [130/120]

(Layout/LineLength)

lib/bridge_api/resources/customer.rb

[convention] 109-109: Final newline missing.

(Layout/TrailingEmptyLines)

Gemfile

[convention] 20-20: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)


[convention] 20-20: Prefer single-quoted strings when you don't need string interpolation or special symbols.

(Style/StringLiterals)

lib/bridge_api/util.rb

[convention] 28-59: Perceived complexity for convert_to_bridged_object is too high. [16/15]

(Metrics/PerceivedComplexity)


[convention] 37-37: Convert if nested inside else to elsif.

(Style/IfInsideElse)

lib/bridge_api/services/kyc_link_service.rb

[convention] 18-18: Final newline missing.

(Layout/TrailingEmptyLines)

🔇 Additional comments (14)
lib/bridge_api/resources/total_balance.rb (1)

29-40: Dynamic attribute helpers align with the shared resource pattern

The added method_missing and respond_to_missing? implementations are consistent with the other resource classes and correctly expose any key in @values as a readable method while deferring unknown methods to super. No issues from a correctness standpoint.

lib/bridge_api/resources/webhook_event_delivery_log.rb (1)

27-38: Dynamic access for arbitrary log fields is implemented correctly

method_missing / respond_to_missing? correctly delegate to @values when a key exists and fall back to super otherwise, matching the rest of the resource layer’s behavior. This should make additional delivery log fields available without further code changes.

lib/bridge_api/resources/webhook_event.rb (1)

55-66: WebhookEvent dynamic attribute access is consistent and safe

The new method_missing and respond_to_missing? implementations are consistent with the rest of the resources and correctly expose any key present in @values while letting unknown methods bubble up via super. This is a straightforward extension of the public API with no apparent regressions.

lib/bridge_api/resources/customer.rb (1)

82-93: Dynamic attribute access is solid.
Matches the pattern used across other resources and preserves the previous id/email access via @values, so no concerns here.

lib/bridge_api/resources/reward_rate.rb (1)

23-34: Dynamic attributes wired correctly.
Keeps the explicit rate/effective_at helpers while exposing the rest of the payload consistently with other resources. Looks good.

exemples/update_webhook_example.rb (1)

19-28: LGTM! Good validation and error handling.

The response validation logic correctly checks both success? and that webhooks are non-empty before proceeding, providing clear error messages for each failure case.

exemples/create_webhook_example.rb (1)

32-49: LGTM! Clear example demonstrating webhook creation.

The webhook creation example correctly demonstrates the API usage with proper error handling and structured output. The example clearly shows both success and failure paths.

lib/bridge_api/services/webhook_service.rb (1)

10-28: LGTM! Service implementation follows established patterns.

The WebhookService correctly follows the same pattern as other service classes (WalletService, VirtualAccountService, ExternalAccountService), with consistent get and list method implementations that properly delegate to the resource class.

lib/bridge_api/client.rb (2)

80-85: LGTM! Appropriate idempotency key handling.

The logic correctly differentiates between operations that support idempotency keys (POST/PATCH) and those that don't (PUT for webhooks), only adding the header when appropriate or explicitly requested.


185-193: LGTM! Clean dynamic accessor generation.

The dynamic resource accessor generation correctly creates per-resource methods that return cached ResourceAccessor instances, providing an ergonomic API like client.webhooks.list while maintaining efficiency through instance variable caching.

exemples/webhook_example.rb (2)

57-98: LGTM! Helpful example with appropriate fallback behavior.

The example correctly handles both real API key scenarios (attempting actual webhook creation) and placeholder scenarios (showing code examples), making it useful for both testing and learning purposes. The placeholder detection logic is reasonable.


107-136: LGTM! Clear webhook handler example.

The heredoc provides a helpful, practical example of how to implement an inbound webhook handler with signature verification placeholder and event type switching, which will be valuable for developers integrating the webhooks.

lib/bridge_api/resources/webhook.rb (1)

23-25: LGTM: Cleaner delegation to base class.

The change to delegate to super is appropriate and aligns with the service layer pattern.

lib/bridge_api/resources/virtual_account.rb (1)

55-66: LGTM: Dynamic attribute access implemented correctly.

The method_missing and respond_to_missing? implementation correctly provides dynamic access to attributes in @values.

Deleted the entire 'exemples' directory and its example scripts. Updated service and resource classes to call 'super' without passing the client argument, aligning with Ruby best practices. Minor .gitignore and Gemfile formatting adjustments were also made.
Eliminated unused require_relative statements for base_resource and client to clean up the WalletService implementation.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
lib/bridge_api/util.rb (1)

5-24: Missing total_balance mapping still breaks TotalBalance resource construction

OBJECT_CLASS_NAMES does not include 'total_balance' => 'BridgeApi::Resources::TotalBalance', so responses with object: "total_balance" (or using that resource_hint) will never be wrapped as a TotalBalance resource and will fall back to a plain hash. This matches the previously noted issue and remains unresolved.

Please add the mapping, e.g.:

     'transaction_history' => 'BridgeApi::Resources::TransactionHistory',
+    'total_balance' => 'BridgeApi::Resources::TotalBalance',
     'reward_rate' => 'BridgeApi::Resources::RewardRate',
🧹 Nitpick comments (3)
lib/bridge_api/util.rb (3)

44-58: Consider guarding against missing BridgeApi::Client::Response constant

unwrap_client_response directly references BridgeApi::Client::Response in is_a?, which will raise a NameError if this file is used in a context where that constant hasn’t been loaded (or in older versions without that class). If Util is ever used independently of the client, this becomes brittle.

You could make it more defensive without changing behavior in normal cases:

-      def unwrap_client_response(data)
-        # Detect if data is a Client::Response and unwrap it
-        return data unless data.is_a?(BridgeApi::Client::Response)
+      def unwrap_client_response(data)
+        # Detect if data is a Client::Response and unwrap it
+        return data unless defined?(BridgeApi::Client::Response) &&
+                          data.is_a?(BridgeApi::Client::Response)

60-100: Hash-processing and type-detection order looks correct; just watch the data-key heuristic

The flow in process_hash_data and detect_resource_type* is coherent:

  1. Treat top-level { data: [...] } as list and wrap in BridgeApi::ListObject.
  2. Prefer explicit object field.
  3. Fall back to resource_hint.
  4. Finally, use RESOURCE_PATTERNS heuristics, then plain symbolized hash.

One thing to be aware of: any non-list payload that happens to include a top-level data key (string or symbol) will be interpreted as a list. If the API contract guarantees that data is reserved for list responses, this is fine; otherwise, you may eventually want a stricter check (e.g., object: 'list' plus data being an array).

No changes strictly required now, but keep this in mind if new endpoints introduce a top-level data field for non-list resources.


102-119: Resource construction and key symbolization are solid; consider slightly safer failure modes

construct_resource + symbolize_keys align well with BaseResource expectations (symbol keys, construct_from when available). Two optional robustness tweaks you might consider:

  • If OBJECT_CLASS_NAMES[object_name] somehow falls out of sync (e.g., bad entry or manual call with an unknown name), Object.const_get(nil) / an invalid constant will raise a somewhat opaque NameError. A small guard could provide a clearer message:

    def construct_resource(object_name, data, opts)
      class_name = OBJECT_CLASS_NAMES[object_name]
      raise ArgumentError, "Unknown resource type: #{object_name}" unless class_name
    
      klass = Object.const_get(class_name)
      klass.respond_to?(:construct_from) ? klass.construct_from(data, opts) : klass.new(data)
    end
  • symbolize_keys assumes keys respond to to_sym, which is true for JSON-style payloads (string keys) but would break for non-string/scalar keys. If there’s any chance of non-string keys creeping in, consider guarding with respond_to?(:to_sym).

These are defensive-only; current behavior is fine given typical JSON API responses and the guarded call sites.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f60814e and c8b96ab.

📒 Files selected for processing (2)
  • lib/bridge_api/client.rb (4 hunks)
  • lib/bridge_api/util.rb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/bridge_api/client.rb
🧰 Additional context used
🧬 Code graph analysis (1)
lib/bridge_api/util.rb (3)
lib/bridge_api/list_object.rb (2)
  • data (12-14)
  • each (32-34)
lib/bridge_api/base_resource.rb (5)
  • key? (92-94)
  • each (87-89)
  • key (40-42)
  • key (45-47)
  • construct_from (112-114)
lib/bridge_api/api_resource.rb (2)
  • object_name (5-79)
  • object_name (9-11)
🔇 Additional comments (1)
lib/bridge_api/util.rb (1)

26-42: Conversion pipeline reads cleanly and restores list → bridged-object behavior

Unwrapping the Client::Response first and then routing via a simple case on Array/Hash keeps convert_to_bridged_object easy to follow and should fix the earlier regression where list calls returned raw responses instead of bridged objects. No issues from my side here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
.gitignore (1)

176-177: Remove duplicate .gitignore entry.

Lines 176–177 contain identical duplicate entries for /exemples. Keep only one.

 config/keys.json
 stripe-ruby/
 *.md
-/exemples
 /exemples
lib/bridge_api/resources/customer.rb (1)

82-93: Extract duplicated dynamic attribute pattern to a shared module.

The method_missing and respond_to_missing? implementation is correct and follows Ruby best practices. However, this exact pattern is duplicated across at least 10 resource classes (webhook.rb, kyc_link.rb, total_balance.rb, reward_rate.rb, transaction_history.rb, virtual_account.rb, webhook_event.rb, wallet.rb, webhook_event_delivery_log.rb, and this file).

Consider extracting this pattern to BaseResource or a shared concern/module to eliminate duplication and ensure consistency across all resources.

Example approach — add to BaseResource or create a new module:

module BridgeApi
  module DynamicAttributes
    def method_missing(method_name, *args)
      if @values.key?(method_name)
        @values[method_name]
      else
        super
      end
    end

    def respond_to_missing?(method_name, include_private = false)
      @values.key?(method_name) || super
    end
  end
end

Then include it in resource classes:

 class Customer < APIResource
   OBJECT_NAME = 'customer'
+  include BridgeApi::DynamicAttributes
   
   # ... rest of the class ...
-
-  def method_missing(method_name, *args)
-    if @values.key?(method_name)
-      @values[method_name]
-    else
-      super
-    end
-  end
-
-  def respond_to_missing?(method_name, include_private = false)
-    @values.key?(method_name) || super
-  end
 end
lib/bridge_api/services/external_account_service.rb (1)

3-4: Consider aligning require_relative usage with other services.

WalletService/WebhookService/VirtualAccountService don’t explicitly require_relative base_resource or client; they rely on the top-level loader. Unless this file must be loadable in isolation, you can likely drop these requires to keep the layering consistent and avoid redundant/circular loading concerns.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8b96ab and eb884c5.

📒 Files selected for processing (10)
  • .gitignore (1 hunks)
  • Gemfile (1 hunks)
  • lib/bridge_api/resources/customer.rb (2 hunks)
  • lib/bridge_api/resources/webhook.rb (2 hunks)
  • lib/bridge_api/services/base_service.rb (1 hunks)
  • lib/bridge_api/services/external_account_service.rb (1 hunks)
  • lib/bridge_api/services/kyc_link_service.rb (1 hunks)
  • lib/bridge_api/services/virtual_account_service.rb (1 hunks)
  • lib/bridge_api/services/wallet_service.rb (1 hunks)
  • lib/bridge_api/services/webhook_service.rb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • lib/bridge_api/services/virtual_account_service.rb
  • lib/bridge_api/resources/webhook.rb
  • Gemfile
  • lib/bridge_api/services/kyc_link_service.rb
  • lib/bridge_api/services/base_service.rb
🧰 Additional context used
🧬 Code graph analysis (3)
lib/bridge_api/services/webhook_service.rb (6)
lib/bridge_api/services/wallet_service.rb (4)
  • initialize (6-26)
  • initialize (7-10)
  • get (15-18)
  • list (23-25)
lib/bridge_api/services/base_service.rb (2)
  • initialize (4-18)
  • initialize (5-7)
lib/bridge_api/services/external_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/virtual_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/resources/webhook.rb (2)
  • retrieve (19-21)
  • list (15-17)
lib/bridge_api/services/kyc_link_service.rb (2)
  • retrieve (9-11)
  • list (13-15)
lib/bridge_api/services/external_account_service.rb (5)
lib/bridge_api/services/wallet_service.rb (4)
  • initialize (6-26)
  • initialize (7-10)
  • get (15-18)
  • list (23-25)
lib/bridge_api/services/base_service.rb (2)
  • initialize (4-18)
  • initialize (5-7)
lib/bridge_api/services/virtual_account_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/services/webhook_service.rb (4)
  • initialize (9-29)
  • initialize (10-13)
  • get (18-21)
  • list (26-28)
lib/bridge_api/resources/webhook.rb (2)
  • retrieve (19-21)
  • list (15-17)
lib/bridge_api/resources/customer.rb (11)
lib/bridge_api/resources/webhook.rb (2)
  • method_missing (53-59)
  • respond_to_missing? (61-63)
lib/bridge_api/resources/kyc_link.rb (2)
  • method_missing (73-79)
  • respond_to_missing? (81-83)
lib/bridge_api/resources/total_balance.rb (2)
  • method_missing (30-36)
  • respond_to_missing? (38-40)
lib/bridge_api/resources/reward_rate.rb (2)
  • method_missing (24-30)
  • respond_to_missing? (32-34)
lib/bridge_api/resources/transaction_history.rb (2)
  • method_missing (40-46)
  • respond_to_missing? (48-50)
lib/bridge_api/resources/virtual_account.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/webhook_event.rb (2)
  • method_missing (56-62)
  • respond_to_missing? (64-66)
lib/bridge_api/resources/wallet.rb (2)
  • method_missing (59-65)
  • respond_to_missing? (67-69)
lib/bridge_api/resources/webhook_event_delivery_log.rb (2)
  • method_missing (28-34)
  • respond_to_missing? (36-38)
lib/bridge_api/client.rb (2)
  • method_missing (159-166)
  • respond_to_missing? (168-170)
lib/bridge_api/base_resource.rb (1)
  • key? (92-94)
🔇 Additional comments (8)
lib/bridge_api/services/wallet_service.rb (4)

3-10: LGTM!

The class structure and initialization follow the established service pattern. The initialize method correctly delegates to the parent and sets the resource class appropriately.


12-18: LGTM!

The get method correctly instantiates the wallet resource and delegates to its retrieve method. The implementation is clean and follows the established service pattern.


20-25: LGTM!

The list method cleanly delegates to the resource class method with appropriate parameters. The optional options parameter provides flexibility for filtering.


1-28: Previous review feedback has been addressed.

The earlier concerns about redundant require_relative statements and the missing final newline have been resolved in this version.

lib/bridge_api/resources/customer.rb (1)

49-56: LGTM!

The datetime accessor overrides are well-implemented. By explicitly defining created_at and updated_at, these methods take precedence over method_missing, ensuring callers always receive parsed Time objects rather than raw strings. The parse_datetime helper properly handles nil values and parsing errors.

lib/bridge_api/services/external_account_service.rb (1)

8-28: Service implementation is consistent with existing patterns (LGTM).

initialize, get, and list follow the same pattern as the other service classes, correctly delegating to the resource class and using the injected client; the public surface looks coherent with the rest of the library.

lib/bridge_api/services/webhook_service.rb (2)

10-13: LGTM!

The initialization pattern correctly calls super to store the client and sets the resource class. This is consistent with other service implementations in the codebase.


26-28: LGTM!

The list method correctly delegates to the class method Webhook.list with the client and options. This is consistent with the established service pattern.

Moved the dynamic method handling for attribute access (method_missing and respond_to_missing?) from individual resource classes to BaseResource. This centralizes the logic, reduces code duplication, and ensures consistent behavior across all resource classes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/bridge_api/resources/transaction_history.rb (1)

42-51: Extract duplicated parse_datetime to a shared module.

This identical private method appears in 6 resource files (TransactionHistory, RewardRate, WebhookEventDeliveryLog, WebhookEvent, KycLink, Webhook). Extract it to a shared module or add it to BaseResource to eliminate duplication and simplify maintenance.

Consider adding to BaseResource:

module BridgeApi
  class BaseResource
    private

    # Parse a datetime string to a Time object
    # @param [String, nil] datetime_string The datetime string to parse
    # @return [Time, nil] The parsed Time object or nil if input is nil
    def parse_datetime(datetime_string)
      return nil unless datetime_string

      Time.parse(datetime_string)
    rescue ArgumentError
      nil
    end
  end
end

Then remove the duplicate private methods from all resource files.

♻️ Duplicate comments (5)
lib/bridge_api/resources/reward_rate.rb (1)

26-35: Duplicate: Extract shared parse_datetime method.

This method is identical to implementations in other resource files. See the earlier comment on transaction_history.rb regarding extracting this to a shared location.

lib/bridge_api/resources/webhook_event_delivery_log.rb (1)

30-39: Duplicate: Extract shared parse_datetime method.

This method is identical to implementations in other resource files. See the earlier comment on transaction_history.rb regarding extracting this to a shared location.

lib/bridge_api/resources/webhook_event.rb (1)

58-67: Duplicate: Extract shared parse_datetime method.

This method is identical to implementations in other resource files. See the earlier comment on transaction_history.rb regarding extracting this to a shared location.

lib/bridge_api/resources/kyc_link.rb (1)

75-84: Duplicate: Extract shared parse_datetime method.

This method is identical to implementations in other resource files. See the earlier comment on transaction_history.rb regarding extracting this to a shared location.

lib/bridge_api/resources/webhook.rb (1)

55-64: Duplicate: Extract shared parse_datetime method.

This method is identical to implementations in other resource files. See the earlier comment on transaction_history.rb regarding extracting this to a shared location.

🧹 Nitpick comments (1)
lib/bridge_api/resources/customer.rb (1)

82-94: Defensive parsing implementation looks good.

The parse_datetime helper correctly handles nil input and parse errors. If the Bridge API returns datetime strings without timezone information, be aware that Time.parse will default to the system timezone, which may cause inconsistencies across different environments.

If datetimes are always ISO8601 format and should be interpreted as UTC, consider:

 def parse_datetime(datetime_string)
   return nil unless datetime_string
 
-  Time.parse(datetime_string)
+  Time.iso8601(datetime_string)
 rescue ArgumentError
   nil
 end
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb884c5 and 698e38e.

📒 Files selected for processing (10)
  • lib/bridge_api/base_resource.rb (1 hunks)
  • lib/bridge_api/resources/customer.rb (2 hunks)
  • lib/bridge_api/resources/kyc_link.rb (1 hunks)
  • lib/bridge_api/resources/reward_rate.rb (1 hunks)
  • lib/bridge_api/resources/transaction_history.rb (1 hunks)
  • lib/bridge_api/resources/virtual_account.rb (1 hunks)
  • lib/bridge_api/resources/wallet.rb (1 hunks)
  • lib/bridge_api/resources/webhook.rb (2 hunks)
  • lib/bridge_api/resources/webhook_event.rb (1 hunks)
  • lib/bridge_api/resources/webhook_event_delivery_log.rb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/bridge_api/resources/wallet.rb
🧰 Additional context used
🧬 Code graph analysis (1)
lib/bridge_api/base_resource.rb (3)
lib/bridge_api/client.rb (2)
  • method_missing (159-166)
  • respond_to_missing? (168-170)
lib/bridge_api/models/wallets_collection.rb (1)
  • empty? (19-21)
lib/bridge_api/list_object.rb (1)
  • empty? (36-38)
🔇 Additional comments (4)
lib/bridge_api/resources/webhook.rb (1)

23-25: LGTM: Proper delegation to parent class.

Delegating to super aligns with the standard inheritance pattern and allows the parent class (APIResource) to handle the create operation consistently.

lib/bridge_api/base_resource.rb (2)

124-136: LGTM: Proper dynamic attribute access implementation.

The method_missing and respond_to_missing? implementation correctly enables dynamic attribute access while maintaining safety:

  • Only responds for zero-argument calls to keys present in @values
  • Properly delegates to super for unknown methods or methods with arguments
  • Includes respond_to_missing? for correct Ruby introspection protocol
  • Explicit accessor methods in subclasses will still take precedence since method_missing is only invoked when no explicit method exists

143-144: LGTM: Recursive hash symbolization improves consistency.

The enhanced convert_value logic for Hash values recursively symbolizes keys and converts nested values, ensuring consistent attribute access patterns across nested API response structures.

lib/bridge_api/resources/customer.rb (1)

49-56: LGTM! Clean datetime accessor implementation.

The created_at and updated_at accessors correctly parse datetime strings from the raw attribute values, delegating to the defensive parse_datetime helper.

Changed require_relative from '../base_resource' to 'base_service' to correct the dependency path. Refactored the get method to call retrieve as a class method on @resource_class, passing @client and webhook_id, instead of instantiating a new resource object.
@bolom bolom merged commit 707debf into master Nov 24, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants