I am using Ruby on Rails, however am interested in a general solution as well. Lets say I have a model users, a model cuisines, and a relational table connecting the two allowing a user to have a list of 'favorite cuisines'. The user is presented with a list of all the cuisines and can check or uncheck them individually. For example lets say Alice starts off liking American, Indian, and Chinese food. She then unchecks Chinese and adds in Thai and hits save. Whats the best way to go about updating the relational table?
I have three solutions, but since this operation seems so common I was hoping for a more elegant solution. If there isn't, what is the standard way to do this?
keep a set of added and a set of removed, and make sure they have no overlap
drop all of the users favorite foods and insert the selected ones
make ajax calls to update each individual add and remove
use the association_ids approach. Instead of looking for a list cuisines and then assigning them to the user, just get a list of their ids and assign it to user.cuisine_ids. Saving the record will generate the association records for you. Since you're using checkboxes, be wary of the scenario where a user unchecks everything and then saves. What usually happens is no change is saved keeping the old selected cuisines selected. This can be easily fixed by adding a nil hidden value with the same name as the checkboxes.
Related
What is the most performance-efficient way to allow end-users to add custom properties to a core table used by an application.
For example, core table FRIENDS has columns ID, FIRST_NAME, LAST_NAME, and BIRTHDAY.
User 1 wants to also track additional properties FAVORITE_COLOR and LUCKY_NUMBER, but User 2 wants to also track different additional properties ZODIAC_SIGN, MARRIAGE_ANNIVERSRY_DATE, and GOLF_HANDICAP.
I have implemented two approaches for testing:
First approach: Add a new table FRIENDS_CUSTOM_PROPERTIES having an FK pointer back to FRIENDS and two columns for value pairs (KEY and VALUE such as FAVORITE_COLOR, YELLOW). This approach potentially requires many queries on FRIENDS_CUSTOM_PROPERTIES to retrieve all the properties for a given friend.
Second approach: Add extension columns right on the FRIENDS table itself of varying data types for CUSTOM_1, CUSTOM_2, ... CUSTOM_64, etc. If a user needed more custom properties than there were columns, my design would "spill over" to approach 1. This approach is more brute force but easily results in many NULL column values on many rows.
I can make both work but am unsure the best approach to determine which is better (or if there is already a clear best practice one way or another).
Thanks.
Approach number one is called entity-attribute-value as Rick James noted in the comments. It can do the job, but you sacrifice lots of useful features of SQL, like data types and constraints. See EAV FAIL for some of my writing on this.
You wrote something about running "many queries" but there's no advantage to doing that. You should plan on fetching the set of custom properties for a user in one query, and saving it to a map object in your client application.
The latter approach number two is incomplete. You would also need to store some kind of metadata so you know that for user 1, CUSTOM_1 means "Favorite Color" and CUSTOM_2 means "Lucky Number" and so on. Where do you plan to store the meaning of each column per user?
At least with the EAV design, each attribute comes with a key, so you know exactly what it means. And EAV allows for an unlimited number of properties, because each property gets a new row.
Ultimately, any design that allow for "user-defined properties" conflicts with principles of relational databases. Your columns no longer have any concept of a type. Read a book like SQL and Relation Theory to understand more about this.
(Table Relationships)
I'm developing a travel agency database, and I've got a table for contacts (people), a table for trips, and a junction table, people_has_trips. "Trip" refers to a table whose identity is mostly many-to-many relationships with various optional travel elements such as hotel, flight, etc. (I have doubts about this structure, but that's an issue for another question).
Anyway, I'm in the early phases of designing the form for Trips, which will almost entirely consist of subforms linking to junction tables. The problem that's given me the most difficulty so far is that of how to add a contact to a trip. I'm fairly new to access, and thus far I've been populating such tables using autofilling comboboxes, but the contacts table contains over 100,000 records, and as such some sort of search function would be prudent.
Here's what I have so far. This subform is based on the people_has_trips table, and currently is limited to showing existing records. I disabled all fields as not to allow the editing of People records, but I'm somewhat stumped as to how to handle adding more people. In my limited Access knowledge, the most logical solution to me seemed to be having a button to open a form that would allow the searching of People and perhaps the addition of new people.
Now, I have a fully realized form for entering new People (shown below), but it doesn't have any real search functionality besides Access's built-in filters. So my subform currently opens People and... does nothing else. Quite frankly, I have no idea where to go from here. Do I develop a second form for searching people, or do I build in search functionality to the primary People form, something I should probably do anyway? If so, How? And after doing either of those things, how do I then populate people_has_trips? The only answer I can think of involves the user clicking the button to open People, finding the person they want to add, and then manually entering the primary key into the subform, which surely isn't optimal.
The aforementioned People entry form
The solution, I would wager, is VBA commands. I've recently taken the time to learn some VBA, and I'm a bit more comfortable with it, but I just don't know where to begin with this problem. I'm confident that I can adapt and apply other people's VBA ideas and code, but I can't find a thread on this particular issue from which to do that! I'm guessing the reason I can't find any help for this issue is that it's so blatantly obvious that nobody has asked the question yet, or my Google skills are lacking. Either way, I'd be quite happy to facepalm in realization of the solution. Thanks any and all for their help!
You need to be focused on your core problem and as far as I understood, you want to search and add "users/contacts" to your "People on this trip" form.
Yes combo-boxes can eat up time loading 100k rows and it's not really search friendly.
In your "People in this trip" form you can:
have a text box => for search
have a combo-box => showing search result
[Search] [Add] [Clear] buttons
In theory,
search button performs a search on your TContacts table and assigns the results to the combobox. something like SELECT PersonId, FirstName, LastName From Prople WHERE firstName like #keyword OR lastNAme like #keyword ... other fields
User selects a specific result form the combo-box.
Add button then performs SQL operation adding selected user to your junction table and refresh your junction table.
something like: INSERT INTO people_has_trips (people_personId, trips_tripId) values (#selectedPersonId, #tripId); followed by requery
This is just a theory, you need to try out something and narrow it down to a specific problem. Otherwise your question might be marked as too broad.
The Django docs say you can put a many to many field in either side's model, but not both. Example showing Pizzas and Toppings says it's more "normal" to think of the toppings on a pizza than think of which pizzas a topping is on, so put the field in the pizza model. OK...
However, in my application which tracks permissions and groups, this is not necessarily true. The application has a many-to-many in the permissions table showing which groups have that permission. It also seems like you should be able to look at a group and see what permissions it has. This would theoretically use the same join table.
Couldn't I add a many-to-many-through field in the groups model and specify the existing permission_group join table? Would this cause problems, as it directly violates the recommendation in the ManyToMany documentation?
Thanks...
I can't really see the reason for it. It doesn't matter which end of an electrified wire you touch - the end result is the same. What happens on the database level is exactly the same with no regard to where you add the field in Django. You can still do reverse lookups from either side (check out documentation about related_name setting, it's handy) so you can get both
a) all persons with some specific permissions
b) all permissions that a user has
If you try what you propose, you will end up with two parallel M2M fields if Django allows that - and I imagine it does, but that doesn't make any sense at all. It's like talking to the same person over two phones at the same time - why would you do that? Don't.
And as Patrick mentioned, Django has a comprehensive permissions system so you might just want to check that out and maybe it will suit your needs without any effort on your part at all.
You're making a distinction where there is none. The point of a many-to-many is that it is automatically accessible from either side of the relationship; Django does that for you. The point the docs were making was that the difference is a semantic one only; in the case they mention, toppings belong to pizzas. But even doing it that way, you can still access the pizzas from each topping.
I have an Access database. Let's pretend it's for a pet store.
There's a table for animals.
Animals (animal_id, birth_date, price)
And then specific tables for the different types of animals we sell.
Dogs (animal_id, bark_volume)
Cats (animal_id, collar_size, shedding_rate)
Fish (animal_id)
Fish aren't interesting so they don't have any special fields. The Fish table just exists so you know which records in the Animals table are fish.
Now, I have a general purpose form for adding animals to the pet store. Before you get the form, you first have to say what kind of animal you're adding. Based on that, the form shows/hides fields, changes its recordsource, and binds the fields to the appropriate data columns. The form pulls its data from the queries DogInfo, CatInfo, and FishInfo.
Now, when you enter a dog or a cat, everything is fine. A record is added to both Animals and either Dogs or Cats.
However, when you enter a Fish, all you get is an Animal, no Fish.
What could be causing this? Is it somehow caused by the lack of other columns on the Fish table?
(Let's leave aside the fact that updating tables with a select query makes no sense at all. I didn't expect Access to let me do it at all in the first place, but Access's motto seems to be "Make the wrong thing easy to do and the right thing awkward to do." The database is relatively simple and infrequently used, though, and it's at least 100 times better than it was before I started working on it, so I'm not really too worried about this issue as long as I can make it work.)
"Is it somehow caused by the lack of other columns on the Fish table?"
Yes - when you enter data on child records (Dogs and Cats) Access will automatically fill in the parent ID (animal_id)
Since there is no data entry for the fish record it does not get created. You have to do that in code. Not sure how your form and data source is setup but you would do something like this on one of the form events:
Fish![animal_id] = Animal![animal_id]
Edit
In your FishInfo query you must give the Fish.[animal_id] an alias - you can't have two fields with the same name - call it Fish_animal_id
Then in the Form_BeforeUpdate event put this:
Me.Fish_animal_id = Me.animal_id
Have you thought about configuring relationships on the different tables? Given the design above, I would start by adding an identifying column to the specific-animal tables, and setting it as the primary key. E.g.:
Dogs(DOG_ID, animal_id, bark_volume)
Cats(CAT_ID, animal_id, collar_size, shedding_rate)
etc. In the relationships view, you'd then define a one-to-many (one-to-one?) relationship from Animals.ANIMAL_ID to Dogs.animal_id. You could then hook up the Animals table to a combo/listbox control on your form to select a record from that table. I think if you configure the control correctly, you can even create new records from that control (or you could use a subform).
Do you not have an separate IDs for the Dogs/Cats/Fish tables? Assuming the only difference is the number of columns, I'd be curious if that suddenly fixed it.
Bad design aside, did you set up a relationship between the various tables? And did you set the tables to enforce referential integrity?
I'm writing a CMS for various forms and such, and I find I'm creating a lot of drop-downs. I don't really feel like mucking up my database with tons of random key/string value tables for simple drop-downs with 2-4 options that change very infrequently. What do you do to manage this in a responsible way?
This is language-agnostic, but I'm working in Rails, if anyone has specific advice.
We put everything into a single LookUp table in the database, with a column that mapped to an enum that described which lookup it was for (title, country, etc.).
This enabled us to add the flexibility of an "Other, please specify" option in lookup dropdowns. We made a control that encapsulated this, with a property to turn this behaviour on or off on a case-by-case basis.
If the end user picked "Other, please specify", a textbox would appear for them to enter their own value. This would be added to the lookup table, but flagged as an ad hoc item.
The table contained a flag denoting the status of each lookup value: Active, Inactive, AdHoc. Only Active ones would appear in the dropdown; AdHoc ones were those created via the "Other, please specify" option.
An admin page showed the frequency of usage of the AdHoc values, allowing the administrators of the site to promote common popular values into general usage (i.e. changing their Status flag to Active).
This may well be overkill for your app, but it worked really well for ours: the app was basically almost entirely CRUD operations on very business-specific data. We had dozens of lookups throughout the site that the customer wanted to be able to maintain themselves. This gave them total flexibility with no intervention from us.
You cold have one single dropdown table with an extra column to say what the drop down is for... limit the results with a where clause...
At my current position, we implemented a LookupCode table that contains a CodeGroup,Code, and Meaning column, as well as some others (like active). That way you have a single table that contains all of your lookup values are in a single location and you can do some quick lookups to bind to your dropdown lists.