1

Assuming I have 2 databases, main and temp, I have an ActiveRecord class Entry that corresponds to an entries table in main, how can I create a similar table in temp.

The first stab is use Entry.connection.execute('show create table #{Entry.table_name}') and invoke that against another table. (works if main and temp are same kind of database).

Is there a nicer way to do it? Preferably one that doesn't involve reading & invoking "create table" expressions.

For example, something with ActiveRecord::Schema.define seems to be best. But I'm not sure exactly what to do.

Thanks.

2
  • You do realize that every method will eventually call show create table, right? You just don't want to call it yourself? :) Commented Apr 13, 2012 at 0:05
  • @SergioTulentsev I'm assuming ActiveRecord adapters will deal with subtle differences in create table syntax for me. e.g. if one table is MySQL and the other is SQLite. Commented Apr 13, 2012 at 0:11

2 Answers 2

2

After quick googling I didn't find ready-made method of achieving this without raw SQL. You can, however, make your own solution by mimicking what annotate_models does.

A piece from https://github.com/ctran/annotate_models/blob/master/lib/annotate/annotate_models.rb

# Use the column information in an ActiveRecord class
# to create a comment block containing a line for
# each column. The line contains the column name,
# the type (and length), and any optional attributes
def get_schema_info(klass, header, options = {})
  info = "# #{header}\n#\n"
  info << "# Table name: #{klass.table_name}\n#\n"

  max_size = klass.column_names.collect{|name| name.size}.max + 1
  klass.columns.each do |col|
    attrs = []
    attrs << "default(#{quote(col.default)})" unless col.default.nil?
    attrs << "not null" unless col.null
    attrs << "primary key" if col.name == klass.primary_key

    col_type = col.type.to_s
    if col_type == "decimal"
      col_type << "(#{col.precision}, #{col.scale})"

Also, you might want to read what ActiveRecord Migrations Guide has to offer.

ActiveRecord::Schema.define(:version => 20080906171750) do
  create_table "authors", :force => true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end

This file is created by inspecting the database and expressing its structure using create_table, add_index, and so on. Because this is database-independent, it could be loaded into any database that Active Record supports. This could be very useful if you were to distribute an application that is able to run against multiple databases.

There is however a trade-off: db/schema.rb cannot express database specific items such as foreign key constraints, triggers, or stored procedures. While in a migration you can execute custom SQL statements, the schema dumper cannot reconstitute those statements from the database. If you are using features like this, then you should set the schema format to :sql.

Instead of using Active Record’s schema dumper, the database’s structure will be dumped using a tool specific to the database (via the db:structure:dump Rake task) into db/structure.sql. For example, for the PostgreSQL RDBMS, the pg_dump utility is used. For MySQL, this file will contain the output of SHOW CREATE TABLE for the various tables. Loading these schemas is simply a question of executing the SQL statements they contain. By definition, this will create a perfect copy of the database’s structure. Using the :sql schema format will, however, prevent loading the schema into a RDBMS other than the one used to create it.

Sign up to request clarification or add additional context in comments.

Comments

1

If you want just move from one database to another, use gem 'yaml_db'

1 Comment

Looks interesting. But the yaml file as the middleman is not needed. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.