English 中文(简体)
如何在rails中编写条件迁移?
原标题:How to write conditional migrations in rails?

我正在寻找在rails中编写迁移的方法,这些迁移可以对数据库多次执行而不会失败。

例如,假设我有这样的迁移:

class AddUrlToProfile < ActiveRecord::Migration
  def self.up
    add_column :profile, :url, :string
  end

  def self.down
    remove_column :profile, :url
  end
end

如果Profile表中已经存在url列(例如,如果schema.rb被意外修改),则我的迁移将失败,说明它是重复的!

那么,只有在迫不得已的情况下,如何执行这种迁移呢?

谢谢

最佳回答

你可以这样做:

class AddUrlToProfile < ActiveRecord::Migration
  def self.up
    Profile.reset_column_information
    add_column(:profile, :url, :string) unless Profile.column_names.include?( url )

  end

  def self.down
    Profile.reset_column_information
    remove_column(:profile, :url) if Profile.column_names.include?( url )
  end
end

这将在开始之前重置列信息,确保Profile模型具有实际表中的最新列信息。然后,它只会在列不存在的情况下添加该列。down函数也会发生同样的情况,但它只删除存在的列。

如果您有多个这样的用例,您可以将代码分解为一个函数,并在迁移中重用它。

问题回答

对于Rails3.X,是否存在column_exists?(:table_name,:column_name)方法。

对于Rails2.X,您可以使用以下命令检查列的存在:

columns("<table name>").index {|col| col.name == "<column name>"}

…或者,如果您不在迁移文件中:

ActiveRecord::Base.connection.columns("<table name>").index {|col| col.name == "<column name>"}

如果返回nil,则不存在这样的列。如果它返回一个Fixnum,那么该列确实存在。当然,如果您希望不仅仅通过列的名称来标识列,您可以在{…}之间放置更多选择性参数,例如:

{ |col| col.name == "foo" and col.sql_type == "tinyint(1)" and col.primary == nil }

这应该有效

def self.table_exists?(name)
  ActiveRecord::Base.connection.tables.include?(name)
end

if table_exists?(:profile) && !Profile.column_names.include?("url")
  add_column :profile, :url, :string
end

Wrapping my migration in a conditional worked for me. Rails 4.X

class AddUrlToProfile < ActiveRecord::Migration
  unless Profile.column_names.include?("url")
    def self.up
      add_column :profile, :url, :string
    end

    def self.down
      remove_column :profile, :url
    end
  end
end 




相关问题
Copy data from Access to SQL

I am in the process of migrating an existing Access database to a SQL database with a web front-end. I have successfully copied the database to SQL using the SQL Server Migration tool and am working ...

MongoMapper and migrations

I m building a Rails application using MongoDB as the back-end and MongoMapper as the ORM tool. Suppose in version 1, I define the following model: class SomeModel include MongoMapper::Document ...

Switching to WPF. Is it time?

I m considering switching from MFC to WPF. My first concern is that there are too many users who don t have .NET with WPF installed yet. Can anybody point to a source containing the WPF penetration ...

rake db:migrate running all migrations correctly

I m fairly new to Ruby on Rails here. I have 2 migrate files that were provided. The first one, prefixed with 001, creates a table and some columns for that table. The next migrate file, prefixed ...

Migrate Java Applet to what/where?

I am reviewing currently a medium size code base (around 30K LOC) which uses a huge Applet and interfaces with other systems. It s a tool to create custom labels, so we need drag-n-drop and other ...

热门标签