Is there a best practice naming convention for Rails migrations, particularly when editing a model?
e.g. if I'm adding a column bar to the Foo model, should I name it edit_foo or add_bar_to_foo
I'm assuming if I'm editing mutliple models then I should create multiple migrations, but what if I'm making multiple modifications to a single model, do I name it add_bar_remove_x_edit_y_to_foo?
I agree with the previous poster. The naming should focus on readability. But also keep in mind that you can't (nor should) have two migrations with the same name.
So, general names like edit_foo_model is generally not a good idea (since, what happens when you want to add more columns to that model), then it would be better to group the columns into what the purpose is, like update_foo_for_bar_support. You can usually skip adding model since, well, everyone knows that migrations do handle models, so there is no need to mention that in the name (that is, update_foo instead of update_foo_model).
Also, what I usually do is to keep different changes separated. So, if there are multiple different changes in a model, I'd separate them into different migration files, one for adding columns and one for removing columns for instance.
I would split up multiple schema changes into multiple migrations so that you can easily name the single migrations!
The point is readability- to find out fast what the migration is responsible for.. if you write too much "data" in the name, it makes it harder to scan and you shoot yourself in the foot.
So.. if it's 1-2 changes, write it in the name, if there are too many changes, write update_foo_model (or edit_foo_model)
Related
I get flat files once a week that have a few 100k rows. I would like to turn them into a relational model system in Rails since there are about five columns that are fairly static and would make sense for a different model that would then be linked back into the main table as a foreign key.
Is there was a quick way to check if an entry already exists, and if so, look it up and put the foreign key in the main model, and if not, create a new entry in the second model and then reference it in the main model.
I can turn the above paragraph into code but wanted to know if there is a simple 'few lines' Ruby or Rails implementation.
Just for the sake of merging my comment and #anton-z 's.
You can use activerecord-import for doing bulk operations, and ActiveRecord's find_or_create_by to do the checking.
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?
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 have a general question about whether people think you should use a database table or constants hashes/arrays for categories. I'm torn on which way to go. Thoughts?
Well, if you are 100% sure you won't ever change the categories, you could go for a custom model with the Object superclass (no DB-table and no ActiveRecord).
If you ever would change a category or add any you want a database. This is because your models won't get reloaded after a change in production mode.
I still recommend a database anyway because of at least the following:
See MattC's comment.
You can use ActiveRecord relationships (has_many and belongs_to). This is hard to do without ActiveRecord.
The performance decrese is not significant. It might slow down 0.2ms at most.
Having them stored in the database (and used as a model) make it more flexible for the future. Adding/Removing new categories could be done without a redeploy of the app, whereas having them as hard-coded constant values would.
But with that said, it all depends on your specific needs. If you know for a fact that the categories will never change, constants might be better since that would mean less database hits.
The RoR tutorials posit one model per table for the ORM to work.
My DB schema has some 70 tables divided conceptually into 5 groups of functionality
(eg, any given table lives in one and only one functional group, and relations between tables of different groups are minimised.)
So: should I design a model per conceptual group, or should I simply have 70 Rails models and leave the grouping 'conceptual'?
Thanks!
Most likely, you should have 70 models. You could namespace the models to have 5 namespaces, one for each group, but that can be more trouble than it's worth. More likely, you have some common functionality throughout each group. In that case, I'd make a module for each group containing its behavior, and include that in each relevant model. Even if there's no shared functionality, doing this can let you quickly query a model for its conceptual group.
I cover this in one of my large apps by just making sure that the tables/models are conceptually grouped by name (with almost 1:1 table-model relationship). Example:
events
event_types
event_groups
event_attendees
etc...
That way when I'm using TextMate or whatever, the model files are nicely grouped together by the alpha sort. I have 80 models in this app, and it works well enough to keep things organised.
You should definitely use one model per table in order to take advantage of all the ActiveRecord magic.
But you could also group your models together into namespaces using modules and sub-directories, in order to avoid having to manage 70 files in your models directory.
For example, you could have:
app/models/admin/user.rb
app/models/admin/group.rb
for models Admin::User and Admin::Group, and
app/models/publishing/article.rb
app/models/publishing/comment.rb
for Publishing::Article and Publishing::Comment
And so forth...
Without knowing more details about the nature of the seventy tables and their conceptual relations it isn't really possible to give a good answer. Are these legacy tables or have you designed this from scratch?
Are the tables related by some kind of inheritance pattern or could they be? Rails can do a limited form of inheritance. Look up Single Table Inheritance (STI).
Personally, I would put a lot of effort into avoiding working with seventy tables simply because that is an awful lot of work - seventy Models & Controllers and their 4+ views, helpers, layouts, and tests not to mention the memory load issue of keeping the design in ind. Unless of course I was getting paid by the hour and well enough to compensate for the repetition.
Before jumping in a making 70 models, please consider this question to help you decide:
Would each of your tables be considered an "object" for example a "cars" table or are some of the tables holding only relationship information, all foreign key columns for example?
In Rails only the "object" tables become models! (With some exception for specific types of associations) So it is very likely that if you have only 5 groups of functionality, you might not have 70 models. Also, if the groups of functionality you mentioned are vastly different, they may even be best suited in their own app.
There may be a small number of cases where you can use the Rails standard single-table-inheritance model. Perhaps all of the classes in one particular functional grouping have the same fields (or nearly all the same). In that case, take advantage of the DRYness STI offers. When it doesn't make sense, though, use class-per-table.
In the class-per-table version, you can't easily pull common functionality into a base class. Instead, pull it into a module. A hierarchy like the following might prove useful:
app/models/admin/base.rb - module Admin::Base, included by all other Admin::xxx
app/models/admin/user.rb - class Admin::User, includes Admin::Base
app/models/admin/group.rb - class Admin::Group, includes Admin::Base
It's already mentioned, it's hard to give decent advice without knowing your database schema etc, however, I would lean towards creating the 70+ models, (one for each of your tables.)
You may be able to get away with ditching some model, but for the cost (negliable) you may as well have them there.
You don't need to create a controller + views for each model (as answerd by srboisvert). You only need a controller for each resource (which I would expect to be a lot less than 70 - probably only 10 or 15 or so judging by your description).