Module: Airtable::ORM::Attributes

Extended by:
ActiveSupport::Concern
Included in:
Base
Defined in:
lib/airtable/orm/attributes.rb

Defined Under Namespace

Classes: AirtableArrayType

Constant Summary collapse

READ_ONLY_ATTRIBUTES =

Special read-only attributes that are not part of the Airtable fields

%i[id created_at].freeze

Instance Method Summary collapse

Instance Method Details

#[](key) ⇒ Object

Override [] to use symbol keys only



115
116
117
118
119
120
121
122
123
# File 'lib/airtable/orm/attributes.rb', line 115

def [](key)
  validate_symbol_key!(key)

  # Handle special read-only attributes
  return read_special_attribute(key) if special_attribute?(key)

  validate_regular_attribute!(key)
  public_send(key)
end

#[]=(key, value) ⇒ Object

Override []= to use symbol keys only



126
127
128
129
130
131
132
# File 'lib/airtable/orm/attributes.rb', line 126

def []=(key, value)
  validate_symbol_key!(key)
  validate_not_readonly!(key)
  validate_regular_attribute!(key)

  public_send("#{key}=", value)
end

#attribute_defined?(symbol) ⇒ Boolean

Check if attribute is defined (explicitly declared in the model class body)

Returns:

  • (Boolean)


214
215
216
# File 'lib/airtable/orm/attributes.rb', line 214

def attribute_defined?(symbol)
  self.class.attribute_types.key?(symbol.to_s)
end

#fields_for_createObject

Non-nil attributes with field IDs as keys (for CREATE).



156
157
158
# File 'lib/airtable/orm/attributes.rb', line 156

def fields_for_create
  map_attributes(key_type: :field_id, exclude_nil: true)
end

#fields_for_updateObject

Changed attributes with field IDs as keys (for UPDATE). Includes nil values.



161
162
163
# File 'lib/airtable/orm/attributes.rb', line 161

def fields_for_update
  map_attributes(key_type: :field_id, filter: ->(symbol) { changed.include?(symbol.to_s) })
end

#map_attributes(key_type:, exclude_nil: false, filter: nil) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/airtable/orm/attributes.rb', line 165

def map_attributes(key_type:, exclude_nil: false, filter: nil)
  return {} unless self.class.field_mapping

  self.class.field_mapping.each_with_object({}) do |(symbol, field_id), hash|
    next if filter && !filter.call(symbol)

    value = read_raw_attribute(symbol)
    next if exclude_nil && value.nil?

    key = key_type == :symbol ? symbol : field_id
    hash[key] = value
  end
end

#read_raw_attribute(key) ⇒ Object

Used by Associations to avoid infinite recursion when association name matches the attribute.



136
137
138
139
140
# File 'lib/airtable/orm/attributes.rb', line 136

def read_raw_attribute(key)
  return nil unless attribute_defined?(key)

  @attributes[key.to_s]&.value
end

#read_special_attribute(key) ⇒ Object

Read a special read-only attribute value



206
207
208
209
210
211
# File 'lib/airtable/orm/attributes.rb', line 206

def read_special_attribute(key)
  case key
  when :id then @id
  when :created_at then @created_at
  end
end

#special_attribute?(key) ⇒ Boolean

Check if this is a special read-only attribute

Returns:

  • (Boolean)


201
202
203
# File 'lib/airtable/orm/attributes.rb', line 201

def special_attribute?(key)
  READ_ONLY_ATTRIBUTES.include?(key)
end

#symbol_attributesObject

Get all attributes as a hash with symbol keys. Delegates to ActiveModel::Attributes#attributes which returns the same data with string keys.



151
152
153
# File 'lib/airtable/orm/attributes.rb', line 151

def symbol_attributes
  attributes.symbolize_keys
end

#validate_not_readonly!(key) ⇒ Object

Validate that key is not a read-only attribute



187
188
189
190
191
# File 'lib/airtable/orm/attributes.rb', line 187

def validate_not_readonly!(key)
  return unless READ_ONLY_ATTRIBUTES.include?(key)

  raise Airtable::ORM::InvalidAttributeError, "Cannot set read-only attribute: #{key.inspect}"
end

#validate_regular_attribute!(key) ⇒ Object

Validate that key is a known regular attribute (not special attributes like :id, :created_at)



194
195
196
197
198
# File 'lib/airtable/orm/attributes.rb', line 194

def validate_regular_attribute!(key)
  return if attribute_defined?(key)

  raise Airtable::ORM::UnknownFieldError, "Unknown field symbol: #{key.inspect}"
end

#validate_symbol_key!(key) ⇒ Object

Validate that key is a symbol



180
181
182
183
184
# File 'lib/airtable/orm/attributes.rb', line 180

def validate_symbol_key!(key)
  return if key.is_a?(Symbol)

  raise Airtable::ORM::InvalidAttributeError, "Only symbol keys are supported (e.g., record[:email])"
end

#write_raw_attribute(key, value) ⇒ Object



143
144
145
146
147
# File 'lib/airtable/orm/attributes.rb', line 143

def write_raw_attribute(key, value)
  return unless attribute_defined?(key)

  @attributes.write_from_user(key.to_s, value)
end