Ruby on Rails,创建模型,附赠模型与表名不一致时的解决方法
在前文《Ruby on Rails,创建和执行migrations迁移文件》中我们提到过创建模型的事情,我们创建模型的同时生成迁移文件。那时候我们关注的是迁移文件,现在我们把目光投向模型这边。
创建模型的命令是
rails generate model ModelNameInCamelCase
其中最后一个参数是模型的名字,用每个单词首字母大写的格式,比如说rails generate model Subject。
这个操作会生成两个中要的文件,其一是位于db/migrate目录下的迁移文件,“20120901143244_create_subjects.rb”。打开这个文件看看,会发现其实这里面定义的是一个叫做CreateSubjects的类,继承ActiveRecord::Migration,创建一个叫做subjects的表。
class CreateSubjects < ActiveRecord::Migration def change create_table :subjects do |t| t.timestamps end end end
另一个是位于app/model下的subject.rb,注意到是单数。打开文件看一看,其中定义了一个叫做Subject的类,继承ActiveRecord::Base,没有任何其他的内容。这代表着,Subject类打算完全按照ActiveRecord提供的缺省行为运行,这个后面再讲。
注意这些生成文件的位置、文件名、内容可以看出他们之间有着一致性(都基于模型名Subject)。
db/migrate
文件名:20120901143244_create_subjects.rb
类名:CreateSubjects
继承:ActiveRecord::Migration
表名:subjects
app/models
文件名:subject.rb
类名:Subject
继承:ActiveRecord::Base
而如果我们遵守这样的一致性便能保证Rails能够建立他们之间的关系,即使不对这些文件的关系进行更多的配置。比如说在某个时刻我对Rails说:“我要使用Subject类!”。你猜怎么着,Rails就会尝试着到app/models中名为subject.rb文件中找到Subject类的定义。如果我们说:”Subject类,我需要从数据库中读取对象!“。Subject类看了看自己,说没问题,我是一个ActiveRecord所以我知道应该到数据库中找到一张叫subjects的表,并从中读取出相应的对象。
当然了,这种遵守不是必须的,但如果我们简单的遵守规则能够这么方便快捷,有什么理由不这么做呢?
所以说rails generate命令没有什么神秘的,只是帮我们按照约定生成代码而已。我们也可以按照约定自己来编写这些内容,结果不会有任何区别。使用rails generate方法创建出来的模型都自动继承了ActiveRecord,相当于建立了与数据库的关联,如果只想建立一个普通的类并不与数据库关联,删除”<ActiveRecord::Basde“或者手工创建即可。
回过头看一看User类,在app/models目录中,以后模型都在这个目录里放着。这个类创建之后,在《Ruby on Rails,数据库迁移命令和迁移任务编写》中修改过迁移文件。
class AlterUsers < ActiveRecord::Migration def up rename_table("users","admin_users") add_column("admin_users","username",:string,:limit=>25) add_column("admin_users","email",:string,:limit=>50) change_column("admin_users","email",:string,:default=>"",:limit=>100) add_column("admin_users","password",:string,:limit=>25) rename_column("admin_users","password","hashed_password") add_column("admin_users","salt",:string,:limit=>40) puts "***about to add an index ***" add_index("admin_users","username") end def down remove_index("admin_users","username") remove_column("admin_users","salt") rename_column("admin_users","hashed_password","password") remove_column("admin_users","password") remove_column("admin_users","email") remove_column("admin_users","username") rename_table("admin_users","users") end end
靠上面的位置,我们使用rename_table命令将表名从users改为了admin_users。可是请注意,迁移文件的这些操作,模型文件并不知道。换句话说,User依然以为与自己关联的表叫做users,但很显然现在已经不是了。
rename_table("users","admin_users")
这样一来就违背了Rails的规则,实际工作中是有可能出现这种情况的。比如说摆在我们面前的是一个老系统,不能按照我们的要求修改表名。我们来尝试自我修复一下,有两种方法。
第一种是调用ActiveRecord中内建的set_table_name方法,告诉User类与你对应的表名从现在起是admin_users了。第二种方法是将User类名改为AdminUser,文件名改为admin_user。