I wanted to know if it is possible to have STI where the subclasses each relate to an unrelated model in different ways.
In other words, say B < A and C < A, and I implement single table inheritance on table A (e.g. a type column where you can have B or C to indicate a subclass).
Now let's say we have a separate model called Xyzzy.
Is it possible to implement a has_and_belongs_to_many relationship between C and Xyzzy while implementing a has_one relationship between B and Xyzzy?
How should I do this in the context of STI? Or would STI simply not affect this?
There is nothing particular to do to make this happen. Simply create your relationships.
Indeed, even if B and C have access to some columns they don't care about, well... they simply don't care about.
Related
I am working on a food related Laravel project where I have three main models: RawMaterial, SemiFinished and Finished. A semiFinished object can contain a list of RawMaterial model objects while a Finished object can contain a list of both SemiFinished objects or RawMaterial objects.
I am aware that the solution lies in using polymorphic relationships but I cant seem to get to the right approach.
Please share your ideas on how such a solution would be implemented on both migrations and models/relationships level
Thanks a bunch
You could easily implement your own manual polymorphic relationships on your Finished model. Basically how it works is you will need 2 important fields here, which is the ingredient_id and ingredient_type (change the name to your preference). Then, inside your Finished model, you can make 3 types of relationships, which is ingredients() to get all ingredients regarding the type, semiFinishedIngredients() to get only the semi finished ingredients, and rawIngredients() to get only the raw ingredients. Again, this is optional, add it on your own needs.
Is it okay to use a polymorphic relation when there are lets say 6 common columns and 2 columns with different names?
I need to track car maintenance and refueling.
maintenances - table
-date
-km_driven
-info (refers to maintenance info )
refuelings - table
-date
-km_driven
-amount (refers to amount in liters)
So, should i use polymorphic relationship or not? Is it ok if there are more different columns per model?
IMHO for your case I will go for single table inheritance (STI), but you need a library like this tightenco/parental or this one Nanigans/single-table-inheritance.
Laravel codebase has no support for STI without an external library. You can try to use polymorphic relation to solve your case but you will end up with 3 different tables. I think you want to use a single table with two or even three models so my advice is to try one of the STI library above.
STI is appropriate when your models have shared data/state. Shared behavior is optional because can be defined per Model. An example could be different type of vehicle Models: Car, Truck, Bike etc..
With Polymorphic Relations instead, a model can belong_to several models with a single association. This is useful when several models do not have a relationship or share data with each other, but have a relationship with the polymorphic class. An example could be the Comment Model that can belongs to other Models: User, Post, Image etc..
The first form of database normalisation is to hold potentially null fields in a second table, and join these in when they are referred to. The SQL would look something like this.
SELECT A.*, DA.* FROM ANIMALS A
INNER JOIN DOG_ATTRIBUTES DA ON DA.ANIMAL_ID = A.ID
This is pretty common for large databases to use, so only a dog would have the dog-specific attributes. Now I know this could be implemented as a has_one relationship, e.g.
class Dog < Animal
has_one :dog_attribute
end
If it was a read-only model, I could implement the above SQL as a view, and just refer to the DOGS view in my Dog model.
Is there a way I can treat the composite Dog object (with attributes from the ANIMALS table and the DOG_ATTRIBUTES table) as a single model, placing attributes of both into forms, saving them as one command and retrieving the attributes of both?
You're looking for Multiple-Table Inheritance (MTI). Rails by default only supports single-table inheritance, but you can install ActiveRecord::ActsAs for this capability.
Simulates multiple-table-inheritance (MTI) for ActiveRecord models. By
default, ActiveRecord only supports single-table inheritance (STI).
MTI gives you the benefits of STI but without having to place dozens
of empty fields into a single table.`
I'm trying to create a one-to-one association between two models, called A and B. Model B can exist in either table Foo, if Foo exists, or table Bar, all other situations.
I tried using the :dataset flag of the one_to_one association method to get it to work, but can't seem to figure out how to make it work without introducing a circular dependency.
Is there a way to accomplish this with Sequel associations? Or is the best course of action to hand-write SQL?
I'm not sure I completely understand what you are attempting to do, but from your description, you should just need to make B's table dependent on whether table Foo exists:
class B < Sequel::Model(DB.table_exists?(:Foo) ? :Foo : :Bar); end
If you really wanted to do it just for the association and not for all of model B, you can modify the FROM table in the association block:
A.many_to_one(:b){|ds| ds.from(ds.db.table_exists?(:Foo) ? :Foo : :Bar)}
I haven't tested either of these, but they should work. If that's not what you want, you probably want to add more detail to your description.
So, this is a bit complicated: I have two tables, say cats and dogs.
They are in a many-to-many relationship (could be called friendships or whatever), so that Doctrine automatically creates a table cats_dogs for me with the appropriate fields. (that is rowid, cat_id, dog_id per default.)
Now, imagine I have a third table, award, where I want to award one of these friendships. Here I therefore need a field that references one row in cats_dogs. However, since this table does not really exist between my models, (Doctrine handles it for me) what would be the most elegant solution for this?
In the end, I want in my award model two fields, a cat and a dog, who need to be in a friendship.
I am using the annotation driver.
What stops you from manually creating the m:n table instead of having doctrine do it for you?
The Doctrine aims is to map objects from an E/R schema and to make easier the access to object connections. Therefore I believe that the table cats_dogs automatically provided by Doctrine is necessary as it is. It is concise and hits its purposes, i.e. it provides a list of all dogs of a cat or, vice versa, all the cats of a dog.
Thus, I can conclude that it is preferable to create a third entity (besides Cat and Dog) named Award which provides a one-to-one relationship with Cat and another one-to-one relationship with Dog. Making it consistent with the cats_dogs table is only up to you, and is not a Doctrine task by default. E.g., you can use some cascade persist option.
I believe that this is the most effective solution with Doctrine.
As a final remark, consider that each table should map a specific relationship between one or more entities, and in fact the table cats_dogs represents the friendship relationships, while the table Award will represent the awarded relationship relationship between two friends.