Model design -- What's the optimal way to do this? - ruby-on-rails

I have this app I am writing in Rails 3.1, I am wondering the best way to model this.
Would it be best if I created a model called "Movie" with a "title" and then create a new model for each "movie asset" such as "poster, trailer, screener" etc and relate it to the "Movie" by associations? Or would it be best if I just created this as one and do-away with the of associations of each asset to "Movie"?
My assumption is to just make it as one as it will remove all the overhead of the FK's and joins to get retrieve the data related to the movie but I am looking for opinions/suggestions. Thanks

There can be three types of attributes(columns) for movies.
Which have exactly one value, and are present in every movie e.g. title, year, official trailer etc.
Keep them in the movie table.
Which have exactly one value, but are present in few of the movies e.g. total Academy Awards.
Keep them in separate table, and use has_one+belongs_to association.
Which have multiple values e.g. trailers
Keep them in separate table, and use has_many+belongs_to association.
More suggestions:
For many key-value attributes, it is easier to use one json/yaml column using serialize instead of creating one column for each key.
Do not store images in DB, keep them in file-system or cloud storage.

You can create your models in the order you want since you have to fill in both models to create a unique association (such as belongs_to and has_many) so I think it doesn't really matter !

Related

Rails model with multipe values for a field

I have a model Movie. That can have multiple Showtimes. Each Showtime is a pair of start and end times. Movies get saved in the database.
So although a Movie might have_many Showtimes, does that really need to be a model, or just a class, or some kind of custom tuple-like type?
I have seen where you can have a field with an array of values, but this would not be basic values as each value is a pair of times.
What is the best way to achieve this?
Showtimes should be a model, yes. Here are a few reasons:
Most relational databases don't natively support a tuple or array type.
What if you want to query movies occurring at a particular time? This would be difficult to do with a custom field, but would be relatively trivial with a separate table.
Most importantly, it enables better flexibility and extensibility through decreased coupling. For instance, does a showtime always exist exclusively to a movie? What if you want to extend your schema to add theatres where each theatre has many showtimes?

Rails Order by Contained Objects 2 Levels Deep?

How can I include ordering in an 'order' ActiveRelation call that's more than one level deep?
That is, I understand the answer when it's only one level deep (asked and answered at Rails order by associated data). However, I have a case where the data on which I want to sort is two levels deep.
Specifically, in my schema a SongbookEntry contains a Recording, which contains an Artist and a Song. I want to be able to sort SongbookEntry lists by song title.
I can go one level deep and sort Recordings by song title:
#recordings = Recording.includes(:song).order('songs.title')
...but don't know how to go two levels deep. In addition, it would be great if I could sort on the recording (that is, the song title and the artist name) -- is this possible without descending into SQL?
Thanks for any help,
Keith
If you model the association between SongbookEntry and Song as such:
class SongbookEntry < ActiveRecord::Base
# ...
has_one :song, through: :recording
end
you will be able to access #songbookentry.song and SongbookEntry.joins(:song) using your existing schema.
Edit:
Applying the same idea for Artist, a possible query would be:
SongbookEntry.joins(:song,:artist).order('songs.title','artists.name')
Note that this may not be the most efficient operation (multiple joins involved) even though it looks Rails-ish, so later on you may want to denormalize the tables as Ryan suggested, or find another way to model the data.
I would advise storing the artist name (and possibly the song title too) on the recording itself, so you don't have to "descend into SQL".
Try this
SongbookEntry.includes(:recording=>[:artist,:song]).order('songs.title, artists.name')
You can use joins in place of includes if you don't want to use associated tables fields in views

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

Structure my database

I'm creating an app that will import products from several XML feeds. In the XML there is a category specified, like T-Shirt for instance. The problem is that different resellers specify the categories differently. For instance, what one reseller calls "T-Shirts" another may call "T-Shirt", a third "short sleeved shirts" and so on.
I want to somehow map these categories to the categories I have myself. So I need some tips on how I should structure my database.
The idea I have is to create a "raw_categories" table which contains the name of the resellers category and a "category_id" which has a belongs_to relationship to my own "categories" table. Then when I import I simply try to find a raw_category which has a matching name and if there is one, pick it, otherwise add a new one. This new one I can then manually relate to one of my own categories.
Do you understand how I mean, and is it a good approach? Is there a better/more efficient way?
If this is a good idea. How do I do it in Rails? Should I use something like this (I think I've seen something like this in the API doc):
# products model
has_one :category, :through => :raw_categories
I estimate that there will be about 40k to 100k products in the database.
Regards
Linus
Yes, that is the typical design. I would usually call your base table category, and call this alias table categoryAlias. I'm picky about verbage, but raw_categories has nothing to do with "rawness", it's just the categories you want to use.
The other thing I'd suggest is that when you create a category you also create a categoryAlias.
Considering the amount of data you will have in these categories, one practical suggestion I can offer is that when you create a category, also create a categoryAlias row for it, with the same name.
This will make your import code easier as you will only need to query categoryAlias to determine if a category already exists, or there is an alias for it.

How do I handle a "fixed content" model in Rails?

In some of my forms I have to provide a dropdown where users can select some districts. The thing is, there will always be a fixed number of districts ( 31 in this case ). Should I create a model named District having only a string field,populate it with the data and be done with it?
It's content will not modify over time. Is there another way?
You should take a look at jnunemakers scam-gem. It mimics the AR for you and lets you define the models in your Rails app without a backing database/table.
I use this whenever I want something to do psuedo belongs to/has many relationships, but do not want to back a model with a database as the data does not change often, if ever.
Making a table-backed model is the simplest way. Otherwise you're going to end up implementing half of an AR model anyway, because you'll want to use collection_select at some point.
I guess it depends on how you want to store the districts and whether you want to do any querying etc.
For example, you could just have the list of districts as a constant, then store them as a string in your models (not very elegant), or as you say you could create a model and use active record associations - this would allow you to easily query on districts etc.

Resources