require 'active_support/concern'
module Arql
module Concerns
module GlobalDataDefinition
extend ActiveSupport::Concern
included do
# Example:
#
# create_table :post, id: false, primary_key: :id do |t|
# t.column :id, :bigint, precison: 19, comment: 'ID'
# t.column :name, :string, comment: '名称'
# t.column :gmt_created, :datetime, comment: '创建时间'
# t.column :gmt_modified, :datetime, comment: '最后修改时间'
# end
#
# Creates a new table with the name +table_name+. +table_name+ may either
# be a String or a Symbol.
#
# There are two ways to work with #create_table. You can use the block
# form or the regular form, like this:
#
# === Block form
#
# # create_table() passes a TableDefinition object to the block.
# # This form will not only create the table, but also columns for the
# # table.
#
# create_table(:suppliers) do |t|
# t.column :name, :string, limit: 60
# # Other fields here
# end
#
# === Block form, with shorthand
#
# # You can also use the column types as method calls, rather than calling the column method.
# create_table(:suppliers) do |t|
# t.string :name, limit: 60
# # Other fields here
# end
#
# === Regular form
#
# # Creates a table called 'suppliers' with no columns.
# create_table(:suppliers)
# # Add a column to 'suppliers'.
# add_column(:suppliers, :name, :string, {limit: 60})
#
# The +options+ hash can include the following keys:
# [:id]
# Whether to automatically add a primary key column. Defaults to true.
# Join tables for {ActiveRecord::Base.has_and_belongs_to_many}[rdoc-ref:Associations::ClassMethods#has_and_belongs_to_many] should set it to false.
#
# A Symbol can be used to specify the type of the generated primary key column.
# [:primary_key]
# The name of the primary key, if one is to be added automatically.
# Defaults to +id+. If :id is false, then this option is ignored.
#
# If an array is passed, a composite primary key will be created.
#
# Note that Active Record models will automatically detect their
# primary key. This can be avoided by using
# {self.primary_key=}[rdoc-ref:AttributeMethods::PrimaryKey::ClassMethods#primary_key=] on the model
# to define the key explicitly.
#
# [:options]
# Any extra options you want appended to the table definition.
# [:temporary]
# Make a temporary table.
# [:force]
# Set to true to drop the table before creating it.
# Set to +:cascade+ to drop dependent objects as well.
# Defaults to false.
# [:if_not_exists]
# Set to true to avoid raising an error when the table already exists.
# Defaults to false.
# [:as]
# SQL to use to generate the table. When this option is used, the block is
# ignored, as are the :id and :primary_key options.
#
# ====== Add a backend specific option to the generated SQL (MySQL)
#
# create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
#
# generates:
#
# CREATE TABLE suppliers (
# id bigint auto_increment PRIMARY KEY
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
#
# ====== Rename the primary key column
#
# create_table(:objects, primary_key: 'guid') do |t|
# t.column :name, :string, limit: 80
# end
#
# generates:
#
# CREATE TABLE objects (
# guid bigint auto_increment PRIMARY KEY,
# name varchar(80)
# )
#
# ====== Change the primary key column type
#
# create_table(:tags, id: :string) do |t|
# t.column :label, :string
# end
#
# generates:
#
# CREATE TABLE tags (
# id varchar PRIMARY KEY,
# label varchar
# )
#
# ====== Create a composite primary key
#
# create_table(:orders, primary_key: [:product_id, :client_id]) do |t|
# t.belongs_to :product
# t.belongs_to :client
# end
#
# generates:
#
# CREATE TABLE order (
# product_id bigint NOT NULL,
# client_id bigint NOT NULL
# );
#
# ALTER TABLE ONLY "orders"
# ADD CONSTRAINT orders_pkey PRIMARY KEY (product_id, client_id);
#
# ====== Do not add a primary key column
#
# create_table(:categories_suppliers, id: false) do |t|
# t.column :category_id, :bigint
# t.column :supplier_id, :bigint
# end
#
# generates:
#
# CREATE TABLE categories_suppliers (
# category_id bigint,
# supplier_id bigint
# )
#
# ====== Create a temporary table based on a query
#
# create_table(:long_query, temporary: true,
# as: "SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id")
#
# generates:
#
# CREATE TEMPORARY TABLE long_query AS
# SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
#
# See also TableDefinition#column for details on how to create columns.
def create_table(table_name, **options, &blk)
ActiveRecord::Base.connection.create_table(table_name, **options, &blk)
end
# Creates a new join table with the name created using the lexical order of the first two
# arguments. These arguments can be a String or a Symbol.
#
# # Creates a table called 'assemblies_parts' with no id.
# create_join_table(:assemblies, :parts)
#
# You can pass an +options+ hash which can include the following keys:
# [:table_name]
# Sets the table name, overriding the default.
# [:column_options]
# Any extra options you want appended to the columns definition.
# [:options]
# Any extra options you want appended to the table definition.
# [:temporary]
# Make a temporary table.
# [:force]
# Set to true to drop the table before creating it.
# Defaults to false.
#
# Note that #create_join_table does not create any indices by default; you can use
# its block form to do so yourself:
#
# create_join_table :products, :categories do |t|
# t.index :product_id
# t.index :category_id
# end
#
# ====== Add a backend specific option to the generated SQL (MySQL)
#
# create_join_table(:assemblies, :parts, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
#
# generates:
#
# CREATE TABLE assemblies_parts (
# assembly_id bigint NOT NULL,
# part_id bigint NOT NULL,
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8
#
def create_join_table(table_1, table_2, column_options: {}, **options)
ActiveRecord::Base.connection.create_join_table(table_1, table_2, column_options, **options)
end
# Drops a table from the database.
#
# [:force]
# Set to +:cascade+ to drop dependent objects as well.
# Defaults to false.
# [:if_exists]
# Set to +true+ to only drop the table if it exists.
# Defaults to false.
#
# Although this command ignores most +options+ and the block if one is given,
# it can be helpful to provide these in a migration's +change+ method so it can be reverted.
# In that case, +options+ and the block will be used by #create_table.
def drop_table(table_name, **options)
ActiveRecord::Base.connection.drop_table(table_name, **options)
end
# Drops the join table specified by the given arguments.
# See #create_join_table for details.
#
# Although this command ignores the block if one is given, it can be helpful
# to provide one in a migration's +change+ method so it can be reverted.
# In that case, the block will be used by #create_join_table.
def drop_join_table(table_1, table_2, **options)
ActiveRecord::Base.connection.drop_join_table(table_1, table_2, **options)
end
# Renames a table.
#
# rename_table('octopuses', 'octopi')
#
def rename_table(table_name, new_name)
ActiveRecord::Base.connection.rename_table(table_name, new_name)
end
end
end
end
end