How to create a model with multiple tables in Rails? - mysql

In my Rails application I am linking into a MySQL database from the legacy PHP application. The naming conventions are incorrect, so am making use of self.table_name to connect models to their respective tables.
I have a requirement to show information from multiple tables into one resource. All these tables have the same column structure. Can I create a model that pulls information from each of these tables? How do I do that? I have been playing around with find_by_sql but am yet to have any success
EDIT: This is all to be read only, no updating is required.

From your question I believe you are planning to load a other models from one particular model. My suggest is to use a polymorphic relationship.
class MainModel
has_many :sub_model, polymorphic: true
end
class Item1
belong_to :main_model, as: :sub_model
end
class Item2
belong_to :main_model, as: :sub_model
end
Now in the view you will have to write your data as follows.
#main_model.sub_model.name | #main_model.sub_model.value
Since all the other models/tables has the same structure you won't have to change the attribute.
And when updating it, you just accept the values of the sub_models as a nested attribute and they will update the corresponding model.
For more details on how to setup a polymorphic relationship visit Setting up a polymorphic association

Related

Laravel User Model with two relationships to same Model

I have a User model and an Events model. A User has_many Events (can create several events), and Events belong to User. However, since my Events also have a registration, I thought the best way would be to add a pivot table users_events_table that would contain all the registration, and now both Models pass to the belongs_to relationship.
Is there any way to maintain both relationships?
Yes - you're probably after a has many through relationship. It works similar to a belongs to many relationship except the pivot table is a first-class model, which means you can attach additional functionality to it. A user can have many events through registrations and vice-versa.
If you don't actually need that much additional information on the pivot table - maybe you just need created_at/updated_at timestamps then you can get away with belongs to many and pop withTimestamps() on the end - Laravel will handle that for you. It does allow you to add more columns on that pivot table but they can get tricky to manage depending on you use case, which is where has many through might become a better solution.

Django Foreign key in another database

I have two separate Django apps with two different databases. In APP1 I need all of the records from one table which is in APP2 DB. Beside that, one of my APP1 models has a ForeignKey which points to APP2 model, and according to docs this is not possible.
As Django does not support foreign key relationships spanning multiple databases i don't know what to do.
Official docs:
If you have used a router to partition models to different databases,
any foreign key and many-to-many relationships defined by those models
must be internal to a single database.
This is because of referential integrity. In order to maintain a
relationship between two objects, Django needs to know that the
primary key of the related object is valid. If the primary key is
stored on a separate database, it’s not possible to easily evaluate
the validity of a primary key.
As a solution I have thought of merging these two databases, so then these two APPS would use one same database. But then i would have a mess with models because APP1 needs only one table from APP2, and it doesn't need remaining models and DB tables. Also, i'm pretty sure it would make problems (conflicts) while making migrations from these two apps to the one same database.
I'm using Django DB router and this is what i've tried so far:
class Car(models.Model):
_DATABASE = "cars"
color = models.TextField(max_length=1000)
...
class Employee(models.Model):
id = models.IntegerField()
car = models.ForeignKey(Car)
...
It gives me:
django.db.utils.OperationalError: (1054, "Unknow column 'car' in 'employees'")
One DB or Two?
First question to ask your self is it really really necessary to have two different databases? More than one app using the same database is quite common in the PHP world where most people are on shared hosting and the hosting plan allows for only one database.
It's very rare for a website to have sufficient traffic to split the content between two databases. And usually the over head of the router makes it not worth the while. Sharding is almost always better handled with specialized software.
Yep it has to be two!
This is not impossible but just darned hard.
The first thing to do is to change your Car model
class Car(models.Model):
color = models.TextField(max_length=1000)
class Meta:
managed = False
Note that it no longer refers to the second database and it's unmanaged. But you don't have such a table in your database. So you need to create a view
CREATE OR REPLACE VIEW myapp_cars AS SELECT * FROM cars.otherapp_cars
Please make sure to use the exact database and table names to match your existing ones. We are only half way through. You need to create a trigger to insert into the other database. That has been discussed here many times before, so I will not elaborate. Examples
MySQL Trigger to insert data into different DB
How to create trigger to insert data to a database on another server
If you want these steps to be reproducible you will need to add a migration manually.
I thing this problem has nothing to do with django. By design DBMS doesn't allow FK between databases. Maybe you can found some workaround on internet but probable they don't adhere to best practices.
Check Cross Database Relations section at:
https://docs.djangoproject.com/en/3.2/topics/db/multi-db/
What worked for me was setting the ForeignKey db_constraint to False. This way, no constraint is created during the migration, but the correct field type is still created (from the target model's primary key). The database integrity is not enforced, so you have to know what you are doing. The ForeignKey field is indexed by Django regardless of this flag.
Example:
class Employee(models.Model):
car = models.ForeignKey(Car, db_constraint=False)
...
Docs: https://docs.djangoproject.com/en/4.1/ref/models/fields/#django.db.models.ForeignKey.db_constraint
This flag has existed at least since version 1.x, so I don't know how it didn't come up before.
Needless to say, you are sacrificing your database constraint, so if a record is deleted on the other database, you will have an invalid reference and this may cause exceptions in Django when accessing the property.
DB Router
You will also need to tell Django that you allow relations between databases. You can do that by adding the following method to your router class:
class MyRouter:
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == 'default' and obj2._meta.app_label == 'database2':
return True
This function should return True if the router should allow the relation, False if you want to actively deny it, and None for the default behaviour - which is allowing only relations in the same database (which is not what we want). A looser implementation would be to just allow everything (return True).
Docs: https://docs.djangoproject.com/en/4.1/topics/db/multi-db/#allow_relation

Grails not generating all SQL tables in many-to-many

I'm a new to Grails and have started a project, but I'm having troubles finding out what is wrong:
The project is already connected to my database (SQL) and it has a few many-to-many to relationship with more than 1 "parameter", like this:
static hasMany = [rules:AvaliateRules,professors:Professor,candidates:Candidate];
I run the application with no problems, but when I used show tables the transaction tables weren't all created. It just created the last parameter's table (candidate).
Any idea about the reason and how to fix it? everywhere I checked, people did the same as me and had no problems with the tables. I'm using grails 2.4.4 version.
I don't think that your current domain has many-to-many relationship with all entities that you mentioned. It might be a one-to-many relationship. Let's say your current domain is "DomainA". If only other domain like AvaliateRules,Professor has "DomainA" in hasMany then it makes it a many-to-many association.
In one-to-many association, only a column is added at the child level(many side) which contains a parentId to denote who the parent is.

Need suggestion on DB architecture

I am working on a Project where I have below use case.
User can have many taglines for them , we have lot of predefined data in the DB which we using to show autosuggestion when they started typing tag lines, I am using Rails.
User has_and_belongs_to_many taglines
Tagline has_and_belongs_to_many users
I have separate joint table and everything was fine , but now I need to store custom taglines of user to DB , which will be belongs to only particular user.
Should I clone the taglines table and add user ID to it Or what is the best architecture to handle these kind of scenario , if we have more than one model which have same use case as like taglines.
your existing user and tagline table has many-to-many relationship, keep it that way. Whereas the user table and the new customTagline has a one-to-many relationship so why don't you create a new table to represent it? Since you mentioned the customTagline belongs to only a particular user.
#BroiSatse Comment make sense, I followed same.
If you create a second table, you will need to remember to update two
tables/models every time you will want to change your model. You won;t
be able to pull all the user tags in one go neither. many-to-many is
able to hold one-to-many association. Just add a validation to check
that given tag can belong to only one user if it is custom.

Limit a user to view only associated records in rails

I have an application with three Models (Profile -> SubModel -> SubSubModel) chained together with has many relationships. I am trying to limit a user, after logging in, to only retrieving records that are associated with their Profile. I am very new to rails and this is what I had been trying in the Profile model
has_many :submodels, :conditions => {:profile_id => self.id}
but this is returning an empty data set when calling with Profile.find_by_id(1).submodels, how else could I achieve what I am trying to do. Or should I handle this in the controller or view instead, I thought it sounded well suited for the model to handle this.
you don't need any conditions on the has_many call - by default it will only return the SubModels associated with the Profile.
If you've named your classes and foreign/primary keys to Rails conventions, just use
class Profile
has_many :sub_models
end
and let Rails figure it out.
This assumes the following:
Profile wraps a table named profiles, which has a numeric primary key named id
SubModel wraps a table named sub_models, which has a numeric foreign key named profile_id