Module: DeclareSchema::Model::ClassMethods
- Defined in:
- lib/declare_schema/model.rb
Instance Method Summary collapse
-
#_declared_primary_key ⇒ Object
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_declared_primary_key.
- #_infer_fk_limit(fkey, refl) ⇒ Object
-
#attr_type(name) ⇒ Object
Returns the type (a class) for a given field or association.
-
#belongs_to(name, scope = nil, **options) ⇒ Object
Extend belongs_to so that it 1.
- #constraint(fkey, options = {}) ⇒ Object
-
#declare_field(name, type, *args, **options) ⇒ Object
Declare named field with a type and an arbitrary set of arguments.
-
#ignore_index(index_name) ⇒ Object
tell the migration generator to ignore the named index.
- #index(fields, options = {}) ⇒ Object
- #index_definitions_with_primary_key ⇒ Object
- #primary_key_index(*fields) ⇒ Object
Instance Method Details
#_declared_primary_key ⇒ Object
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_declared_primary_key
192 193 194 195 196 |
# File 'lib/declare_schema/model.rb', line 192 def _declared_primary_key if defined?(@primary_key) @primary_key&.to_s end || _default_declared_primary_key end |
#_infer_fk_limit(fkey, refl) ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/declare_schema/model.rb', line 167 def _infer_fk_limit(fkey, refl) if refl.[:polymorphic] if (fkey_column = columns_hash[fkey.to_s]) && fkey_column.type == :integer fkey_column.limit end else klass = refl.klass or raise "Couldn't find belongs_to klass for #{name} in #{refl.inspect}" if (pk_id_type = klass.&.[](:id)) if pk_id_type == :integer 4 end else if klass.table_exists? && (pk_column = klass.columns_hash[klass._declared_primary_key]) pk_id_type = pk_column.type if pk_id_type == :integer pk_column.limit end end end end 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
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/declare_schema/model.rb', line 298 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.[: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
-
declares an index on the foreign key
-
declares a foreign_key constraint
103 104 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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/declare_schema/model.rb', line 103 def belongs_to(name, scope = nil, **) = {} [:null] = if .has_key?(:null) .delete(:null) elsif .has_key?(:optional) [:optional] # infer :null from :optional end || false [:default] = .delete(:default) if .has_key?(:default) if .has_key?(:limit) .delete(:limit) ActiveSupport::Deprecation.warn("belongs_to limit: is deprecated since it is now inferred") end = {} [:name] = .delete(:index) if .has_key?(:index) [:unique] = .delete(:unique) if .has_key?(:unique) [:allow_equivalent] = .delete(:allow_equivalent) if .has_key?(:allow_equivalent) = .dup [:constraint_name] = .delete(:constraint) if .has_key?(:constraint) [:index_name] = [:name] fk = [:foreign_key]&.to_s || "#{name}_id" if !.has_key?(:optional) [:optional] = [:null] # infer :optional from :null end [:dependent] = .delete(:far_end_dependent) if .has_key?(:far_end_dependent) super 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}" = .dup # Note: the foreign key limit: should match the primary key limit:. (If there is a foreign key constraint, # those limits _must_ match.) We'd like to call _infer_fk_limit and get the limit right from the PK. # But we can't here, because that will mess up the autoloader to follow every belongs_to association right # when it is declared. So instead we assume :bigint (integer limit: 8) below, while also registering this # pre_migration: callback to double-check that assumption Just In Time--right before we generate a migration. # # The one downside of this approach is that application code that asks the field_spec for the declared # foreign key limit: will always get 8 back even if this is a grandfathered foreign key that points to # a limit: 4 primary key. It seems unlikely that any application code would do this. [:pre_migration] = ->(field_spec) do if (inferred_limit = _infer_fk_limit(fkey, refl)) field_spec.[:limit] = inferred_limit end end declare_field(fkey.to_sym, :bigint, ) if refl.[:polymorphic] foreign_type = [:foreign_type] || "#{name}_type" _declare_polymorphic_type_field(foreign_type, ) index([foreign_type, fkey], ) if [:name] != false else index(fkey, ) if [:name] != false constraint(fkey, ) if [:constraint_name] != false end end |
#constraint(fkey, options = {}) ⇒ Object
64 65 66 67 68 69 |
# File 'lib/declare_schema/model.rb', line 64 def constraint(fkey, = {}) 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, ) 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.
81 82 83 84 85 86 87 88 89 |
# File 'lib/declare_schema/model.rb', line 81 def declare_field(name, type, *args, **) try(:field_added, name, type, args, ) _add_serialize_for_field(name, type, ) _add_formatting_for_field(name, type) _add_validations_for_field(name, type, args, ) _add_index_for_field(name, args, ) field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, position: field_specs.size, **) 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)
73 74 75 |
# File 'lib/declare_schema/model.rb', line 73 def ignore_index(index_name) ignore_indexes << index_name.to_s end |
#index(fields, options = {}) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/declare_schema/model.rb', line 52 def index(fields, = {}) # 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, ) end end |
#index_definitions_with_primary_key ⇒ Object
91 92 93 94 95 96 97 |
# File 'lib/declare_schema/model.rb', line 91 def index_definitions_with_primary_key if index_definitions.any?(&:primary_key?) index_definitions else index_definitions + [_rails_default_primary_key] end end |
#primary_key_index(*fields) ⇒ Object
60 61 62 |
# File 'lib/declare_schema/model.rb', line 60 def primary_key_index(*fields) index(fields.flatten, unique: true, name: ::DeclareSchema::Model::IndexDefinition::PRIMARY_KEY_NAME) end |