Parent Model that can only have one child in Rails? - ruby-on-rails

Sorry the title is pretty unclear - I'm just not quiet sure how to phrase the question without explaining it.
I would like to record workouts with my app. I would like a Workout Table (what I'm calling the parent) that has basic information like date and sub_workout_type_id
A workout record can have either a Cardiovascular workout (One Model) or a Strength Workout (Another Model).
My thought on have 3 tables instead of just the 2 Cario Workout model and strength workout model is that I would be able to pull a feed of any type of workout, by pulling the Workout Records and then dig deeper as needed.
Perhaps there is a more ruby-ish way to do this? Because right now I don't know of a way to say has_one_model_or_the_other. Thanks!

I see two options, either you use STI (single table inheritance) : in that case you would have a single table that would be able to contain both a cardiovascular model or a strength workout, and a type. This would only work if the two models share some common characteristics.
Another solution is to write something like
has_one :cardiovascular
has_one :strength
and then use validations to enforce that only one of them is set.
Hope this helps.

As mentioned by #nathanvda, STI could be a good choice.
If you're looking to store class specific data with your models, maybe check out Modeling inheritance with Ruby/Rails ORMs to see if that answer gives you any ideas on how to model this relationship.
Note, the example there uses has_many's but a lot of the ideas are similar.

Related

Accessing relationship tables data in rails (using has_many :through)

It is my first question, but I have yet to find an answer, so I hope it doesn't violate any rule.
I have a problem with a seemingly simple rails issue. I have taken the time to read about relationship models in rails (has_many :through) and came upon this example:
Exemplary model relations
In my model, I have Anthology (phyisicians), Poem(patients), and an anthology_poem relationship model (appointments). In may relationship table, I have a column, order, that indicates the position of a specific poem in a specific anthology.
The question is - How do I address said "order" column? How do I update it/read it? I imagine something like:
book.poems.first.order
which obviously doesn't work.
I'd like to be able to do it without too much hacking, because I fell in love with how simply rails handled the rest of the stuff.
Thanks in advance!
If you want to access your relationship model attribute you should call it on that model:
Appointment.where(physician: physician).pluck(:order)

Rails: storing arrays in DB vs. setting up relationship

Setting: There are two models with the following attributes.
Person: name, age, work_experience, available_dates
WorkExperience: job_title, starting_date, ending_date
Then, I can do the following
Person
has_many work_experiences
WorkExperience
belongs_to Person
Q1: Should available_dates be an attribute (array of dates) or a child (e.g. Person has_many available_dates)?
Q2: Can Person have work_experiences field that's just an array of objects instead of an individual table in DB?
TL;DR: As in all design questions, I think the answer is "it depends."
On Q1:
I've done both ways before. If I were making this decision, I would consider the following:
Do I see myself adding more information to available_dates in a very near future? For example, it could be location, timezone, commute distance, and so on that would make this data into "availability" in general. In that
case, I'd rather create separate objects with association.
Do I see myself reusing these dates in some other place in my code? Then I'd rather make them into separate objects and persist.
On Q2:
I don't think it'd be good for your sanity. DB has simple datatypes and are not designed to retain object models.
On Q1 I would go with an association instead of an array as it provides more flexibility. So a child, as you call it is what I would do.
On Q2 I would also go with a separate WorkExperience Model as it also provides more flexibility and room for growth. Also the array might get a bit messy as a Person starts gathering work experiences and querying for information might get more complicated than it needs to be with an array. With a separate model Active Record will give you a lot of tools you can use to dig into a person's work experiences.
Hope that helps.

Model which belongs_to can be several models?

This is the situation that I have now:
Adword has_many pages
page belongs_to Adword
Right now I want to place another Ad provider, and that will also generate pages. So, ideally I want somehow to say something like (this is where I am lost):
AdProvider has_many pages
page belongs_to AdProvider
Where AdProvider could be Adwords, X, Y - What is the correct way to approach this kind of situations in Rails? RIght now I just have a adword_id attribute in Page, but there will be pages which are not associated to Adword but to another Ad provider.
Use Polymorphic association.
From the doc:
With polymorphic associations, a model can belong to more than one
other model, on a single association. For example, you might have a
picture model that belongs to either an employee model or a product
model.
I use Single Table Inheritance (STI) when I want to accomplish this.
"STI should be considered when dealing with model classes that share much of the same functionality and data fields, but you as the developer may want more granular control over extending or adding to each class individually. Rather than duplicate the code over and over for multiple tables (and not being DRY) or forego the flexibility of adding idiosyncratic functionality or methods, STI permits you to use keep your data in a single table while writing specialized functionality."
You can read more about it here.
As suggested by #emaillenin you could use polimorphic associations to deal with this.
You can see more about that here
But you should have in mind that classes sharing this type of association should follow a pattern, or else you could end up with tons of if statements in order to avoid their differences.
However by your description of the relation between AdProvider and Adword, I'm guessing that you are using a STI (Single Table Inheritance) system, so those similarities are already implied.
This article will help you to choose between Polymorphism and STI approach: STI
Below you can find a quote from the article:
"
3. Do the objects have similar data but different behavior?
How many database columns are shared by every model? If there are going to be many model-specific columns, you should consider Polymorphic Associations. On the other hand, if a Car, Truck, and Motorcycle all have the same attributes, eg:
color
engine_size
price
but different method implementations, eg:
drivetrain_weight # sums different components
value_after_depreciation(years) # uses different depreciation rates
drivers_license_certifications # references different certifications
then Single Table Inheritance is probably a good design choice. If there are only minor differences in a few methods, you may want to “cheat” and go with a Single Class."

Rails: associations in app with one model

I've read so many Rails books/tutorials, but when it comes time to actually make the app, I keep tripping over myself, so I'm trying this little exercise to help me get it better.
I have an app with 3 classes (Link, Url, Visit) that have associations defined between them, such as has_one, belongs_to etc. This allows me to call methods like Link.url
If I were to convert this into an app with a single model, is it possible to create the convenience methods (such as Link.url) even though there are no relationships between models, because there is only one model.
This might not be the 'Rails way' but if you answer this question it'll help me get it more.
I guess another way to ask this is, do the Rails associations only exist because the tab
Thanks
Models exist to represent tables in a database. If you have 3 different conceptual objects, then you need 3 different models. Keeping those objects separate and in different tables/models is essential to good programming in any language. The relations are there to help you understand the correlation of each object to the others.
If you think all of data from each of the models can be represented in one table sensibly, then combine them in to one model with a name that encompasses all of the data. If you choose this option, you'll use columns for that one table which represent each of the pieces of data you need. Those column names come free in the model when you create the migration. A table with a column named "url" on a model named "Hit" could be used like this:
Hit.first.url

Attribute with multiple values in rails: booleans, string and serialize or hbtm?

Say you have a Book model that can belong to multiple categories. Categories are predefined, but we might let the user add his own even though most of the time default ones are enough.
What is the best way to deal with that according to you ?
a) a many to many relationship to a Category model ? But isn't that overkill given the fact default categories are enough most of the time ?
b) booleans for each default category and an extra string for user entered categories
C) just a string and the use of serialize ? But then it might be a bit more tricky to use checkbox inputs for the default choices
d) any other suggestion of yours...
Thanks for your time!
Thanks
You'll probably want to use HABTM. It's not overkill if you're ever going to want to collect any sort of information about the various categories; date created, for example. You'll also gain the ability to easily fetch all books for a given category without having to worry about scopes inside the book model.
Also, down the road you might want to be able to add other objects to categories. There's not much overhead, and it's quite simple to set up, so worth going for, IMHO.
For help on implementing HABTM with checkboxes, check out the HABTM Checkboxes railscast. For a discussion of the differences between HABTM and has_many :through, I really recommend the Two Many-to-Many railscasts.

Resources