Class: ActiveRecordInlineSchema::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record_inline_schema/config.rb

Defined Under Namespace

Classes: Column, Index

Constant Summary collapse

DEFAULT_CREATE_TABLE_OPTIONS =
{
  :mysql => 'ENGINE=InnoDB'
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ Config

Returns a new instance of Config.



12
13
14
15
16
# File 'lib/active_record_inline_schema/config.rb', line 12

def initialize(model)
  @model = model
  @ideal_columns = ::Set.new
  @ideal_indexes = ::Set.new
end

Instance Attribute Details

#ideal_columnsObject (readonly)

Returns the value of attribute ideal_columns.



9
10
11
# File 'lib/active_record_inline_schema/config.rb', line 9

def ideal_columns
  @ideal_columns
end

#ideal_indexesObject (readonly)

Returns the value of attribute ideal_indexes.



10
11
12
# File 'lib/active_record_inline_schema/config.rb', line 10

def ideal_indexes
  @ideal_indexes
end

#modelObject (readonly)

Returns the value of attribute model.



8
9
10
# File 'lib/active_record_inline_schema/config.rb', line 8

def model
  @model
end

Instance Method Details

#add_ideal_column(column_name, options) ⇒ Object



18
19
20
# File 'lib/active_record_inline_schema/config.rb', line 18

def add_ideal_column(column_name, options)
  ideal_columns.add Column.new(self, column_name, options)
end

#add_ideal_index(column_name, options) ⇒ Object



22
23
24
# File 'lib/active_record_inline_schema/config.rb', line 22

def add_ideal_index(column_name, options)
  ideal_indexes.add Index.new(self, column_name, options)
end

#apply(create_table_options) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/active_record_inline_schema/config.rb', line 26

def apply(create_table_options)
  non_standard_primary_key = if (primary_key_column = find_ideal_column(model.primary_key))
    primary_key_column.type != :primary_key
  end

  unless non_standard_primary_key
    add_ideal_column :id, :type => :primary_key
  end

  # Table doesn't exist, create it
  unless connection.table_exists? model.table_name

    if mysql?
      create_table_options ||= DEFAULT_CREATE_TABLE_OPTIONS[database_type]
    end

    table_definition = ::ActiveRecord::ConnectionAdapters::TableDefinition.new connection
    ideal_columns.each do |ideal_column|
      ideal_column.inject table_definition
    end

    # avoid using connection.create_table because in 3.0.x it ignores table_definition
    # and it also is too eager about adding a primary key column
    create_sql = "CREATE TABLE #{model.quoted_table_name} (#{table_definition.to_sql}) #{create_table_options}"

    if sqlite?
      connection.execute create_sql
      if non_standard_primary_key
        add_ideal_index model.primary_key, :unique => true
      end
    elsif postgresql?
      connection.execute create_sql
      if non_standard_primary_key
        # can't use add_index method because it won't let you do "PRIMARY KEY"
        connection.execute "ALTER TABLE #{model.quoted_table_name} ADD PRIMARY KEY (#{model.quoted_primary_key})"
      end
    elsif mysql?
      if non_standard_primary_key
        k = connection.quote_column_name(model.primary_key)
        create_sql.sub! /#{k} *([^\)]+)(?:[^,]+),/, "#{k} \\1) PRIMARY KEY,"
      end
      connection.execute create_sql
    end
    safe_reset_column_information
  end

  # Add to schema inheritance column if necessary
  if model.descendants.any? and not find_ideal_column(model.inheritance_column)
    add_ideal_column model.inheritance_column, :type => :string
  end

  # Remove fields from db no longer in schema
  existing_column_names.reject do |existing_column_name|
    find_ideal_column existing_column_name
  end.each do |existing_column_name|
    connection.remove_column model.table_name, existing_column_name
  end

  # Add fields to db new to schema
  ideal_columns.reject do |ideal_column|
    find_existing_column ideal_column.name
  end.each do |ideal_column|
    connection.add_column model.table_name, ideal_column.name, ideal_column.type, ideal_column.options
  end

  # Change attributes of existent columns
  existing_columns_hash.each do |existing_column_name, existing_column|
    next if existing_column_name.to_s == model.primary_key.to_s
    ideal_column = find_ideal_column existing_column_name
    option_changes = {}

    # First, check if the field type changed
    type_changed = !([existing_column.type.to_s, existing_column.sql_type.to_s].include?(ideal_column.type.to_s))

    # Next, iterate through our extended attributes, looking for any differences
    # This catches stuff like :null, :precision, etc
    ideal_column.options.except(:base).each do |k, v|
      if !v.nil? and v != existing_column.send(k)
        option_changes[k] = v
      end
    end

    # Change the column if applicable
    if type_changed or option_changes.any?
      connection.change_column model.table_name, existing_column_name, ideal_column.type, option_changes
    end
  end

  # Remove old index
  existing_index_names.reject do |existing_index_name|
    find_ideal_index existing_index_name
  end.each do |existing_index_name|
    connection.remove_index model.table_name, :name => existing_index_name
  end

  # Add indexes
  ideal_indexes.reject do |ideal_index|
    find_existing_index ideal_index.name
  end.each do |ideal_index|
    connection.add_index model.table_name, ideal_index.column_name, ideal_index.options
  end

  safe_reset_column_information
end

#clearObject



131
132
133
134
# File 'lib/active_record_inline_schema/config.rb', line 131

def clear
  @ideal_columns = ::Set.new
  @ideal_indexes = ::Set.new
end