Class: DBDiagram::Domain::Attribute

Inherits:
Object
  • Object
show all
Extended by:
Inspectable
Defined in:
lib/db_diagram/domain/attribute.rb

Overview

Describes an entity’s attribute. Attributes correspond directly to database columns.

Constant Summary collapse

TIMESTAMP_NAMES =
%w{created_at created_on updated_at updated_on}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Inspectable

inspection_attributes

Constructor Details

#initialize(domain, model, column) ⇒ Attribute

Returns a new instance of Attribute.



38
39
40
# File 'lib/db_diagram/domain/attribute.rb', line 38

def initialize(domain, model, column) # @private :nodoc:
  @domain, @model, @column = domain, model, column
end

Instance Attribute Details

#columnObject (readonly)



36
37
38
# File 'lib/db_diagram/domain/attribute.rb', line 36

def column
  @column
end

Class Method Details

.from_model(domain, model) ⇒ Object



12
13
14
15
16
17
18
19
20
21
# File 'lib/db_diagram/domain/attribute.rb', line 12

def from_model(domain, model) # @private :nodoc:
  attributes = model.columns.collect { |column| new(domain, model, column) }
  attributes.sort! if DBDiagram.options[:sort]

  if DBDiagram.options[:prepend_primary]
    attributes = prepend_primary(model, attributes)
  end

  attributes
end

.prepend_primary(model, attributes) ⇒ Object



23
24
25
26
27
28
29
30
# File 'lib/db_diagram/domain/attribute.rb', line 23

def prepend_primary(model, attributes)
  primary_key = ActiveRecord::Base.get_primary_key(model)
  primary = attributes.index { |column| column.name == primary_key }

  return attributes if primary || primary == 0

  [primary_key, *attributes[0...primary], *attributes[(primary+1)..-1]]
end

Instance Method Details

#<=>(other) ⇒ Object



106
107
108
# File 'lib/db_diagram/domain/attribute.rb', line 106

def <=>(other) # @private :nodoc:
  name <=> other.name
end

#content?Boolean

Returns true if this attribute is a content column, that is, if it is not a primary key, foreign key, timestamp, or inheritance column.

Returns:

  • (Boolean)


55
56
57
# File 'lib/db_diagram/domain/attribute.rb', line 55

def content?
  !primary_key? and !foreign_key? and !timestamp? and !inheritance?
end

#false?Boolean

Method allows false to be set as an attributes option when making custom graphs. It rejects all attributes when called from Diagram#filtered_attributes method

Returns:

  • (Boolean)


91
92
93
# File 'lib/db_diagram/domain/attribute.rb', line 91

def false?
  false
end

#foreign_key?Boolean

Returns true if this attribute is used as a foreign key for any relationship.

Returns:

  • (Boolean)


77
78
79
80
81
# File 'lib/db_diagram/domain/attribute.rb', line 77

def foreign_key?
  @domain.relationships_by_entity_name(@model.name).map(&:associations).flatten.map { |associaton|
    associaton.send(Domain.foreign_key_method_name)
  }.include?(name)
end

#inheritance?Boolean

Returns true if this attribute is used for single table inheritance. These attributes are typically named type.

Returns:

  • (Boolean)


85
86
87
# File 'lib/db_diagram/domain/attribute.rb', line 85

def inheritance?
  @model.inheritance_column == name
end

#limitObject

Returns any non-standard limit for this attribute. If a column has no limit or uses a default database limit, this method returns nil.



135
136
137
138
139
# File 'lib/db_diagram/domain/attribute.rb', line 135

def limit
  return if native_type == 'geometry' || native_type == 'geography'
  return column.limit.to_i if column.limit != native_type[:limit] and column.limit.respond_to?(:to_i)
  column.precision.to_i if column.precision != native_type[:precision] and column.precision.respond_to?(:to_i)
end

#limit_descriptionObject

Returns a string that describes the limit for this attribute, such as (128), or (5,2) for decimal types. Returns nil if no non-standard limit was set.



150
151
152
153
# File 'lib/db_diagram/domain/attribute.rb', line 150

def limit_description # @private :nodoc:
  return "(#{limit},#{scale})" if limit and scale
  return "(#{limit})" if limit
end

#mandatory?Boolean

Returns true if this attribute is mandatory. Mandatory attributes either have a presence validation (validates_presence_of), or have a NOT NULL database constraint.

Returns:

  • (Boolean)


62
63
64
# File 'lib/db_diagram/domain/attribute.rb', line 62

def mandatory?
  !column.null or @model.validators_on(name).map(&:kind).include?(:presence)
end

#nameObject

The name of the attribute, equal to the column name.



43
44
45
# File 'lib/db_diagram/domain/attribute.rb', line 43

def name
  column.name
end

#primary_key?Boolean

Returns true if this attribute is the primary key of the entity.

Returns:

  • (Boolean)


71
72
73
# File 'lib/db_diagram/domain/attribute.rb', line 71

def primary_key?
  @model.primary_key.to_s == name.to_s
end

#scaleObject

Returns any non-standard scale for this attribute (decimal types only).



142
143
144
145
# File 'lib/db_diagram/domain/attribute.rb', line 142

def scale
  return column.scale.to_i if column.scale != native_type[:scale] and column.scale.respond_to?(:to_i)
  0 if column.precision
end

#timestamp?Boolean

Returns true if this attribute is one of the standard ‘magic’ Rails timestamp columns, being created_at, updated_at, created_on or updated_on.

Returns:

  • (Boolean)


102
103
104
# File 'lib/db_diagram/domain/attribute.rb', line 102

def timestamp?
  TIMESTAMP_NAMES.include? name
end

#to_sObject



110
111
112
# File 'lib/db_diagram/domain/attribute.rb', line 110

def to_s # @private :nodoc:
  name
end

#true?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/db_diagram/domain/attribute.rb', line 95

def true?
  true
end

#typeObject

The type of the attribute, equal to the Rails migration type. Can be any of :string, :integer, :boolean, :text, etc.



49
50
51
# File 'lib/db_diagram/domain/attribute.rb', line 49

def type
  column.sql_type.downcase.to_sym or column.type
end

#type_descriptionObject

Returns a description of the attribute type. If the attribute has a non-standard limit or if it is mandatory, this information is included.

Example output:

:integer

integer

:string, :limit => 255

string

:string, :limit => 128

string (128)

<tt>:decimal, :precision => 5, :scale => 2/tt>

decimal (5,2)

:boolean, :null => false

boolean *



123
124
125
126
127
128
129
130
131
# File 'lib/db_diagram/domain/attribute.rb', line 123

def type_description
  type.to_s.tap do |desc|
    # desc << " #{limit_description}" if limit_description
    desc << " ∗" if mandatory? && !primary_key? # Add a hair space + low asterisk (Unicode characters)
    desc << " U" if unique? && !primary_key? && !foreign_key? # Add U if unique but non-key
    desc << " PK" if primary_key?
    desc << " FK" if foreign_key?
  end
end

#unique?Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/db_diagram/domain/attribute.rb', line 66

def unique?
  @model.validators_on(name).map(&:kind).include?(:uniqueness)
end