Module: DeclareSchema::Model::ClassMethods

Defined in:
lib/declare_schema/model.rb

Instance Method Summary collapse

Instance Method Details

#_defined_primary_keyObject

returns the primary key (String) as declared with primary_key = unlike the primary_key method, DOES NOT query the database to find the actual primary key in use right now if no explicit primary key set, returns the default_defined_primary_key



161
162
163
164
165
# File 'lib/declare_schema/model.rb', line 161

def _defined_primary_key
  if defined?(@primary_key)
    @primary_key&.to_s
  end || _default_defined_primary_key
end

#attr_type(name) ⇒ Object

Returns the type (a class) for a given field or association. If the association is a collection (has_many or habtm) return the AssociationReflection instead



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/declare_schema/model.rb', line 269

public \
def attr_type(name)
  if attr_types.nil? && self != self.name.constantize
    raise "attr_types called on a stale class object (#{self.name}). Avoid storing persistent references to classes"
  end

  attr_types[name] ||
    if (refl = reflections[name.to_s])
      if refl.macro.in?([:has_one, :belongs_to]) && !refl.options[:polymorphic]
        refl.klass
      else
        refl
      end
    end ||
    if (col = _column(name.to_s))
      DeclareSchema::PLAIN_TYPES[col.type] || col.klass
    end
end

#belongs_to(name, scope = nil, **options) ⇒ Object

Extend belongs_to so that it creates a FieldSpec for the foreign key



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/declare_schema/model.rb', line 105

def belongs_to(name, scope = nil, **options)
  column_options = {}

  column_options[:null] = if options.has_key?(:null)
                            options.delete(:null)
                          elsif options.has_key?(:optional)
                            options[:optional] # infer :null from :optional
                          end || false
  column_options[:default] = options.delete(:default) if options.has_key?(:default)
  column_options[:limit] = options.delete(:limit) if options.has_key?(:limit)

  index_options = {}
  index_options[:name]   = options.delete(:index) if options.has_key?(:index)
  index_options[:unique] = options.delete(:unique) if options.has_key?(:unique)
  index_options[:allow_equivalent] = options.delete(:allow_equivalent) if options.has_key?(:allow_equivalent)

  fk_options = options.dup
  fk_options[:constraint_name] = options.delete(:constraint) if options.has_key?(:constraint)
  fk_options[:index_name] = index_options[:name]

  fk = options[:foreign_key]&.to_s || "#{name}_id"

  if !options.has_key?(:optional)
    options[:optional] = column_options[:null] # infer :optional from :null
  end

  fk_options[:dependent] = options.delete(:far_end_dependent) if options.has_key?(:far_end_dependent)

  if Rails::VERSION::MAJOR >= 5
    super
  else
    super(name, scope, options.except(:optional))
  end

  refl = reflections[name.to_s] or raise "Couldn't find reflection #{name} in #{reflections.keys}"
  fkey = refl.foreign_key or raise "Couldn't find foreign_key for #{name} in #{refl.inspect}"
  declare_field(fkey.to_sym, :integer, column_options)
  if refl.options[:polymorphic]
    foreign_type = options[:foreign_type] || "#{name}_type"
    _declare_polymorphic_type_field(foreign_type, column_options)
    index([foreign_type, fkey], index_options) if index_options[:name] != false
  else
    index(fkey, index_options) if index_options[:name] != false
    constraint(fkey, fk_options) if fk_options[:constraint_name] != false
  end
end

#constraint(fkey, options = {}) ⇒ Object



69
70
71
72
73
74
# File 'lib/declare_schema/model.rb', line 69

def constraint(fkey, options = {})
  fkey_s = fkey.to_s
  unless constraint_specs.any? { |constraint_spec| constraint_spec.foreign_key == fkey_s }
    constraint_specs << DeclareSchema::Model::ForeignKeyDefinition.new(self, fkey, options)
  end
end

#declare_field(name, type, *args, **options) ⇒ Object

Declare named field with a type and an arbitrary set of arguments. The arguments are forwarded to the #field_added callback, allowing custom metadata to be added to field declarations.



86
87
88
89
90
91
92
93
94
# File 'lib/declare_schema/model.rb', line 86

def declare_field(name, type, *args, **options)
  try(:field_added, name, type, args, options)
  _add_serialize_for_field(name, type, options)
  _add_formatting_for_field(name, type)
  _add_validations_for_field(name, type, args, options)
  _add_index_for_field(name, args, options)
  field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, position: field_specs.size, **options)
  attr_order << name unless attr_order.include?(name)
end

#ignore_index(index_name) ⇒ Object

tell the migration generator to ignore the named index. Useful for existing indexes, or for indexes that can’t be automatically generated (for example: a prefix index in MySQL)



78
79
80
# File 'lib/declare_schema/model.rb', line 78

def ignore_index(index_name)
  ignore_indexes << index_name.to_s
end

#index(fields, options = {}) ⇒ Object



57
58
59
60
61
62
63
# File 'lib/declare_schema/model.rb', line 57

def index(fields, options = {})
  # make index idempotent
  index_fields_s = Array.wrap(fields).map(&:to_s)
  unless index_definitions.any? { |index_spec| index_spec.fields == index_fields_s }
    index_definitions << ::DeclareSchema::Model::IndexDefinition.new(self, fields, options)
  end
end

#index_definitions_with_primary_keyObject



96
97
98
99
100
101
102
# File 'lib/declare_schema/model.rb', line 96

def index_definitions_with_primary_key
  if index_definitions.any?(&:primary_key?)
    index_definitions
  else
    index_definitions + [_rails_default_primary_key]
  end
end

#primary_keyObject



153
154
155
# File 'lib/declare_schema/model.rb', line 153

def primary_key
  super || 'id'
end

#primary_key_index(*fields) ⇒ Object



65
66
67
# File 'lib/declare_schema/model.rb', line 65

def primary_key_index(*fields)
  index(fields.flatten, unique: true, name: ::DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME)
end