Facultative relation with Doctrine ORM - symfony1

How should be implemented facultative one-to-one relation in Doctrine ORM and Symfony? Suppose there are some folders represented in database. Each folder can have a default icon or some custom icon represented in another table. How should this relation be described in the schema file? How can I tell that in case of given folder relation does or doesn't occur?
I myself have to guesses, but each seems to be not quite good:
1) Let's say I define folder_icon table with id column and folder_icon_id column in folder table and link these columns with foreign key. If folder_icon_id contains NULL, relation doesn't occur. If it contains some integer value it points to respective folder icon. When I implement it this way and try to obtain folder icon using something like $folder->getFolderIcon(), I get an instance of FolderIcon class with fields set to null (where I would rather excpect to get something like NULL, FALSE or Doctrine_Null). Why is it so? How should I check if the returned object is not 'real' folder icon?
2) Let's assume that I use method similar to previous but I define first row of folder_icon table to be the default icon, so that each folder that doesn't have any custom icon selected is related to this first row. In this case there is no problem with getting some dummy instances of FolderIcon class. But there is a problem if custom folder icon is removed form database, as there is no onDelete behaviour 'SET 1' to relate any folders using the deleted icon with the default icon.
How should this problem be solved? What is the proper way to define this kind of relation in schema file?

The problem is with the magic methods getVariable
Use $folder->folder_icon and to test for an existence of that relationship use isset(). Have a read of the doctrine website docs about testing for the existence of a relationship, I'm currently mobile so unable to link to it.

Related

rename domain class, groovy and grails reverse engineering

How do a rename a domain class while reverse engineering or after reverse engineering.
i generated class using reverse engineering in Groovy and Grails.
the domain class name was AgentTable. I want to rename it as Agent. When i renamed the domain class using IntelliJ (right click - refactor - rename), it renamed the AgentTable to Agent whereever it was used. but when i start the server (run the app), giving error
"nested exception is org.hibernate.HibernateException: Missing table: agent"
I have to do this for few domain class. is it anyway i can give an alternative name while reverse engineering the domain classes.
or after domain class was created how do i rename it without this error.
Look into your database the name of the table it created for the agent. Once you know the name of the table add the following in your new domain
static mapping = {
table "table-name-here"
}
While it works I would not recommend #elixir 's approach.
In my opinion the mapping is not supposed to be used for renames. This is also how I understand the official documentation.
In the example they use it to map Person onto the 'people' table, not because of a rename but because of a semantic reason. Tables are typically named after the plural form. Here is a nice answer on another question regarding this. In the project I am working on the domain object 'User' is mapped to the table 'users'. You can not use the table name 'user' as it is an SQL statement.
Assumptions and clarifications:
In my experience Grails maps the domain name to the table name after these rules (example domain name 'MyExampleDomain':
separate the domain name by capital letters (My Example Domain)
lower case all (my example domain)
replace spaces with underlines (my_example_domain)
Following this your Domain Class 'AgentTable' has a table 'agent_table' in your respective database. After your rename Grails even tells you what it wants:
nested exception is org.hibernate.HibernateException: Missing table: agent
It wants to look up values in a table called 'agent' but it can not find it. The refactor function of IntelliJ does not rename the functions, so it will miss out on the database.
Luckily we know exactly what values it wants - the values previously found in 'agent_table'.
So why create this confusion with remapping domains and table names when we could just rename the table and be done with it?
The solution:
Execute an SQL script like this on your database:
ALTER TABLE <old_domain_name> RENAME TO <new_domain_name>;
The names are of course in their "table-form".
This simply renames your table to match the expected format in Grails. When restarting everything should be fine.
However you do not need to use rename. You could also create a whole new table, build it the way the domain objects wants it to be and then migrate the data. See section 'Problems with this approach' for information on when to use what.
Problems with this approach:
As always, tinkering with information a program depends on (and even generated itself) will often have some dire consequences if you aren't careful.
For example we have to pay attention to keys. If your domain object has a relation to other objects it will hold them in the table via foreign keys. Depending on how you chose to migrate the information in the table you might have deleted these foreign keys connections. You will have to add them via a separate SQL statement. When you choose to recreate the table this will happen for sure. Renaming it should keep the keys.
Another one are column names. If you choose to rename attributes you will also have to rename the columns via SQL. You will also have to remember the foreign keys other tables might have on the table you are renaming. RENAME did this automatically for me, but you should double check.
Why you should still stick with this approach:
Remapping domain objects to the tables with old names is bound to create code smell and confusion. Do you really want to remember these mappings in your head? And more importantly: do you really expect other people to have to work with this?
The best case is if people can't even tell if this object has ever had a different name and changing the database is the best way I know to achieve this.

Facing an issue in accessing a rails model

My postgres table is having a column name called "class". On accessing the relevant model to this table am getting this error: (Object doesn't support #inspect). This all issue is because of using a reserved word as a column name.
Is there any solution to this to make the model accessible without modifying/renaming the column name of the table? Am using Rails5. Thanks in advance for any suggestions.
I just tested with a column named class, it seems to mess up ActiveRecord's internals somehow. Thus I think you'll need to rename that column to e.g. klass.
Or, in case you can't change DB schema, create an updatable view on top of it, where you name the column as you please.

How do I add a column that points to another table in a Rails database?

Let's say I currently have a table titled "Report" and within Report, there are a bunch of strings, integers, timestamps, etc.
Now, I want to somehow be able to see who is currently working on a certain report - all I need are names, but the key is it could be more than one name so just adding a string column to the Report table wouldn't work. Plus, the names would keep changing - at one point, "Steve" and "John" could be working on a report, but once "Steve" stops, I need to be able to get rid of his name from the table.
I have a feeling that the correct way to do this is by:
creating a new table titled "Viewers" and having just one string field (for the person's name) in there. I'd add rows to this table when a new viewer is detected.
linking to indices within the Viewers table from the Report table. When a person stops viewing the report, the respective index is destroyed.
I think that makes sense logically, but I'm hesitant to implement this without being sure that this is the way to go. Any help/feedback/suggestions would be appreciated!
Edit:
I created a model for my join table and it auto-generated a migration and added an integer "viewer_id" and an integer "report_id" like Vimsha suggested below. However, I can't correctly implement the join tables in my code for some reason - when I want to add to the new Table (report_viewers), I say:
#viewer = ReportViewer.new
#viewer.viewer_id = get_current_user[:id]
#viewer.report_id = this_report.id
#viewer.save
However, when I access the table via
ReportViewer.where(:report_id => my_report.id).last.viewer_id.name (the viewer table has a string name)
it gives me a nil class. Do you know why?
Looks like you need a join table report_viewers
report_viewers
-report_id
-viewer_id
When you detect a new viewer, add an entry with report_id and viewer_id.
Remove the record if the viewer stops viewing the report.
What i usually do is use
rails generate migration addviewertoreport
and then just add the relevant commands

Entity Framework - Creating a lookup NavigationProperty

Quick question that requires a long explanation..
Say I have two tables - one is an item table (say 'Users') and another is a definition table - like 'Custom Properties'. Many different items in the system ('Users', 'Articles', 'Posts', etc) can all have custom property defined to them, and these are stored in the 'Custom Properties' table. So, for example, the 'Custom Properties' table looks like:
CREATE TABLE [CUSTOMPROP_DEFINITION] (
[ITEM_TYPE] INTEGER NOT NULL,
[POSITION] INTEGER NOT NULL,
[NAME] NVARCHAR(MAX) NOT NULL
)
Simple little table. Each item has a 'item_type' id (for example, a user is an item type of 1. Article would be an item type of 2, and so on), so this table could have multiple rows for each item. Essentially, this table's metadata for the other tables.
I want to create a navigation property on my Users table, that will link to all the entries in the props table where 'item_type' == 1.
What's the best way of going about this? From the way I see it, there are two options -
(1) Creating a navigation property through the EDMX and letting it populate it automagically. (This is preferred, but having troubles implementing..) or
(2) Creating a property in the partial class, and having that load everything manually.
The issue with #2 is that it would (could potentially?) be slower than having the entity framework handle loading.
The issue with #1 is that.. no matter what I try, I can't get a NavigationProperty defined that will handle it. Because the primary key is a fixed number - i.e. It will always be '1' for ALL Users, always be '2' for all articles, etc.. - I haven't been able to find a way to hook into that.
Thoughts?
--Mike.
What you're describing isn't really a "Navigation Property" in terms of what EF defines as a naviation property. A navigation property in EF terms follows a [usually] primary key - foreign key reference in the database schema itself. And, AFAIK, the only way to get that navigation property in the EDMX is for there to actually be a FK involved.
You could, obviously (and probably do) have a FK here, but that's not entirely what you want, because that FK is going to return all instances of your custom properties for the given primary key. What you want is instances of only a particular type; and I don't think there is a "off the shelf" way of doing this in EF.
What you probably want to do is implement a Stored Procedure, and bring that into your model; you could then implement this is a property (or probably more appropriately a method) on your entity.
Alternatively, you could just create the FK, have your entity load all of the custom properties, and then write "helper properties" that do simple LINQ based .Where() filters.

Why does "linq to sql classes" change the name of a table when making a class?

I go in and add a new "linq to sql classes" in Visual Studio and then go and drag a table from Database Explorer to the new DBML and the name of the new class is no longer plural. What if I still want it to be plural? If I drag a table that isn't plural I get a bunch of compile errors about how there is already a type definition for all of the fields in the table I put on the dbml layout. If I then make the class name plural for the table that wasn't plural in the dbml layout by clicking on the name and changing it then no more compile errors.
You can single click on the tablename in the dbml table and rename it. Or you can select the table in the DBML and go to the properties window. There you can change the name, and the table it hooks up to.
One way to avoid the name conflict is to designate namespaces accordingly. For example, you can place your DBML file in a subfolder in your project and assign it something like DataAccess. Therefore, when you map to the Ling2Sql class, you'd do DataAccess.Customer and you can avoid the conflict with Customer, since it lives somewhere else.
As a tidbit, Linq2Sql by default makes tables non-plural. It's based off of a convention. For example, a table Customers has many customers. When you instantiate an object, you're looking at a single Customer, not the table. The object is essentially being mapped to a row in the Customers table, thus it becomes singular.
I just figured out what was happening. After the "move it to a new folder" suggestion I tried that and it worked. But it didn't make any sense as to why it worked because if there were type conflicts there should have still been the same conflicts in the new folder but I had none of the problems I was having before and I could rename things anything I wanted after moving to a new folder and there were no conflicts. Renaming things after dragging it over is a bad idea because if the database schema changes and you want to update your classes you have to drag the table back over and then make the changes manually again.
ANYWAY, the problem is that before I made the "linq to sql classes" I made a "ADO.NET Entity Data Model". That's what was causing all the name conflicts. But the suggestion about moving it to a new folder was awesome and led me to the final solution!

Resources