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
Related
I have a model which has many of another model but this model only needs to have 10 or less id's in it.
Let's say it has, Bathroom, Kitchen, LivingRoom for arguments sake and the new records will probably never need to change.
What is the best way of making a model like this that doesn't use a database table?
This may not be best practices, but to solve the same problem I just specified a collection in my model, like this:
ROOM_TYPES = [ "Bathroom", "Living Room", "Kitchen" ]
Then in the view:
<%= f.select(:room_type, Project::ROOM_TYPES, {:prompt => '...'}) %>
(replace Project with your actual model name.)
Super-straightforward, almost no setup. I can see how it would be difficult to maintain though, since there's no way to add items without accessing the Rails code, but it does get the job done quickly.
Even though the collection of rows never changes, it's still useful to have this as a table in your database in order to leverage ActiveRecord relations. A less contrived example would be a database table that has a list of US states. This is highly unlikely to change, and would likely have only a couple of columns (state name and state abbreviation). However, by storing these in the database and supporting them with ActiveRecord, you preserve the ability to do handy things like searching for all users in a state using conventional rails semantics.
That being said, an alternative would be to simply create a class that you stick in your models directory that does not inherit from ActiveRecord, and then either populate it once from the database when the application loads, or simply populate it by hand.
A similar question was asked yesterday, and one of the answers proposes a mechanism for supporting something similar to what you want to do:
How to create a static class that represents what is in the database?
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 !
So this is probably a fairly easy question to answer but here goes anyway.
I want to have this view, say media_objects/ that shows a list of media objects. Easy enough, right? However, I want the list of media objects to be a collection of things that are subtypes of MediaObject, CDMediaObject, DVDMediaObject, for example. Each of these subtypes needs to be represented with a db table for specific set of metadata that is not entirely common across the subtypes.
My first pass at this was to create a model for each of the subtypes, alter the MediaObject to be smart enough to join into those tables on it's conceptual 'all' behavior. This seems straightforward enough but I end up doing a lot of little things that feel not so rails-O-rific so I wanted to ask for advice here.
I don't have any concrete code for this example yet, obviously, but if you have questions I'll gladly edit this question to provide that information...
thanks!
Creating a model for each sub-type is the way to go, but what you're talking about is multiple-table inheritance. Rails assumes single-table inheritance and provides really easy support for setting it up. Add a type column to your media_objects table, and add all the columns for each of the specific types of MediaObject to the table. Then make each of your models a sub-class of MediaObject:
class MediaObject < ActiveRecord::Base
end
class CDMediaObject < MediaObject
end
Rails will handle pulling the records out and instantiating the correct subclass, so that when you MediaObject.find(:all) the results will contain a mixture of instances of the various subclasses of MediaObject.
Note this doesn't meet your requirement:
Each of these subtypes needs to be represented with a db table for specific set of metadata that is not entirely common across the subtypes.
Rails is all about convention-over-configuration, and it will make your life very easy if you write your application to it's strengths rather than expecting Rails to adapt to your requirements. Yes, STI will waste space leaving some columns unpopulated for every record. Should you care? Probably not; database storage is cheap, and extra columns won't affect lookup performance if your important columns have indexes on them.
That said, you can setup something very close to multiple-table inheritance, but you probably shouldn't.
I know this question is pretty old but just putting down my thoughts, if somebody lands up here.
In case the DB is postgres, I would suggest use STI along hstore column for storing attributes not common across different objects. This will avoid wasting space in DB yet the attributes can be accessed for different operations.
I would say, it depends on your data: For example, if the differences between the specific media objects do not have to be searchable, you could use a single db table with a TEXT column, say "additional_attributes". With rails, you could then serialize arbitrary data into that column.
If you can't go with that, you could have a general table "media_objects" which "has one :dataset". Within the dataset, you could then store the specifics between CDMediaObject, DVDMediaObject, etc.
A completely different approach would be to go with MongoDB (instead of MySQL) which is a document store. Each document can have a completely different form. The entire document tree is also searchable.
I am converting a php project into ruby on rails. The previous project used mysql as the database and the rails project will do the same.
In the project there is a concept of a "step", which a course can have many of. A step has 1 of 5 types. (Quiz, Video, Text..etc) Obviously the type of data required for each step is different.
The way it was modeled before is to store all steps in the same table and have a field that holds a serialized php object of the step. I think this is bad for a couple reasons...You can' really query against serialized data, and it makes adding data or changing the structure of an object very hard.
Would it make more sense to model this data in a database instead of objects?
Generally yes. Rails has two possible ways to model this:
Single Table Inheritance - Several models inheriting from a common ancestor, stored in the same table. Good if your steps are really similar to each other. Here you would call has_many on the parent model.
Polymorphic associations - the association macros have an option :polymorphic which allows you to have different models in one association (each can have it's own table). I'd go for that if your steps have little in common.
I have two models on the Rails app that I am working on, Article and Profile. I want them to have separate sets of categories. Should I create two different category models? article_category and profile_category? There will be lots of redundant code if I do this.
The question is, would both categories function the same way?
If they do, then I would use one model of categories, even though different names would be attributed different.
The trick is to DRY or "Don't Repeat Yourself". So if anything gets written twice, you can absolutely refactor that into a smaller code.
If the models will be identical, then you should use a polymorphic relationship. See my response here: Rails -- How to setup model that can belong to either of 3 different models
If the different category models will need additional logic, then I would use single table inheritance for this. You would have a parent Category class, and ArticleCategory and ProfileCategory would inherit from this. Basically all you will need to do is add a type field to categories and the two additional classes. This will eliminate redundant code and allow you to separate any model specific code into the appropriate class. Let me know if you need additional direction on this.