Class: CustomField

Inherits:
Field
  • Object
show all
Defined in:
app/models/fields/custom_field.rb

Overview

Implementation Notes


Adding database columns dynamically is not usually recommended, and can be potentially unsafe. However, the only alternative would be static migrations, and we want to let users add custom fields without having to restart their server. We could not use the EAV model for performance reasons, since we need to retain the ability to filter and search across thousands of records with potentially hundreds of custom fields.

We have solved all of the major issues:

  • Custom fields for view templates are dynamically generated based on normalized database records in the ‘fields’ table, instead of ActiveRecord’s cached attributes.

  • Concurrency issues are resolved by using ‘method_missing’ to refresh a model’s column information when fields are added by a separate server process.

  • The custom field can be renamed or deleted, but database columns are never renamed or destroyed. A rake task can be run to purge any orphaned columns.

  • Custom field types can only be changed if the database can support the transition. For example, you can change an ‘email’ field to a ‘string’, but not to a ‘datetime’, since changing the type of the database column would cause data to be lost.

Constant Summary collapse

SAFE_DB_TRANSITIONS =
{
  :any => [[:date, :time, :timestamp], [:integer, :float]],
  :one => {:string => :text}
}

Constants inherited from Field

Field::FIELD_TYPES, Field::KLASSES

Instance Method Summary collapse

Methods inherited from Field

#collection_string, #collection_string=, #column_type, field_types, #input_options, #render, #render_value

Instance Method Details

#available_asObject



70
71
72
73
74
# File 'app/models/fields/custom_field.rb', line 70

def available_as
  Field.field_types.reject do |new_type, params|
    db_transition_safety(as, new_type) == :unsafe
  end
end