Class: Basecamp::Services::BaseService
- Inherits:
-
Object
- Object
- Basecamp::Services::BaseService
- Defined in:
- lib/basecamp/generated/services/base_service.rb
Overview
Base service class for Basecamp API services.
Provides shared functionality for all service classes including:
- HTTP method delegation (http_get, http_post, etc.)
- Path building helpers
- Pagination support
Direct Known Subclasses
AccountService, AttachmentsService, AuthorizationService, AutomationService, BoostsService, CampfiresService, CardColumnsService, CardStepsService, CardTablesService, CardsService, CheckinsService, ClientApprovalsService, ClientCorrespondencesService, ClientRepliesService, ClientVisibilityService, CommentsService, DocumentsService, EventsService, ForwardsService, GaugesService, HillChartsService, LineupService, MessageBoardsService, MessageTypesService, MessagesService, MyAssignmentsService, MyNotificationsService, PeopleService, ProjectsService, RecordingsService, ReportsService, SchedulesService, SearchService, SubscriptionsService, TemplatesService, TimelineService, TimesheetsService, TodolistGroupsService, TodolistsService, TodosService, TodosetsService, ToolsService, UploadsService, VaultsService, WebhooksService, WormholesService
Instance Attribute Summary collapse
-
#account_id ⇒ String
readonly
The account ID for API requests.
Instance Method Summary collapse
-
#bucket_path(project_id, path) ⇒ String
protected
Build a bucket (project) path.
-
#compact_params(**kwargs) ⇒ Hash
protected
Helper to remove nil values from a hash.
-
#compact_query_params(**kwargs) ⇒ Hash
protected
Like compact_params, but also drops empty arrays.
-
#http ⇒ HTTP
protected
The HTTP client for direct access.
- #http_delete(path) ⇒ Object protected
- #http_get(path, params: {}) ⇒ Object protected
- #http_post(path, body: nil) ⇒ Object protected
- #http_post_raw(path, body:, content_type:) ⇒ Object protected
- #http_put(path, body: nil) ⇒ Object protected
-
#http_put_multipart(path, io:, filename:, content_type:, field: "file") ⇒ Object
protected
Upload a file as multipart/form-data.
-
#initialize(client) ⇒ BaseService
constructor
A new instance of BaseService.
-
#safe_hook ⇒ Object
protected
Invoke a hook callback, swallowing exceptions so hooks never break SDK behavior.
-
#with_operation(service:, operation:, resource_type: nil, is_mutation: false, project_id: nil, resource_id: nil) { ... } ⇒ Object
protected
Wraps a service operation with hooks for observability.
-
#wrap_paginated(service:, operation:, is_mutation: false, project_id: nil, resource_id: nil) ⇒ Object
protected
Wraps a lazy Enumerator so operation hooks fire around actual iteration, not at enumerator creation time.
-
#wrap_paginated_wrapped(key:, service:, operation:, is_mutation: false, project_id: nil, resource_id: nil) ⇒ Object
protected
Wraps a wrapped-paginated operation with hooks.
Constructor Details
#initialize(client) ⇒ BaseService
Returns a new instance of BaseService.
26 27 28 29 30 |
# File 'lib/basecamp/generated/services/base_service.rb', line 26 def initialize(client) @client = client @account_id = client.account_id @hooks = client.hooks end |
Instance Attribute Details
#account_id ⇒ String (readonly)
Returns the account ID for API requests.
23 24 25 |
# File 'lib/basecamp/generated/services/base_service.rb', line 23 def account_id @account_id end |
Instance Method Details
#bucket_path(project_id, path) ⇒ String (protected)
Build a bucket (project) path.
161 162 163 |
# File 'lib/basecamp/generated/services/base_service.rb', line 161 def bucket_path(project_id, path) "/buckets/#{project_id}#{path}" end |
#compact_params(**kwargs) ⇒ Hash (protected)
Helper to remove nil values from a hash.
140 141 142 |
# File 'lib/basecamp/generated/services/base_service.rb', line 140 def compact_params(**kwargs) kwargs.compact end |
#compact_query_params(**kwargs) ⇒ Hash (protected)
Like compact_params, but also drops empty arrays. For query filters an
empty array means "no filter" and must be omitted entirely: Faraday's
nested encoder would otherwise emit a bare bucket_ids[], which Rails
normalizes into a bogus [0] filter instead of the unfiltered request
the caller intended. Not used for request bodies, where an explicit
empty array (e.g. clearing a list) can be meaningful.
153 154 155 |
# File 'lib/basecamp/generated/services/base_service.rb', line 153 def compact_query_params(**kwargs) kwargs.reject { |_, value| value.nil? || value == [] } end |
#http ⇒ HTTP (protected)
Returns the HTTP client for direct access.
133 134 135 |
# File 'lib/basecamp/generated/services/base_service.rb', line 133 def http @client.http end |
#http_delete(path) ⇒ Object (protected)
179 180 181 182 183 |
# File 'lib/basecamp/generated/services/base_service.rb', line 179 %i[get post put delete post_raw put_raw].each do |method| define_method(:"http_#{method}") do |*args, **kwargs, &block| @client.public_send(method, *args, **kwargs, &block) end end |
#http_get(path, params: {}) ⇒ Object (protected)
179 180 181 182 183 |
# File 'lib/basecamp/generated/services/base_service.rb', line 179 %i[get post put delete post_raw put_raw].each do |method| define_method(:"http_#{method}") do |*args, **kwargs, &block| @client.public_send(method, *args, **kwargs, &block) end end |
#http_post(path, body: nil) ⇒ Object (protected)
179 180 181 182 183 |
# File 'lib/basecamp/generated/services/base_service.rb', line 179 %i[get post put delete post_raw put_raw].each do |method| define_method(:"http_#{method}") do |*args, **kwargs, &block| @client.public_send(method, *args, **kwargs, &block) end end |
#http_post_raw(path, body:, content_type:) ⇒ Object (protected)
179 180 181 182 183 |
# File 'lib/basecamp/generated/services/base_service.rb', line 179 %i[get post put delete post_raw put_raw].each do |method| define_method(:"http_#{method}") do |*args, **kwargs, &block| @client.public_send(method, *args, **kwargs, &block) end end |
#http_put(path, body: nil) ⇒ Object (protected)
179 180 181 182 183 |
# File 'lib/basecamp/generated/services/base_service.rb', line 179 %i[get post put delete post_raw put_raw].each do |method| define_method(:"http_#{method}") do |*args, **kwargs, &block| @client.public_send(method, *args, **kwargs, &block) end end |
#http_put_multipart(path, io:, filename:, content_type:, field: "file") ⇒ Object (protected)
Upload a file as multipart/form-data.
191 192 193 194 195 196 197 |
# File 'lib/basecamp/generated/services/base_service.rb', line 191 def http_put_multipart(path, io:, filename:, content_type:, field: "file") boundary = "BasecampSDK#{SecureRandom.hex(16)}" body = build_multipart_body(boundary: boundary, field: field, io: io, \ filename: filename, content_type: content_type) http_put_raw(path, body: body, content_type: "multipart/form-data; boundary=#{boundary}") nil end |
#safe_hook ⇒ Object (protected)
Invoke a hook callback, swallowing exceptions so hooks never break SDK behavior.
126 127 128 129 130 |
# File 'lib/basecamp/generated/services/base_service.rb', line 126 def safe_hook yield rescue => e warn "Basecamp hook error: #{e.class}: #{e.}" end |
#with_operation(service:, operation:, resource_type: nil, is_mutation: false, project_id: nil, resource_id: nil) { ... } ⇒ Object (protected)
Wraps a service operation with hooks for observability.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/basecamp/generated/services/base_service.rb', line 43 def with_operation(service:, operation:, resource_type: nil, is_mutation: false, project_id: nil, resource_id: nil) info = OperationInfo.new( service: service, operation: operation, resource_type: resource_type, is_mutation: is_mutation, project_id: project_id, resource_id: resource_id ) start = Process.clock_gettime(Process::CLOCK_MONOTONIC) safe_hook { @hooks.on_operation_start(info) } result = yield duration = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round safe_hook { @hooks.on_operation_end(info, OperationResult.new(duration_ms: duration, error: nil)) } result rescue => e duration = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round safe_hook { @hooks.on_operation_end(info, OperationResult.new(duration_ms: duration, error: e)) } raise end |
#wrap_paginated(service:, operation:, is_mutation: false, project_id: nil, resource_id: nil) ⇒ Object (protected)
Wraps a lazy Enumerator so operation hooks fire around actual iteration, not at enumerator creation time. Hooks fire when the consumer begins iterating (.each, .to_a, .first, etc.) and end fires via ensure when iteration completes, errors, or is cut short by break/take.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/basecamp/generated/services/base_service.rb', line 64 def wrap_paginated(service:, operation:, is_mutation: false, project_id: nil, resource_id: nil) info = OperationInfo.new( service: service, operation: operation, is_mutation: is_mutation, project_id: project_id, resource_id: resource_id ) enum = yield hooks = @hooks Enumerator.new do |yielder| start = Process.clock_gettime(Process::CLOCK_MONOTONIC) error = nil begin safe_hook { hooks.on_operation_start(info) } enum.each { |item| yielder.yield(item) } rescue => e error = e raise ensure duration = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round safe_hook { hooks.on_operation_end(info, OperationResult.new(duration_ms: duration, error: error)) } end end end |
#wrap_paginated_wrapped(key:, service:, operation:, is_mutation: false, project_id: nil, resource_id: nil) ⇒ Object (protected)
Wraps a wrapped-paginated operation with hooks. Fires on_operation_start eagerly (before page 1 fetch), on_operation_end when the events Enumerator completes/errors/breaks.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/basecamp/generated/services/base_service.rb', line 91 def wrap_paginated_wrapped(key:, service:, operation:, is_mutation: false, project_id: nil, resource_id: nil) info = OperationInfo.new( service: service, operation: operation, is_mutation: is_mutation, project_id: project_id, resource_id: resource_id ) hooks = @hooks start = Process.clock_gettime(Process::CLOCK_MONOTONIC) safe_hook { hooks.on_operation_start(info) } begin result = yield # paginate_wrapped fetches page 1 here rescue => e duration = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round safe_hook { hooks.on_operation_end(info, OperationResult.new(duration_ms: duration, error: e)) } raise end inner_enum = result[key] wrapped_enum = Enumerator.new do |yielder| error = nil begin inner_enum.each { |item| yielder.yield(item) } rescue => e error = e raise ensure duration = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round safe_hook { hooks.on_operation_end(info, OperationResult.new(duration_ms: duration, error: error)) } end end result.merge(key => wrapped_enum) end |