User has many Toys, its `Polymorphic` is `Owner`, Pet has one Toy, its `Polymorphic` is `Owner` type User struct { Toys []Toy `gorm:"polymorphic:Owner;"` } type Pet struct { Toy Toy `gorm:"polymorphic:Owner;"` } type Toy struct { OwnerID int OwnerType string }
(relation *Relationship, field *Field)
| 193 | // OwnerType string |
| 194 | // } |
| 195 | func (schema *Schema) buildPolymorphicRelation(relation *Relationship, field *Field) { |
| 196 | polymorphic := field.TagSettings["POLYMORPHIC"] |
| 197 | |
| 198 | relation.Polymorphic = &Polymorphic{ |
| 199 | Value: schema.Table, |
| 200 | } |
| 201 | |
| 202 | var ( |
| 203 | typeName = polymorphic + "Type" |
| 204 | typeId = polymorphic + "ID" |
| 205 | ) |
| 206 | |
| 207 | if value, ok := field.TagSettings["POLYMORPHICTYPE"]; ok { |
| 208 | typeName = strings.TrimSpace(value) |
| 209 | } |
| 210 | |
| 211 | if value, ok := field.TagSettings["POLYMORPHICID"]; ok { |
| 212 | typeId = strings.TrimSpace(value) |
| 213 | } |
| 214 | |
| 215 | relation.Polymorphic.PolymorphicType = relation.FieldSchema.FieldsByName[typeName] |
| 216 | relation.Polymorphic.PolymorphicID = relation.FieldSchema.FieldsByName[typeId] |
| 217 | |
| 218 | if value, ok := field.TagSettings["POLYMORPHICVALUE"]; ok { |
| 219 | relation.Polymorphic.Value = strings.TrimSpace(value) |
| 220 | } |
| 221 | |
| 222 | if relation.Polymorphic.PolymorphicType == nil { |
| 223 | schema.err = fmt.Errorf("invalid polymorphic type %v for %v on field %s, missing field %s", |
| 224 | relation.FieldSchema, schema, field.Name, polymorphic+"Type") |
| 225 | } |
| 226 | |
| 227 | if relation.Polymorphic.PolymorphicID == nil { |
| 228 | schema.err = fmt.Errorf("invalid polymorphic type %v for %v on field %s, missing field %s", |
| 229 | relation.FieldSchema, schema, field.Name, polymorphic+"ID") |
| 230 | } |
| 231 | |
| 232 | if schema.err == nil { |
| 233 | relation.References = append(relation.References, &Reference{ |
| 234 | PrimaryValue: relation.Polymorphic.Value, |
| 235 | ForeignKey: relation.Polymorphic.PolymorphicType, |
| 236 | }) |
| 237 | |
| 238 | primaryKeyField := schema.PrioritizedPrimaryField |
| 239 | if len(relation.foreignKeys) > 0 { |
| 240 | if primaryKeyField = schema.LookUpField(relation.foreignKeys[0]); primaryKeyField == nil || len(relation.foreignKeys) > 1 { |
| 241 | schema.err = fmt.Errorf("invalid polymorphic foreign keys %+v for %v on field %s", relation.foreignKeys, |
| 242 | schema, field.Name) |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | if primaryKeyField == nil { |
| 247 | schema.err = fmt.Errorf("invalid polymorphic type %v for %v on field %s, missing primaryKey field", |
| 248 | relation.FieldSchema, schema, field.Name) |
| 249 | return |
| 250 | } |
| 251 | |
| 252 | // use same data type for foreign keys |
no test coverage detected