Rails is known for its convention over configuration design paradigm. For example, database table and column names are automatically derived and generated from the model classes. This is very convenient, but when you want to build a new application upon an existing (“legacy”) database schema you have to explore the configuration side of this paradigm.
The most basic operation for dealing with a legacy schema in Rails is to explicitly set the table_names and the primary_keys of model classes:
class User < ActiveRecord::Base self.table_name = 'benutzer' self.primary_key = 'benutzer_nr' # ... end
Additionally you might want to define aliases for your column names, which are mapped by ActiveRecord to attributes:
class Article < ActiveRecord::Base # ... alias_attribute :author_id, :autor_nr alias_attribute :title, :titel alias_attribute :date, :datum end
This automatically generates getter, setter and query methods for the new alias names. For associations like belongs_to, has_one, has_many you can explicitly specify the foreign_key:
class Article < ActiveRecord::Base # ... belongs_to :author, class_name: 'User', foreign_key: :autor_nr end
Here you have to repeat the original name. You can’t use the previously defined alias attribute name. Another place where you have to live with the legacy names are SQL queries:
q = "%#{query.downcase}%" Article.where('lower(titel) LIKE ?', q).order('datum')
While the usual attribute based finders such as find_by_* are aware of ActiveRecord aliases, Arel queries aren’t:
articles = Article.arel_table Article.where(articles[:titel].matches("%#{query}%"))
And lastly, the YML files with test fixture data must be named after the database table name, not after the model name. So for the example above the fixture file name would be benutzer.yml, not user.yml.
Conclusion
If you step outside the well-trodden path of convention be prepared for some inconveniences.
Next part: Primary key schema definition and value generation
Great post! I wish I had read this a few months ago. Still I learned a lot. I’m working with a ridiculously complex SQL SERVER database that doesn’t comport to Rails conventions. To configure the associations of an existing database, all I have to do is add ‘belongs_to’ and/or ‘has_many’ in the appropriate models? That is it?