Models and Database associations - ruby-on-rails

I try to do for me a kind of application for a Writer. Possibility to add chapters, scenes, characters and anecdotes.
My models : chapter, scene, character, anecdote
Chapter has a number, a title, and has scenes and anecdotes
Anedote has a subject and one or several themes
Scene has a text, one or several characters, a place, a period
Character can appear in on or several scenes
I did the tutorial on Ruby on Rails by Michael Hartl, but I have some difficulties now to implement my model.
Do you know some tutorials on database associations like I want to do, or explanations ?
I hope you understand, and sorry for my bad english
Thanks

You can't do Scene has_many: characters and Charaker has_many: scenes. `has_many expects to find a foreign key on associated model and such a key can only point to one parent.
What you need is either:
has_and_belongs_to_many association
has_many :through association
Those associations are rather a vast subject to describe in a single question. Please have some reading: http://guides.rubyonrails.org/association_basics.html. I strongly recommend reading at least first three chapters and scan the forth before starting designing your models. It is really a pain to realize you have designed extra elaborate database structure which could have been achieved with AR feature you didn't know at the time.

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)

Semantic vs. Functional Interpretation of has_many/belongs_to in Rails

I'm a Rails beginner and I'm having trouble wrapping my head around how I should design my database schema. Here's a quick breakdown of some of my models:
Submission: Contains multiple Guesses.
Guess: Contains one Song.
Song: Contains song-related info, has a many-to-many relationship with Shows.
Show: Contains show-related info, including Songs that were played.
The relationship between the last two models are managed through the Song_Show relationship model. Things get a little trickier when I try and relate the Guess model to the Song model. Semantically, I think of it like each Guess has_one Song and each Song belongs_to many Guesses; however, there is no belongs_to_many relation.
In the classic example that uses the Customer and Order models, the semantic relationship matches the Rails relationship - each Order belongs_to a Customer and a Customer has_many Orders; however, trying to apply that logic to my example doesn't quite work if the proper way to do things is a Song has_many Guesses and each Guess belongs_to a Song. Is the way I'm thinking about these relationships semantically getting in my way of understanding Rails associations?
On a related topic, creating all of these relationships seems to be a hassle, at least for the initial version of this application where both the Guess and Song models seem rather useless, as they each essentially store a single song_name property. One of the critical features of the application is to compare a Submission to a Song and see if any of the song_names from the Submission match those in the Show. Is it a bad idea to simply serialize a list of song_names in both the Submission and Show instances and compare those directly, rather than complicating things with the Song and Guess models?
Don't get too bogged down by the meaning of has_many and belongs_to. At some point in your Rails career, you'll start to see them for what they really mean: which model keeps track of the relationship.
In a has_many relationship, it's the other model that keeps track of the relationship. If a Song has_many Guesses, then the Guess would have the song_id.
In a belongs_to relationship, the class that you're in is the thing that keeps the id. If a Guess belongs_to a Song, then the Guess has the song_id.
In a has_many...through model, it's the joining class that keeps track of everything.
As for your last question, I think you have to figure out how you're going to compare Guesses to Songs. Seems like a Guess might not merit it's own class—could be serialized—but a Song could probably merit its own class. Doing it like this might make it easier to search too:
Song.where(song_name: #submission.guesses) # where guesses is an array.

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

Resources that best explain associations used in Rails

I am coming from a Java background where we write our own queries or stored procedures and deal directly with low level database stuff.
I am going though AWDR 3rd edition book and can not grasp the joins concept.
Can someone share a resource they used when first coming to Rails?
Let's say I want a Customer table and Order table. a customer can place many orders. So will my Customer Model class contain :has_many order_id
If I do the above, will it make foreign/primary keys in the actual database?
Now let's say I want to find all customers which order with id 5.
How will I do that?
Is it good to just go with find_by_sql?
Take a look at http://guides.rubyonrails.org/association_basics.html
It has a pretty good explanation of Rails Associations, how they work, why you need them, and how to use them.
I think I can give you a quick rundown.
You're used to dealing with SQL directly, and the nice thing is that Rails promotes good database design. If you have a books table and a chapters table, then a book will have many chapters, correct? So just as in other database setups, the chapter table should have a foreign key telling what book it belongs to.
Assuming you have this foreign key in the chapters table, you can setup your Book model like so:
# app/models/book.rb
class Book < ActiveRecord::Base
has_many :chapters
end
You're telling Rails that a book literally has many chapters. So if you have a book object, you can say book.chapters and that will return an array of the chapter objects that belong to this book. Rails will know to look at the chapters table for the book_id foreign key, no custom SQL required.
Conversely, assuming this same database setup, you can define your chapter model to be associated with books, like this:
# app/models/chapter.rb
class Chapter < ActiveRecord::Base
belongs_to :book
end
Notice :book here is singular, just an idiom that helps readability, since a chapter can only belong to a single book. Now if you have a chapter object and say chapter.book, it will return the book object that the chapter belongs to.
Just as in other database applications, the foreign key is always on the "belonged to" table.
I hope this helps!
As suggested the Ruby On Rails Guides is a good place to start, along with the RailsCast site
The key point is that the foreign keys, although implied by the use of the ActiveRecord abstractions such as :belongs_to, :has_many, :has_and_belongs_to_many etc, are not created for you. In the Rails Guides notes on Associations you'll notice comments like:
"In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations."
This note is often referenced in the details of the individual associations under the :foreign_key option.
I guess it's often not obvious and from my experience (esp. coming from a Java/C++ background) I found that I had to print out and read the set of guides a couple of times to really appreciate the elegance, simplicity as well as the wealth of information contained within them.
On a side note - it's great not to have to deal with all the low level plumbing as per the Java experience.

Resources