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。

posted on 2012-09-01 23:59  边晓宇  阅读(3470)  评论(0编辑  收藏  举报