Rails Association Guidance [closed] - ruby-on-rails

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am new to rails 4. I have gone through lots of tutorials and trying to solve below scenario. But still no success. Can anybody point me in the right direction. How to handle associations for below scenario.
Scenario:
1. Patient can have many surgeries.
2. Surgery has two types (Patient will undergo only one surgery at a time.)
a.) Surgery Type A (if chosen, record 15 column fields values)
b.) Surgery Type B (if chosen, record 25 column fields values)
3. Surgery Type A can be of any one type.
a.) unilateral (if chosen, record 10 column fields for unilateral & skip bilateral)
b.) bilateral (if chosen, record 10 column fields for bilateral & skip unilateral)
4. Surgery Type B can be of any one type.
a.) unilateral (if chosen, record 10 column fields for unilateral & skip bilateral)
b.) bilateral (if chosen, record 10 column fields for bilateral & skip unilateral)
I need some suggestions to handle associations correctly.. This is little confusing, I need to record lot of field values in table based on each surgery type and sub type (unilateral or bilateral).. What is the best way to handle associations for this scenario and later fetch data easily for reporting purpose.
Thanks in Advance

So, the complex part of your situation is that you have one thing (Surgery) that can be of many different types, and the different types have different fields. There are a number of different approaches to this problem, and I don't believe there's wide consensus on the 'best way'.
The first and simplest way (from a data model perspective, at least), is 'just put it all in one thing' - make a Surgery model, give it a surgery_type field to specify which type it is, and give that one record all 45 fields, and then use logic in your views to display only the relevant fields based on the surgery_type field, and to validated the presence of only those fields, and so on.
A more complex variant on this is Single Table Inheritance, in which you have multiple models, but they all live in the same table.
There are some obvious downsides to this approach - 45 fields is a lot, and when most of them are empty for any given record, that feels wasteful (and can have performance impacts). Which is why the various other patterns exist.
And so, as an alternative, there is Multiple Table Inheritance, which Rails implements via polymorphism. In this pattern, a Patient has_many Surgeries, but this is a polymorphic association, meaning that it can refer to other objects of multiple types. In this pattern, you'd have either two or four models representing types of surgery, and associate each one to a patient. TheUnilateralEndocrineSurgery model, for instance, only needs its ten fields. The downsides of polymorphism include making it more difficult to work with groups of Surgery objects, because they are of different types and respond to different methods.
The relative strengths of these approaches are complex and frequently debated, and enumerating them is beyond the scope of a SO answer.

Related

What is the difference between adding a column to a table in rails and joining a table? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I recently discovered that you can add columns to a table in Rails by doing something like:
rails generate migration add_lastname_to_users lastname:string
Previously I used to join tables which was a very complicated to me but, adding a column seems to accomplish the same task.
Why should I choose one over another?
A table represents a single "entity". In this case, it probably makes most sense to store the users.lastname in the same table.
On the other hand, suppose a user can have many phone numbers. In this case, it is better to normalise the database and store this data in a separate table.
In other words, you want to avoid doing something like this:
users.phone_number_1
users.phone_number_2
users.phone_number_3
The key issues with this approach (as explained in more detail by the above link) are:
You'll have lots of redundant columns, for must users. This causes wasted storage space, and decreased performance.
You need to keep adding new columns if a user goes over the limit (e.g. 3 numbers, because there are 3 columns).
Querying the data gets much harder. For example, suppose you want to query "all users who have phone number X" -- you now need to search across multiple columns!
Instead, create a separate phones table - which is joined the the user by a user_id column.
I guess it depends on your application, but generally it's best to "normalize" your database. That is, define individual tables for specific objects. A user table might have the fields user_id, first_name, & last_name. You can then join on the user_id field. This tends to make your lookups faster and your tables smaller.
https://en.wikipedia.org/wiki/Database_normalization
This is not so much related to rails and ActiveRecord but more a question of database design.
Without going into too much detail: In a relational database management system you join tables (or columns in your case?) when some piece of information you need is already available in a different place (usually another table) (hence the "relational" in the name, tables are related to each other and share information). You do not want to repeat data.
This is different in NoSQL databases where joins might not even exist (MongoDB has the notion of embedded documents, you will at some point have to repeat data)
I your case, it is easy (from the point of view of the DB) to just take the already available information (first_name + last_name) and return that. Adding another column with the same information seems 'wasteful'.
You should be able to define a helper method in your model that returns the full name, see create a name helper

How to create an Order Model with a type field that dictates other fields

I'm building a Ruby on Rails App for a business and will be utilizing an ActiveRecord database. My question really has to do with Database Architecture and really the best way I should organize all the different tables and models within my app. So the App I'm building is going to have a database of orders for an ECommerce Business that sells products through 2 different channels, a subscription service where they pick the products and sell it for a fixed monthly fee and a traditional ECommerce channel, where customers pay for their products directly. So essentially while all of these would be classified as the Order model, there are two types of Orders: Subscription Order and Regular Order.
So initially I thought I would classify all this activity in my Orders Table and include a field 'Type' that would indicate whether it is a subscription order or a regular order. My issue is that there are a bunch of fields that I would need that would be specific to each type. For instance, transaction_id, batch_id and sub_id are all fields that would only be present if that order type was a subscription, and conversely would be absent if the order type was regular.
My question is, would it be in my best interest to just create two separate tables, one for subscription orders and one for regular orders? Or is there a way that fields could only appear conditional on what the Type field is? I would hate to see so many Nil values, for instance, if the order type was a regular order.
Sorry this question isn't as technical as it is just pertaining to best practice and organization.
Thanks,
Sunny
What you've described is a pattern called Single Table Inheritance — aka, having one table store data for different types of objects with different behavior.
Generally, people will tell you not to do it, since it leads to a lot of empty fields in your database which will hurt performance long term. It also just looks gross.
You should probably instead store the data in separate tables. If you want to get fancy, you can try to implement Class Table Inheritance, in which there are actually separate but connected table for each of the child classes. This isn't supported natively by ActiveRecord. This gem and this gem might be able to help you, but I've never used either, so I can't give you a firm recommendation.
I would keep all of my orders in one table. You could create a second table for "subscription order information" that would only contain the columns transaction_id, batch_id and sub_id as well as a primary key to link it back to the main orders table. You would still want to include an order type column in the main database though to make it a little easier when debugging.
Assuming you're using Postgres, I might lean towards an Hstore for that.
Some reading:
http://www.devmynd.com/blog/2013-3-single-table-inheritance-hstore-lovely-combination
https://github.com/devmynd/hstore_accessor
Make an integer column called order_type.
In the model do:
SUBSCRIPTION = 0
ONLINE = 1
...
It'll query better than strings and whenever you want to call one you do Order:SUBSCRIPTION.
Make two+ other tables with a foreign key equal to whatever the ID of the corresponding row in orders.
Now you can keep all shared data in the orders table, for easy querying, and all unique data in the other tables so you don't have bloated models.

Properly gathering metadata/object data using Core Data/sqlite [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I'm new to objective c and core data. I am making an iOS app kind of like a flash card app. I have a core data set up with an EnglishWord entity in a many to one relationship with ForeignWord entities (different languages).
For each ForeignWord entity I want to keep track of certain metadata: how many times I have viewed the word, the dates I viewed it, a score I give it, etc. Ideally would be if I could have an array/dictionary as an attribute within the ForeignWord managed object itself. This is not possible.
The only option I can think of is to create a new entity called 'Score', with each ForeignWord entity 'owning' many Score managed objects (one to many), a new 'Score' managed object being created every time I view the foreignWord.
However, this sounds very messy. If I have 1000 words then I would have 1000 different tables in the sqlite database, one for each card.. does that slow things down? is it bad to have 1000 different tables?
is this really the way to do it? Is there a more elegant solution? Thanks!
You might consider adding a table called something like "Viewing" that has a relationship (to 1) both to EnglishWord and ForeignWord. You could then track the metadata that interest you in this table and aggregate the data in this table to determine how many times that you viewed a particular word, whether or not you identified it correctly, etc.
I would create one new table called ViewEntry or something and link relationships to both of your word tables. That way when a word is viewed you can store whatever meta information you want, as well as having an active link to the English and foreign version. Something like this:
This way you can create a new ViewEntry set its foreignVersion and word attributes to the English and foreign words, set the date, score, and total answer time (along with anything else you want). You could then do some really nice querying to pull up useful information.
give me all of the foreign versions of the English word "school" where the score was less than 50%.
I want all of the times the user attempted the Russian translation of "house" and the associated scores.
what English words have the worst/best score?
what is the most/least view English (or foreign) word?
All of this would be relatively easy since the English word could access all of the times it was viewed and any foreign version of any English version could do the same. You could also access the score and view date and pull up all of the English/foreign versions from that data.
You also would not need to create 1000 tables :)

How to model Players for different Sports in RoR?

I am building an app that have the following requirements:
-> A User can be a player of different teams.
-> A Team can be of a sport type.
My question is:
-> Since for each sport type I want to store different information of a Player, what would be the best way to model that?
I have thought on having several models (and tables) for each kind of Sport, for example:
Basketball_Players, Football_Players and so on, but I am not sure if that would be a good approach. How do you usually do this on RoR?
I'd say you have two options, and I don't know that it's really possible to say which is the "most correct" way to do it without knowing the details of the requirements of your application.
What's a given is that you'll have a sport table and a player table. I can say that for sure. The question is how you connect the two.
Option 1: a single join table
You could have a table called player_sport (or whatever) with a player_id column, a sport_id column, and a serialized_player_data column or something like that, where you'd keep serialized player data (JSON, perhaps) depending on the sport. Pros: simple schema. Cons: not properly normalized, and therefore subject to inconsistencies.
Option 2: a separate join table for each sport
This is what you alluded to in your question, where you have a basketball_player, football_player, etc. Here you'd also have a player_id column but probably not a sport_id column because that would be redundant now that you're specifying the sport right in the table name. The need to have a serialized_player_data column would go away, since you'd now be free to store the needed attributes directly in columns, e.g. wrestling_player.weight_class_id or whatever. Pros: proper normalization. Cons: more complex schema, and therefore more work in your application code.
There's actually a third option as well:
Option 3: a combination of 1 and 2
Here you might do everything you would do in Option 2, except you'd move the common player attributes to the player_sport table and save basketball_player, etc. for the sport-specific attributes. So weight_class_id would stay in wrestling_player but player_sport would have height, weight, and other columns that are relevant to all sports.
If you're looking for a recommendation, I would probably do Option 2, or, if it looks like there's enough overlap for it to make sense, Option 3.

Core data database design issues

I want to create a core data model to store user input questions and then entries for those questions.
The questions will be 1 of 3 types. (1-10, Yes No or a number of specific units). So users will go into the app, click "add question" and will be shown a form where they will input the question title choose the question type (Yes/No, Scale 1-10 or Specific Units) - and if they choose specific units they have to put in those units eg: centimetres, millimetres, litres etc...
There will be multiple entries to these questions mapped over a period of time. IE: Users may put in the questions "How tall is your tomato plant? - specific units - CMs" and "How red are your tomatos? - scale 1-10" and will go back into the app time and again to map out the progress over time.
My question is about database design for this. How would I set this up in my core data?
At the moment I have this:
Now, I'm stuck! I don't quite know how to account for the fact that questions have different types, and therefore the entries will be different.
Plus I need to account for questions where units may be required. These are the questions that will just be a number.
So I'm thinking I probably need different question entites. Something like having a Questions entity and the specific questions as sub-entites - but I'm not sure how to do this, and not sure how to then record the entries made to those questions!
Thank you for looking, and for helping if you can. :)
There's no correct way to design it, and there are indeed many different ways to design a solution.
As #dasdom suggested, you could remove the value from the Entry entity description, and make Entry abstract. Create three subclasses of Entry (BooleanAnswer, RankedAnswer, and ValueAnswer for example). The ValueAnswer would have a decimalValue and units, the others similar related values.
Also, FYI on naming conventions:
Entities: upper case, singular: Question and Entry (though i'd name it Answer)
Attributes/Relationships: lower case: questionText, type, entries, value, questions ('forQuestion' and 'forEntity' are redundant, being the relationship is defined on each of those)
Another option is to have Entity have units, boolValue, rankValue, and decimalValue but only use the attribute that's relevant. That's not an elegant solution, imho.

Resources