我正在阅读Rails 3 in Action并按顺序执行命令。但是,当我运行命令
时rails new things_i_bought
cd things_i_bought
bundle install
rails generate scaffold purchase name:string cost:float
这本书说我应该得到这个代码:
class CreatePurchases < ActiveRecord::Migration
def self.up #not created in my code
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
def self.down # not created in my code
drop_table :purchases
end
end
我改为使用此代码:
class CreatePurchases < ActiveRecord::Migration
def change
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
end
为什么不为我创建上下类方法?我正在使用 rails 3.1.1和ruby 1.9.2。
答案 0 :(得分:11)
感谢您阅读我的书!
正如JacobM和dbalatero已经解释过的,这是Rails 3.1中的一个新功能。 Aaron Patterson添加了这一特殊功能,作为简化迁移语法的一种方法。在早期版本的Rails中,您必须按照本书所示进行操作:
class CreatePurchases < ActiveRecord::Migration
def self.up
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
def self.down
drop_table :purchases
end
end
但这有点重复自己。 Aaron创建了一个看起来很好且更简单的迁移语法,只调用了向前迁移所需的方法,但也允许向后迁移(称为“回滚”)。使用Rails 3.1语法编写的相同迁移是:
class CreatePurchases < ActiveRecord::Migration
def change
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
end
因此,当此迁移“向前”运行时,Rails将使用字段创建购买表。当你向后滚动(或者“向后”运行)时,Rails会知道放下桌子。
然而,这种语法并不完全完善,并且您会遇到change_column
等方法的问题。当发生这种情况时,最好坚持在迁移中定义def up
和def down
方法:
class CreatePurchases < ActiveRecord::Migration
def up
change_column :purchases, :cost, :integer
end
def down
change_column :purchases, :cost, :float
end
end
那是因为在这个例子中Rails不知道如何将它切换回以前的类型。我希望这能更好地解释它!
答案 1 :(得分:1)
这是new feature in Rails 3.1。对于Rails可以找出如何反转的更改,例如创建表,您只需创建一个“更改”方法,其中包含可能已经“up”的代码,并且它会找出如何自行执行“down”操作
您也可以自己定义“向上”和“向下”方法 - 对于某些更改(例如删除列),Rails将无法弄清楚 - 但语法有点不同;它不只是def up
而不是def self.up
(它们现在是实例方法而不是类方法)。
答案 2 :(得分:0)
我相信新的Rails 3.1,数据库迁移方法可以自我意识到如何运行向上/向下迁移。
因此,如果您定义def change
方法,它会尝试使用这些自我感知方法:在这种情况下,create_table
知道在DROP TABLE
中执行down
上下文,CREATE TABLE
上下文中的up
。
如果你想要旧样式,你可以继续使用它并定义你自己的self.down
和self.up
方法。
编辑:这是关于此博客文章的链接,名为“可逆迁移”:http://www.edgerails.info/articles/what-s-new-in-edge-rails/2011/05/06/reversible-migrations/index.html