define associative model in Golang gorm - go

I am using golang gorm in my RestFul service, however, now I have a doubt that might be simple but I cannot find any example or specific documentation, its not clear to me.
Let's say that I have the tables users and languages, any user can have many languages and any language can have many users, in this case for theory of relational database modeling we have to create a table users_languages, and checking gorm I see that I will have to use many to many relationship.
By now, I have the structs that define the user and language tables, lets say:
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
}
Then I ran the migrations and the tables User and Language were created. My question is, how should I define then the structure of the user_languages table? how the foreign keys are set there?

how should I define then the structure of the user_languages table?
You should also describe the user_languages model for many2many relations like User and Language as example
type UserLanguages struct {
gorm.Model
UserId int
LanguageId int
}
And probably you should define primary keys for User and Language models
how the foreign keys are set there?
GORM generates names of foreign keys in queries yourself, in underscore format (like user_id, language_id), for redefining it you can use special AssociationForeignKey annotation on model fields, I hope it will help!

Related

Should I create three models or a polymorphic type

I have a Laravel 8 application and am wondering how to solve the problem of how to solve a typical polymorphic issue. I have an Employee model. That Employee can be an ExecutiveEmployee or EntryLevelEmployee. There will be methods an ExecutiveEmployee has that an EntryLevelEmployee doesn't have and the inverse is also true.
Using Laravel 8, is it right to create a base Employee model (without a corresponding table?) and then create two models named ExecutiveEmployee and EntryLevelEmployee that inherit from Employee? This would also imply that both employee types will have two different database tables, even though there will be a lot of overlapping data.
Does it make sense to just have one Employee model and create a migration that has the employee type listed in the model? I am assuming that it's ok if an EntryLevelEmployee has some database attributes which are relevant to it that may or may not be relevant to an ExecutiveEmployee type here, or is that an incorrect assumption?
What's the correct way to model this in Laravel 8? I prefer to keep everything in one table because of how similar the models are. I do have to keep in mind that there will be data that one has that the other doesn't. There will be different accessor methods as well.
Is it possible to have everything in one employees table while utilizing multiple models? Meaning, if I create two models named ExecutiveEmployee and EntryLevelEmployee they would both query the underlying table employees?
UPDATE 1
The more I research, the more I think polymorphism is the incorrect approach here and what I might need is Single-Table Inheritance. This package seems to bring the capability to Eloquent. Would there be a good reason to not use this?
I would use polymorphic relationships in this case, because you are more flexible and have less coupling.
Using the Single Table Inheritance (STI), you can add type specific columns in the employees table and make them nullable. But think about adding/removing types in the future.
executive_employees
id - integer
executive_specific - string
entry_level_employees
id - integer
entry_level_specific - string
employees
id - integer
name - string
email - string
employable_id - integer
employable_type - string
As for the STI the same would be
employees
id - integer
name - string
email - string
type - string
executive_specific - nullable string
entry_level_specific - nullable string
So STI would be suitable when you don't have type specific columns. But you want to add specific behavior in your code. For example a User type (Admin, Author).
Even so, it's a matter of preferences.
It really depends on the state and behavior of your employee object.
Below are few points I will consider to make a decision
If your objects' states/properties are different then definitely you will create different models as your data will be stored in different tables.
If most states/properties are same and some are different, you can
consider storing all in one table/model and for the difference in
behavior create separate table like Ron Van Der Heijden has
suggested and you can consider query scope with that to make
transaction with database.
And another view will be
How many JOINs you will create if you will create different tables,
will that impact the performance and other stuffs, will it make your
code complex?
Can you make simpler relations and handle stuffs independently?
When you are making an API, will your
code make the api overworking? or you need to create too many request
for any operation?
These stuffs will decide how you will make a decision.
Update 1:
Another point I would like to add about the package you are thinking to use, consider using a parent key in table and you can define relationships in a single model.I do not think you need to use a package, you can define it yourself, I guess.
I don't understand why you don't create a simple one-to-many relation. Based on the information you provided, the polymorphic relation looks unnecessary. I think the right way is to create employee_roles table and relations. Then you can give different permissions to different employee types. There are several ways to do that. You can create a middleware to create route restrictions. You can check the role before executing a function in the controller, and run only if the employee has permission. You can use if-else in blade not to render the parts that can't be used by auth user etc.
If you have different “types” of employees, and each employee type should have different logic then yeah, that sounds like a polymorphic relationship.

How to implement specific Part/BOM design using two foreign keys from BOM to Part in GORM?

Here's a picture of a generic Bill of Materials.
How does one implement the join table named "BOM" above using GORM and its tags? (Ignore the supplier tables.)
type Part struct {
gorm.Model
Parents []Part
Children []Part
}
Update
The goal is to query for a part, P, and be able to show all the parts that P is used in and all the parts P uses. The ER diagram designs this kind of solution in the database. I've built solutions in SQL and other languages to do this. Now I'd like to use GORM to provide it.
Because Quantity is in the join table, there will have to be a declared struct rather than a GORM generated join table. Something like this:
type Bom struct {
Parent Part
Child Part
Quantity int
}
How do I indicate to GORM that Bom has two foreign keys into Part?
How do I furnish the slices in Part from Bom?

Laravel: Polymorphic types table vs many types tables

I am trying to determine what the best way to many a relationship describing a type would be using Laravel. For example, I might have a user model that can be of many types. Everything I have ever been taught would suggest I need to make a users_types. However, if I wanted to use Eloquent to reference this relationship, I would also need to make a UserType model and an IdentificationType model. For example:
// User Class
public function type() {
return $this->belongsTo('App\UserType');
}
// User Type Class
public function users(){
return $this->hasMany('App\User');
}
$user->type->description; // Could return 'casual'
This seems like it could quickly become ridiculous if I have a bunch of models and each one could potentially have a "type" or maybe a "status".
Would it be better to make a single types table or a single status table and manage everything with a polymorphic relationship, or is that bad database design? Is there a better way to accomplish this using Query Builder instead of Eloquent?
If it makes semantic sense then using a polymorphic relationship is reasonable. The example Laravel sets is with commentable entities. A commentable entity can either be a video or a post (both allow comments).
In your case you'd need to do something like these tables:
typable_type
type_id | typable_id | typable_type
type
id | name
and use:
public function type() {
return $this->morphToMany(Type::class,"type");
}
There's no practical reason why you can't do this anyway, in your case. There is however a semantic reason. Example:
A User can be of type primary , a Product can be of type primary however does that mean the same thing? For example does it make sense to say : "Everything primary can be accessed through this page" in short when you say primary user and primary product, does the word primary carry the same meaning? If the answer is yes then polymorphism is something you should use.

Golang Gorm: Is it possible to delete a record via a many2many relationship?

I have a many2many structure similar to GORM's example:
// User has and belongs to many languages, use `user_languages` as join table
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
}
db.Model(&user).Related(&languages)
Let's say I create a user and it has two associated languages.
I fetch a user record from the database and remove one language from the user's Languages array. I then save the user with gorm:save_associations set to true.
I would expect GORM to delete the record associating the user to this language (in the association table that GORM manages). However, it is not deleted. Is this expected?
Is it possible to delete many2many association records by removing a language from the Languages list on the user record and then saving the user? If not, how should this be done in GORM?
Update
I found a solution to this question, but not sure it's the best way to do this. I store the current languages, clear all the associations, then add back the languages, then save.
languages := user.Languages
DB.Model(&user).Association("Languages").Clear()
user.Languages = languages
I was having the same problem, If you want to just remove one of the associations this worked for me
c.DB.Model(&user).Association("Roles").Delete(&role)
Also, you can do this by using "replace"
DB.Model(&user).Association("Languages").Replace(user.Languages)
I found a solution to this question, but not sure it's the best way to do this. I store the current languages, clear all the associations, then add back the languages, then save.
languages := user.Languages
DB.Model(&user).Association("Languages").Clear()
user.Languages = languages
This is something that i am using it. If this is helpful to anyone.
db.Preload("Languages").Find(&user, r.FormValues("id"))
db.Model(&user).Association("Languages").Clear()
db.Save(&user) // We are deleting all the records first
.....
.....
user.Languages = languages
db.Save(&user) // Re insert all the records

how can I 'walk' the relationships between tables in LINQ?

Let's say I have three tables:
Office
ID
SalespeopleOffice
ID
OfficeID
PersonID
People
ID
ManagerID
In LINQ to SQL, how can I start from the SalespeopleOffices table and "walk" from that table to the People table or the Office table via the relationships between the tables? Specifically without knowing what those relationships are; pull the data about the relationships instead of interacting with the objects directly. I'm looking for a way to programatically analyze table relationships. The database I'm working with has many more tables than this, so in reality it's a lot more complex than this.
I'd ideally like to create a LinqPad script to do this.
You can use reflection to examine the properties on each type in the context. (In LinqPad, the context is this).
Value and string properties will be scalar fields on the table,
EntitySet properties will represent [something]-to-many relationships, and
other types will be [something]-to-one relationships.
If you connect the two sides of the relationships you can figure out what the [something] is in each case. Does that make sense?
Edit
I was just poking around a little, and there's a better approach. The model information is available via the Mapping property. Try this:
var tableData = from t in this.Mapping.GetTables()
select new
{
t.TableName,
Associations =
from a in t.RowType.Associations
select new
{
a.ThisMember.Name,
TypeName = a.ThisMember.Type.Name
}
};
tableData.Dump();
Assuming you've activated Auto Completion, it should be a piece of cake to find the exact data you're interested in by exploring the properties on this meta data.
If you're using LINQ to SQL, your SalespeopleOffices instances shoud have People and Office properties.
Something like:
var salesPO = dataContext.SalespeopleOffices.First()
var office = salesPO.Office
var man = salesPO.People

Resources