How to convert ActiveRecord table name to model class name
I did it!
This returns a hash in the form of "table_name" => "model_class_name".
Hash[ObjectSpace.enum_for(:each_object, class << ActiveRecord::Base;
self; end).to_a.reject{|c| c == ActiveRecord::Base}.collect{
|c| [c.table_name, c.name]}]
EDIT: Better version (works with Rails 3 only):
Hash[ActiveRecord::Base.send(:descendants).collect{|c| [c.table_name, c.name]}]
Please note not all your model classes are always loaded. To load them all before creating such a hash do this:
Dir.foreach("#{RAILS_ROOT}/app/models") { |f| require f if f =~ /.*\.rb/ }
Nice.
How do I explicitly specify a Model's table-name mapping in Rails?
Rails >= 3.2 (including Rails 4+ and 5+):
class Countries < ActiveRecord::Base
self.table_name = "cc"
end
Rails <= 3.1:
class Countries < ActiveRecord::Base
self.set_table_name "cc"
...
end
Rails 3 joins table and model naming conventions
Your question is not completely clear to me.
By Rails conventions, model names are singular and written in camel case, for instance InstructionProduct
. Each model matches a table in the database with the same words, down-cased, separated by '_' and in plural. instruction_products
for the provided example.
Look at the following example using has_many:
class User < ActiveRecord::Base
has_many :contacts
end
class Contact < ActiveRecord::Base
belong_to :name
end
user = User.find(1)
user.contacts # returns an array of all the associated objects
When doing user.contacts
, contacts is not the table name. It's the collection method, a placeholder for the symbol passed in the has_many method (please follow the has_many link and read what documentation says about has_many). Another name could be used, though:
class User < ActiveRecord::Base
has_many :personal_contacts, class_name: 'Contact' #, foreign_key: :contact_id
end
user = User.find(1)
user.personal_contacts
The class_name and foreign_key are required because rails conventions are not being followed. When using has_many :personal_contacts
rails expects that personal_contacts
will return an array of PersonalContact
.
In Ruby you must start a class name with a capital word, so it is not possible to create a class named instruction_product
. If you want to provide a name that does not follow the Rails convention, which I don't recommend, you will need to inform rails about the new table name:
Class AdminUser
self.table_name = "users"
end
Update 1:
As you already know, the convention states that the model should be declared as singular (class InstructionProduct
instead class InstructionsProducts
. However its just a convention. When a class inherits from ActiveRecord::Base, and a sql query is generated, ActiveRecord lowercases the class name, separates the words by _, converts to a plural name and uses it as the table name (mainly rails uses InstructionsProducts.model_name.plural
which returns instructions_products
).
You are assuming that singular actually does a name translation to singular, even if it's written in plural, but it doesn't. It assumes that you are using the convention, and mainly returns the class name underscored.
Looking at the rails source code (ActiveModel::Name), ActiveSupport::Inflector.underscore seems to be used (I just did a very superficial investigation, I have to admit). You can see how underscore works at documentation.
Class name to table name ambiguity
use self.table_name
to assign custom table name
class PlanetOsmLine < ActiveRecord::Base
self.table_name = "planet_osm_line"
end
Rename single table inheritance rails model class name without changing existing data
This is how you could do it:
- Create
ULD < Component
component/file that is a copy ofUld < Component
. I.e. have 2 components, don't removeUld
- In places where you previously fetched
Uld
make it so that now you fetch records where type isUld
orULD
- In places where you created new
Uld
records make it so that it instead creates newULD
records - Deploy these changes without any migrations, this way your servers will be backwards compatible with
Uld
but would also work withULD
- Deploy your migration now
- Finally, remove all the mentions/files related to the old
Uld
and deploy again
How to re-name a ActiveRecord Model which can automatically change the table name in DB?
I would recommend the following:
Change manually the Active Record model class into Train
Make migration to change the database table name from cars to trains
Make good search to change references from Car to Train.
If you have constantly the need to change database table names, you might want to reconsider naming the tables more abstact way. Like in this case you could have table called vehicles and have the "type" field specifying the type (for instance: car or train).
Related Topics
Rails 3.2.8 - How to Get the Week Number from Rails
Clicking a Button with Ruby Mechanize
What Are All the "Conventions" for Ruby on Rails
Activerecords Select(:Id).Collect VS. Pluck(:Id) Methods: Why Is Pure Ar "Pluck" Slower
Soap Client for Ruby 1.9 and Rails
How to Stub a Method of an Included Module with Rspec
How to Express 'Infinite Time'
Thor & Yaml Outputting as Binary
Array Typeerror: Can't Convert Fixnum into String
Duplicating a Ruby Array of Strings
Getaddrinfo Error with Mechanize
Ror - How to Remove Rails 4.1.1 Version
Why Will a Range Not Work When Descending