Module: Dynamoid::Fields::ClassMethods

Defined in:
lib/dynamoid/fields.rb

Instance Method Summary collapse

Instance Method Details

#field(name, type = :string, options = {}) ⇒ Object

Specify a field for a document.

class User
  include Dynamoid::Document

  field :last_name
  field :age, :integer
  field :last_sign_in, :datetime
end

Its type determines how it is coerced when read in and out of the data store. You can specify string, integer, number, set, array, map, datetime, date, serialized, raw, boolean and binary or specify a class that defines a serialization strategy.

By default field type is string.

Set can store elements of the same type only (it’s a limitation of DynamoDB itself). If a set should store elements only of some particular type then of option should be specified:

field :hobbies, :set, of: :string

Only string, integer, number, date, datetime and serialized element types are supported.

Element type can have own options - they should be specified in the form of Hash:

field :hobbies, :set, of: { serialized: { serializer: JSON } }

Array can contain element of different types but if supports the same of option to convert all the provided elements to the declared type.

field :rates, :array, of: :number

By default date and datetime fields are stored as integer values. The format can be changed to string with option store_as_string:

field :published_on, :datetime, store_as_string: true

Boolean field by default is stored as a string t or f. But DynamoDB supports boolean type natively. In order to switch to the native boolean type an option store_as_native_boolean should be specified:

field :active, :boolean, store_as_native_boolean: true

If you specify the serialized type a value will be serialized to string in Yaml format by default. Custom way to serialize value to string can be specified with serializer option. Custom serializer should have dump and load methods.

If you specify a class for field type, Dynamoid will serialize using dynamoid_dump method and load using dynamoid_load method.

Default field type is string.

A field can have a default value. It’s assigned at initializing a model if no value is specified:

field :age, :integer, default: 1

If a defautl value should be recalculated every time it can be specified as a callable object (it should implement a call method e.g. Proc object):

field :date_of_birth, :date, default: -> { Date.today }

For every field Dynamoid creates several methods:

  • getter

  • setter

  • predicate <name>? to check whether a value set

  • <name>_before_type_cast? to get an original field value before it was type casted

It works in the following way:

class User
  include Dynamoid::Document

  field :age, :integer
end

user = User.new
user.age # => nil
user.age? # => false

user.age = 20
user.age? # => true

user.age = '21'
user.age # => 21 - integer
user.age_before_type_cast # => '21' - string

There is also an option alias which allows to use another name for a field:

class User
  include Dynamoid::Document

  field :firstName, :string, alias: :first_name
end

user = User.new(firstName: 'Michael')
user.firstName # Michael
user.first_name # Michael

Parameters:

  • name (Symbol)

    name of the field

  • type (Symbol) (defaults to: :string)

    type of the field (optional)

  • options (Hash) (defaults to: {})

    any additional options for the field type (optional)

Options Hash (options):

  • :of (Symbol)

    <description>

  • :store_as_string (Symbol)

    <description>

  • :store_as_native_boolean (Symbol)

    <description>

  • :default (Symbol)

    <description>

  • :alias (Symbol)

    <description>

Since:

  • 0.2.0



144
145
146
147
148
149
150
151
# File 'lib/dynamoid/fields.rb', line 144

def field(name, type = :string, options = {})
  if type == :float
    Dynamoid.logger.warn("Field type :float, which you declared for '#{name}', is deprecated in favor of :number.")
    type = :number
  end

  Dynamoid::Fields::Declare.new(self, name, type, options).call
end

#generated_methodsObject



305
306
307
308
309
# File 'lib/dynamoid/fields.rb', line 305

def generated_methods
  @generated_methods ||= Module.new.tap do |mod|
    include(mod)
  end
end

#range(name, type = :string, options = {}) ⇒ Object

Declare a table range key.

class User
  include Dynamoid::Document

  range :last_name
end

By default a range key is a string. In order to use any other type it should be specified as a second argument:

range :age, :integer

Type options can be specified as well:

range :date_of_birth, :date, store_as_string: true

Parameters:

  • name (Symbol)

    a range key attribute name

  • type (Symbol) (defaults to: :string)

    a range key type (optional)

  • options (Hash) (defaults to: {})

    type options (optional)



173
174
175
176
# File 'lib/dynamoid/fields.rb', line 173

def range(name, type = :string, options = {})
  field(name, type, options)
  self.range_key = name
end

#remove_field(field) ⇒ Object

Remove a field declaration

Removes a field from the list of fields and removes all te generated for a field methods.

Parameters:

  • field (Symbol)

    a field name



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/dynamoid/fields.rb', line 283

def remove_field(field)
  field = field.to_sym
  attributes.delete(field) || raise('No such field')

  # Dirty API
  undefine_attribute_methods
  define_attribute_methods attributes.keys

  generated_methods.module_eval do
    remove_method field
    remove_method :"#{field}="
    remove_method :"#{field}?"
    remove_method :"#{field}_before_type_cast"
  end
end

#table(options) ⇒ Object

Set table level properties.

There are some sensible defaults:

  • table name is based on a model class e.g. users for User class

  • hash key name - id by default

  • hash key type - string by default

  • generating timestamp fields created_at and updated_at

  • billing mode and read/write capacity units

The table method can be used to override the defaults:

class User
  include Dynamoid::Document

  table name: :customers, key: :uuid
end

The hash key field is declared by default and a type is a string. If another type is needed the field should be declared explicitly:

class User
  include Dynamoid::Document

  field :id, :integer
end

To declare a new attribute with not-default type as a table hash key a :key_type option can be used:

class User
  include Dynamoid::Document

  table key: :user_id, key_type: :integer
end

Parameters:

  • options (Hash)

    options to override default table settings

Options Hash (options):

  • :name (Symbol)

    name of a table

  • :arn (Symbol)

    table ARN; it allows referring tables in another AWS accounts; has higher priority than the name option

  • :key (Symbol)

    name of a hash key attribute

  • :key_type (Symbol)

    type of a hash key attribute

  • :inheritance_field (Symbol)

    name of an attribute used for STI

  • :skip_generating_fields (Array<Symbol>)

    don’t generate implicitly methods with given names, e.g. :id, :created_at, :updated_at

  • :capacity_mode (Symbol)

    table billing mode - either provisioned or on_demand

  • :write_capacity (Integer)

    table write capacity units

  • :read_capacity (Integer)

    table read capacity units

  • :timestamps (true|false)

    whether generate created_at and updated_at fields or not

  • :expires (Hash)

    set up a table TTL and should have following structure { field: <attriubute name>, after: <seconds> }

Since:

  • 0.4.0



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/dynamoid/fields.rb', line 228

def table(options)
  self.options = options

  id_already_declared = true
  timestamps_already_declared = Dynamoid::Config.timestamps

  # a default 'id' column is created when Dynamoid::Document is included
  unless attributes.key? hash_key
    remove_field :id
    id_already_declared = false

    key_type = options[:key_type] || :string
    field(hash_key, key_type)
    id_already_declared = hash_key == :id
  end

  # The created_at/updated_at fields are declared in the `included` callback first.
  # At that moment the only known setting is `Dynamoid::Config.timestamps`.
  # Now `options[:timestamps]` may override the global setting for a model.
  # So we need to make decision again and declare the fields or rollback thier declaration.
  #
  # Do not replace with `#timestamps_enabled?`.
  if options[:timestamps] && !timestamps_already_declared
    # The fields weren't declared in `included` callback because they are disabled globaly
    field :created_at, :datetime
    field :updated_at, :datetime

    timestamps_already_declared = true
  elsif options[:timestamps] == false && timestamps_already_declared
    # The fields were declared in `included` callback but they are disabled for a table
    remove_field :created_at
    remove_field :updated_at

    timestamps_already_declared = false
  end

  # handle :skip_generating_fields option
  skip_generating_fields = options[:skip_generating_fields] || []
  if id_already_declared && skip_generating_fields.include?(:id)
    remove_field :id
  end
  if timestamps_already_declared && skip_generating_fields.include?(:created_at)
    remove_field :created_at
  end
  if timestamps_already_declared && skip_generating_fields.include?(:updated_at)
    remove_field :updated_at
  end
end

#timestamps_enabled?Boolean

Returns:

  • (Boolean)


300
301
302
# File 'lib/dynamoid/fields.rb', line 300

def timestamps_enabled?
  options[:timestamps] || (options[:timestamps].nil? && Dynamoid::Config.timestamps)
end