Class: Attio::Internal::Record Private

Inherits:
APIResource show all
Defined in:
lib/attio/internal/record.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Base class for record-based resources (Person, Company, etc.) This class handles the complex Attio Record API and should not be used directly. Use Person, Company, or TypedRecord instead.

Direct Known Subclasses

TypedRecord

Constant Summary

Constants inherited from APIResource

APIResource::SKIP_KEYS

Instance Attribute Summary collapse

Attributes inherited from APIResource

#created_at, #id, #metadata

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from APIResource

#==, #[], #[]=, api_operations, attr_attio, #changed, #changed?, #changed_attributes, #changes, #each, execute_request, #fetch, #hash, id_param_name, #key?, #keys, #persisted?, prepare_params_for_create, prepare_params_for_update, #reset_changes!, resource_name, #revert!, #to_json, #update_attributes, #update_from, validate_id!, #values

Constructor Details

#initialize(attributes = {}, opts = {}) ⇒ Record

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Record.



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/attio/internal/record.rb', line 26

def initialize(attributes = {}, opts = {})
  super

  normalized_attrs = normalize_attributes(attributes)
  @attio_object_id = normalized_attrs[:object_id]
  @object_api_slug = normalized_attrs[:object_api_slug]

  # Process values into attributes
  if normalized_attrs[:values]
    process_values(normalized_attrs[:values])
  end
end

Instance Attribute Details

#attio_object_idObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



24
25
26
# File 'lib/attio/internal/record.rb', line 24

def attio_object_id
  @attio_object_id
end

#object_api_slugObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



24
25
26
# File 'lib/attio/internal/record.rb', line 24

def object_api_slug
  @object_api_slug
end

Class Method Details

.create(object: nil, values: nil, data: nil, **opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Create a new record



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/attio/internal/record.rb', line 56

def create(object: nil, values: nil, data: nil, **opts)
  # Handle both parameter styles
  if values
    # Test style: create(object: "people", values: {...})
    validate_object_identifier!(object)
    validate_values!(values)
    normalized_values = values
  elsif data && data[:values]
    # API style: create(object: "people", data: { values: {...} })
    validate_object_identifier!(object)
    validate_values!(data[:values])
    normalized_values = data[:values]
  else
    raise ArgumentError, "Must provide object and either values or data.values"
  end

  normalized = normalize_values(normalized_values)
  puts "DEBUG: Normalized values: #{normalized.inspect}" if ENV["ATTIO_DEBUG"]

  request_params = {
    data: {
      values: normalized
    }
  }

  response = execute_request(:POST, "#{resource_path}/#{object}/records", request_params, opts)

  # Ensure object info is included
  record_data = response["data"] || {}
  record_data["object_api_slug"] ||= object if record_data.is_a?(Hash)

  new(record_data, opts)
end

.list(object:, **opts) ⇒ Object Also known as: all

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

List records for an object



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/attio/internal/record.rb', line 41

def list(object:, **opts)
  validate_object_identifier!(object)

  # Extract query parameters from opts
  # Handle both opts[:params] (from find_by) and direct opts (from other callers)
  params = opts[:params] || opts
  query_params = build_query_params(params)

  response = execute_request(:POST, "#{resource_path}/#{object}/records/query", query_params, opts)

  APIResource::ListObject.new(response, self, opts.merge(object: object), opts)
end

.resource_pathString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

API endpoint path for records (nested under objects)

Returns:

  • (String)

    The API path



20
21
22
# File 'lib/attio/internal/record.rb', line 20

def self.resource_path
  "objects"
end

.retrieve(record_id: nil, object: nil, **opts) ⇒ Object Also known as: get, find

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retrieve a specific record



91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/attio/internal/record.rb', line 91

def retrieve(record_id: nil, object: nil, **opts)
  validate_object_identifier!(object)

  # Extract simple ID if it's a nested hash
  simple_record_id = record_id.is_a?(Hash) ? record_id["record_id"] : record_id
  validate_id!(simple_record_id)

  response = execute_request(:GET, "#{resource_path}/#{object}/records/#{simple_record_id}", {}, opts)

  record_data = response["data"] || {}
  record_data["object_api_slug"] ||= object if record_data.is_a?(Hash)

  new(record_data, opts)
end

.search(query, object:, **opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Search records Note: The Attio API doesn't have a search endpoint, so we use filtering This provides a basic search across common text fields



133
134
135
136
137
# File 'lib/attio/internal/record.rb', line 133

def search(query, object:, **opts)
  # For now, just pass through to list with the query
  # Subclasses should override this to provide proper search filters
  list(object: object, **opts)
end

.update(record_id: nil, object: nil, data: nil, **opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Update a record



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/attio/internal/record.rb', line 109

def update(record_id: nil, object: nil, data: nil, **opts)
  validate_object_identifier!(object)

  # Extract simple ID if it's a nested hash
  simple_record_id = record_id.is_a?(Hash) ? record_id["record_id"] : record_id
  validate_id!(simple_record_id)

  request_params = {
    data: {
      values: normalize_values(data[:values] || data)
    }
  }

  response = execute_request(:PUT, "#{resource_path}/#{object}/records/#{simple_record_id}", request_params, opts)

  record_data = response["data"] || {}
  record_data["object_api_slug"] ||= object if record_data.is_a?(Hash)

  new(record_data, opts)
end

Instance Method Details

#add_to_list(list_id) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Add this record to a list



260
261
262
263
# File 'lib/attio/internal/record.rb', line 260

def add_to_list(list_id, **)
  list = List.retrieve(list_id, **)
  list.add_record(id, **)
end

#destroy(**opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Override destroy to use correct path



281
282
283
284
285
286
287
288
289
290
291
# File 'lib/attio/internal/record.rb', line 281

def destroy(**opts)
  raise InvalidRequestError, "Cannot destroy a record without an ID" unless persisted?
  raise InvalidRequestError, "Cannot destroy without object context" unless object_api_slug

  self.class.send(:execute_request, :DELETE, resource_path, {}, opts)
  @attributes.clear
  @changed_attributes.clear
  @id = nil
  freeze
  true
end

#inspectString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Human-readable representation of the record

Returns:

  • (String)

    Inspection string with ID, object, and sample values



309
310
311
312
313
314
# File 'lib/attio/internal/record.rb', line 309

def inspect
  values_preview = @attributes.take(3).map { |k, v| "#{k}: #{v.inspect}" }.join(", ")
  values_preview += "..." if @attributes.size > 3

  "#<#{self.class.name}:#{object_id} id=#{id.inspect} object=#{object_api_slug.inspect} values={#{values_preview}}>"
end

#listsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get lists containing this record



266
267
268
269
270
271
272
# File 'lib/attio/internal/record.rb', line 266

def lists(**)
  raise InvalidRequestError, "Cannot get lists without an ID" unless persisted?

  # This is a simplified implementation - in reality you'd need to query the API
  # for lists that contain this record
  List.list(record_id: id, **)
end

#resource_pathObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



274
275
276
277
278
# File 'lib/attio/internal/record.rb', line 274

def resource_path
  raise InvalidRequestError, "Cannot generate path without object context" unless object_api_slug
  record_id = id.is_a?(Hash) ? id["record_id"] : id
  "#{self.class.resource_path}/#{object_api_slug}/records/#{record_id}"
end

#save(**opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Save changes to the record



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/attio/internal/record.rb', line 240

def save(**opts)
  raise InvalidRequestError, "Cannot update a record without an ID" unless persisted?
  raise InvalidRequestError, "Cannot save without object context" unless object_api_slug

  return self unless changed?

  params = {
    data: {
      values: prepare_values_for_update
    }
  }

  response = self.class.send(:execute_request, :PATCH, resource_path, params, opts)

  update_from(response[:data] || response)
  reset_changes!
  self
end

#to_hHash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Convert record to hash representation

Returns:

  • (Hash)

    Record data as a hash



295
296
297
298
299
300
301
302
303
304
305
# File 'lib/attio/internal/record.rb', line 295

def to_h
  values = @attributes.except(:id, :created_at, :object_id, :object_api_slug)

  {
    id: id,
    object_id: attio_object_id,
    object_api_slug: object_api_slug,
    created_at: created_at&.iso8601,
    values: values
  }.compact
end