Class: Miguel::Schema
- Inherits:
-
Object
- Object
- Miguel::Schema
- Defined in:
- lib/miguel/schema.rb
Overview
Class for defining database schema.
Defined Under Namespace
Modules: Output Classes: Column, ForeignKey, Index, Table
Constant Summary collapse
- ZERO_TIME =
String denoting zero time in MySQL.
'0000-00-00 00:00:00'.freeze
- DEFAULT_TIME =
String denoting default time.
'2000-01-01 00:00:00'.freeze
- LOCK =
Mutex protecting access to thread sensitive variables.
Mutex.new
Instance Attribute Summary collapse
-
#opts ⇒ Object
readonly
Schema options.
Class Method Summary collapse
-
.default_options ⇒ Object
Get default schema options.
-
.default_options=(opts) ⇒ Object
(also: set_default_options)
Set default schema options.
-
.define(opts = {}, &block) ⇒ Object
Define schema with provided block.
-
.load(name, opts = {}) ⇒ Object
Load schema from given file.
Instance Method Summary collapse
-
#add_join_table(id_left, table_left, id_right, table_right, name = nil, &block) ⇒ Object
(also: #join_table)
Helper for creating join tables conveniently.
-
#add_table(name, &block) ⇒ Object
(also: #table)
Add table with given name, optionally defined with provided block.
-
#apply_defaults(table_name, name, *args) ⇒ Object
Apply default options to given +add_table+ block statement.
-
#clear_defaults(name) ⇒ Object
Clear defaults and aliases for given statement.
-
#define(&block) ⇒ Object
Define schema with the provided block.
-
#dump(out = Dumper.new) ⇒ Object
Dump table definition to given output.
-
#get_defaults(name) ⇒ Object
Get default options for given statement.
-
#initialize(opts = {}) ⇒ Schema
constructor
Create new schema.
-
#named_tables(names) ⇒ Object
Get tables with given names.
-
#set_defaults(name, *args, &block) ⇒ Object
Set default options for given statement used in +add_table+ blocks.
-
#set_standard_defaults(opts = self.opts) ⇒ Object
Set standard defaults and aliases for often used types.
-
#table_names ⇒ Object
Get names of all tables.
-
#tables ⇒ Object
Get all tables.
Constructor Details
#initialize(opts = {}) ⇒ Schema
Create new schema.
429 430 431 432 433 434 435 |
# File 'lib/miguel/schema.rb', line 429 def initialize( opts = {} ) @tables = {} @aliases = {} @defaults = {} @callbacks = {} @opts = self.class..merge(opts) end |
Instance Attribute Details
#opts ⇒ Object (readonly)
Schema options.
426 427 428 |
# File 'lib/miguel/schema.rb', line 426 def opts @opts end |
Class Method Details
.default_options ⇒ Object
Get default schema options.
650 651 652 |
# File 'lib/miguel/schema.rb', line 650 def sync{ @opts || {} } end |
.default_options=(opts) ⇒ Object Also known as: set_default_options
Set default schema options.
655 656 657 |
# File 'lib/miguel/schema.rb', line 655 def ( opts ) sync{ @opts = opts.nil? ? nil : opts.dup } end |
.define(opts = {}, &block) ⇒ Object
Define schema with provided block.
661 662 663 664 665 |
# File 'lib/miguel/schema.rb', line 661 def define( opts = {}, &block ) sync do set_schema( new( opts ).define( &block ) ) end end |
.load(name, opts = {}) ⇒ Object
Load schema from given file.
668 669 670 671 672 673 674 675 676 677 |
# File 'lib/miguel/schema.rb', line 668 def load( name, opts = {} ) name = File.( name ) sync do get_schema do ( opts ) do Kernel.load( name ) end end end end |
Instance Method Details
#add_join_table(id_left, table_left, id_right, table_right, name = nil, &block) ⇒ Object Also known as: join_table
Helper for creating join tables conveniently. It is equivalent to the following: add_table name do foreign_key id_left, table_left foreign_key id_right, table_right primary_key [id_left, id_right] unique [id_right, id_left] end In case a block is provided, it is used to further extend the table defined.
471 472 473 474 475 476 477 478 479 480 |
# File 'lib/miguel/schema.rb', line 471 def add_join_table( id_left, table_left, id_right, table_right, name = nil, &block ) name ||= [ table_left, table_right ].sort.join( '_' ) add_table name do foreign_key id_left, table_left foreign_key id_right, table_right primary_key [ id_left, id_right ] unique [ id_right, id_left ] instance_eval &block if block end end |
#add_table(name, &block) ⇒ Object Also known as: table
Add table with given name, optionally defined with provided block.
453 454 455 456 457 458 459 |
# File 'lib/miguel/schema.rb', line 453 def add_table( name, &block ) name = name.to_sym fail( ArgumentError, "table #{name} is already defined" ) if @tables[ name ] @tables[ name ] = table = Table.new( self, name ) table.define( &block ) if block table end |
#apply_defaults(table_name, name, *args) ⇒ Object
Apply default options to given +add_table+ block statement. See +set_defaults+ for detailed explanation.
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 |
# File 'lib/miguel/schema.rb', line 605 def apply_defaults( table_name, name, *args ) opts = {} opts.merge!( get_defaults( :global ) ) if name[ -1 ] == '?' opts[ :null ] = true original_name = name name = name[ 0..-2 ].to_sym end opts.merge!( get_defaults( name ) ) opts.merge!( get_defaults( original_name ) ) if original_name if callback = @callbacks[ name ] callback.call( opts, args, table_name ) end opts.merge!( args.pop ) if args.last.is_a? Hash args << opts unless opts.empty? [ ( @aliases[ name ] || name ), *args ] end |
#clear_defaults(name) ⇒ Object
Clear defaults and aliases for given statement.
513 514 515 516 517 518 |
# File 'lib/miguel/schema.rb', line 513 def clear_defaults( name ) @aliases.delete( name ) @defaults.delete( name ) @callbacks.delete( name ) self end |
#define(&block) ⇒ Object
Define schema with the provided block.
637 638 639 640 641 642 |
# File 'lib/miguel/schema.rb', line 637 def define( &block ) fail( ArgumentError, "missing schema block" ) unless block set_standard_defaults unless opts[ :use_defaults ] == false instance_eval &block self end |
#dump(out = Dumper.new) ⇒ Object
Dump table definition to given output.
629 630 631 632 633 634 |
# File 'lib/miguel/schema.rb', line 629 def dump( out = Dumper.new ) for table in tables table.dump( out ) end out end |
#get_defaults(name) ⇒ Object
Get default options for given statement.
521 522 523 |
# File 'lib/miguel/schema.rb', line 521 def get_defaults( name ) @defaults[ name ] || {} end |
#named_tables(names) ⇒ Object
Get tables with given names.
448 449 450 |
# File 'lib/miguel/schema.rb', line 448 def named_tables( names ) @tables.values_at( *names ) end |
#set_defaults(name, *args, &block) ⇒ Object
Set default options for given statement used in +add_table+ blocks. It uses the following arguments: +name+:: The name of the statement, like +:primary_key+ or +:String+. The special name +:global+ may be used to set default options for any statement. +alias+:: Optional real statement to use instead of +name+, like +:String+ instead of +:Text+. +args+:: Hash containing the default options for +name+. +block+:: Optional block which may further modify the options.
If a block is provided, it is invoked with the following arguments: +opts+:: The trailing options passed to given statement, to be modified as necessary. +args+:: Any leading arguments passed to given statement, as readonly context. +table+:: The name of the currently defined table, as readonly context.
The final options for each statement are created in the following order: +:global+ options, extended with +:null+ set to +true+ in case of ? syntax, merged with options for +name+ (without ?), modified by the optional +block+ callback, and merged with the original options used with the statement.
Also note that the defaults are applied in the instant the +table+ block is evaluated, so it is eventually possible (though not necessarily recommended) to change them in between.
503 504 505 506 507 508 509 510 |
# File 'lib/miguel/schema.rb', line 503 def set_defaults( name, *args, &block ) clear_defaults( name ) @aliases[ name ] = args.shift if args.first.is_a? Symbol @defaults[ name ] = args.pop if args.last.is_a? Hash @callbacks[ name ] = block fail( ArgumentError, "invalid defaults for #{name}" ) unless args.empty? self end |
#set_standard_defaults(opts = self.opts) ⇒ Object
Set standard defaults and aliases for often used types.
The current set of defaults is as follows:
:global, :null => false
:Bool, :TrueClass :True, :TrueClass, :default => true :False, :TrueClass, :default => false :Signed, :integer, :unsigned => false :Unsigned, :integer, :unsigned => true :Text, :String, :text => true :Time, :timestamp, :default => '0000-00-00 00:00:00' :Time?, :timestamp, :default => nil
:unique, :index, :unique => true :fulltext, :index, :type => :full_text
:Key, :integer, :unsigned => false :primary_key, :type => :integer, :unsigned => false :foreign_key, :key => :id, :type => :integer, :unsigned => false
If the +unsigned_keys+ option is set to true, the keys are set up to use unsigned integers instead.
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 |
# File 'lib/miguel/schema.rb', line 549 def set_standard_defaults( opts = self.opts ) # We set NOT NULL on everything by default, but note the ? # syntax (like Text?) which declares the column as NULL. set_defaults :global, :null => false # We also like our keys unsigned, so we allow setting that, too. # Unfortunately, :unsigned currently works only with :integer, # not the default :Integer, and :integer can't be specified for compound keys, # so we have to use the callback to set the type only at correct times. # Furthermore, Postgres's autoincrementing serials only work with Integer, # so we set the type only as long as the unsigned keys are requested. unsigned_keys = !! opts[ :unsigned_keys ] set_defaults :Key, :integer, :unsigned => unsigned_keys set_defaults :primary_key, :unsigned => unsigned_keys do |opts,args,table| opts[ :type ] ||= :integer unless args.first.is_a? Array or not opts[ :unsigned ] end set_defaults :foreign_key, :key => :id, :unsigned => unsigned_keys do |opts,args,table| opts[ :type ] ||= :integer unless args.first.is_a? Array or not opts[ :unsigned ] end # Save some typing for unique and fulltext indexes. set_defaults :unique, :index, :unique => true set_defaults :fulltext, :index, :type => :full_text do |opts,args,table| opts[ :name ] ||= [ table, *args, :fulltext ].join( '_' ).to_sym end # Type shortcuts we use frequently. set_defaults :Bool, :TrueClass set_defaults :True, :TrueClass, :default => true set_defaults :False, :TrueClass, :default => false set_defaults :Signed, :integer, :unsigned => false set_defaults :Unsigned, :integer, :unsigned => ! opts[ :signed_unsigned ] set_defaults :String, :text => false set_defaults :Text, :String, :text => true # We want times to be stored as 4 byte timestamps, however # we have to be careful to turn off the MySQL autoupdate behavior. # That's why we have to set defaults explicitly. default_time = ( opts[ :zero_timestamps ] || ( opts[ :mysql_timestamps ] && opts[ :zero_timestamps ].nil? ) ) ? ZERO_TIME : DEFAULT_TIME set_defaults :Time, :timestamp, :default => default_time set_defaults :Time?, :timestamp, :default => nil self end |
#table_names ⇒ Object
Get names of all tables.
443 444 445 |
# File 'lib/miguel/schema.rb', line 443 def table_names @tables.keys end |
#tables ⇒ Object
Get all tables.
438 439 440 |
# File 'lib/miguel/schema.rb', line 438 def tables @tables.values end |