Pregunta

Estoy utilizando jruby y carriles 2.2.2. Mi problema es que tengo una migración que no está siendo escrito correctamente en el esquema de base de datos.

Aquí está mi migración:

class CreateNotes < ActiveRecord::Migration
  def self.up
    create_table(:notes, :options => 'ENGINE=MyISAM') do |t|
      t.string :title
      t.text :body

      t.timestamps
    end

    execute "alter table notes ADD FULLTEXT(title, body)"

end

Esto es lo que produce en en schema.rb

create_table "notes", :force => true do |t|
  t.string   "title"
  t.text     "body"
  t.datetime "created_at"
  t.datetime "updated_at"
end

add_index "notes", ["title", "body"], :name => "title"

Tengo dos preguntas:

  • ¿Cómo consigo 'ENGINE=MyISAM' en el esquema?
  • add_index "notes", ["title", "body"], :name => "title" ¿Por qué la instrucción de ejecución convertirse? y ¿Cómo fuerzo migraciones a dejarlo como una instrucción de ejecución?

Gracias a Christian Lescuyer por la respuesta. Sin embargo, cuando he intentado esto nada cambió. Yo sin comentar la línea de config.active_record ... pero, mi esquema no ha cambiado. He intentado esto en jruby y el rubí 1.8.6 2.2.2 con los carriles y canales del borde y no hay cambios en el esquema. Alguien puede decirme lo que estoy haciendo mal?

¿Fue útil?

Solución

Como utilizo restricciones de clave externa, utilizo el formato de SQL para las migraciones. En environment.rb

# Use SQL instead of Active Record's schema dumper when creating the test database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
config.active_record.schema_format = :sql

Otros consejos

Yo también esperaba ver un nuevo archivo .sql aparece después de un "rake db: migrate", una vez que me puse

config.active_record.schema_format = :sql

en config / environment.rb.

Al parecer no es así como funciona, sin embargo. Tengo que hacer esto de forma explícita para obtener una db / [desarrollo | prueba | producción] archivo _structure.sql:

rake db:structure:dump

Apenas una actualización para aquellos en los carriles 3 (beta 4, en la actualidad) - solución de Christian sigue siendo correcta, sólo el lugar correcto para poner la línea está en config/application.rb, en el ámbito de la clase Application que debería definirse en un módulo el nombre de su proyecto Rails.

Christian es correcto.

DO

config.active_record.schema_format =: sql

en environment.rb

pero luego se va a utilizar un formato de volcado de archivos de esquema y ubicación diferente. trate de hacer la migración y en busca de "schema.sql" en lugar de scehema.rb

la razón de todo esto es que el punto del archivo de esquema es una base de datos inespecíficos (funciona para todos los tipos de bases de datos) del archivo. por lo que cuando se utilizan las funciones que sólo funcionan en MySQL a través de un comunicado unsupoorted ejecutar, no pueden ser shoehorned a schema.rb

Para utilizar la variante de SQL para probar (en lugar de schema.rb), tendrá que utilizar

  

rake db: test: clone_structure

Nuestro esquema utiliza UUID (UUID) de la gema y también Red Hill on Rails (Rhor) FK buen complemento. Por desgracia, los FKs requieren PK que sólo pueden ser añadidos usando ejecuta en las migraciones.

Es bien sabido que estos se ejecuta no lo hacen a la schema.rb; sin embargo, era más difícil encontrar la alternativa rake db: test:. prepararse para aplicaciones que no pueden utilizar schema.rb

La siguiente monkeypatch resuelve tanto el problema índice FULLTEXT y la opción de motor de base de datos para su dumper esquema (Rails 3.2). Se puede poner en config/initializers/ (por ejemplo schema_dumper_monkeypatch.rb):

module ActiveRecord
  class SchemaDumper
    def table(table, stream)
      columns = @connection.columns(table)
      begin
        tbl = StringIO.new

        # first dump primary key column
        if @connection.respond_to?(:pk_and_sequence_for)
          pk, _ = @connection.pk_and_sequence_for(table)
        elsif @connection.respond_to?(:primary_key)
          pk = @connection.primary_key(table)
        end

        tbl.print "  create_table #{remove_prefix_and_suffix(table).inspect}"
        if columns.detect { |c| c.name == pk }
          if pk != 'id'
            tbl.print %Q(, :primary_key => "#{pk}")
          end
        else
          tbl.print ", :id => false"
        end
        tbl.print ", :force => true"

        # Add table engine
        res = @connection.execute "SHOW TABLE STATUS LIKE '#{table}'"
        engine = res.first[res.fields.index("Engine")] rescue nil
        tbl.print ", :options => 'ENGINE=#{engine}'" if engine
        res = nil # Free the result        

        tbl.puts " do |t|"

        # then dump all non-primary key columns
        column_specs = columns.map do |column|
          raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
          next if column.name == pk
          spec = {}
          spec[:name]      = column.name.inspect

          # AR has an optimization which handles zero-scale decimals as integers. This
          # code ensures that the dumper still dumps the column as a decimal.
          spec[:type]      = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) }
                               'decimal'
                             else
                               column.type.to_s
                             end
          spec[:limit]     = column.limit.inspect if column.limit != @types[column.type][:limit] && spec[:type] != 'decimal'
          spec[:precision] = column.precision.inspect if column.precision
          spec[:scale]     = column.scale.inspect if column.scale
          spec[:null]      = 'false' unless column.null
          spec[:default]   = default_string(column.default) if column.has_default?
          (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
          spec
        end.compact

        # find all migration keys used in this table
        keys = [:name, :limit, :precision, :scale, :default, :null] & column_specs.map{ |k| k.keys }.flatten

        # figure out the lengths for each column based on above keys
        lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }

        # the string we're going to sprintf our values against, with standardized column widths
        format_string = lengths.map{ |len| "%-#{len}s" }

        # find the max length for the 'type' column, which is special
        type_length = column_specs.map{ |column| column[:type].length }.max

        # add column type definition to our format string
        format_string.unshift "    t.%-#{type_length}s "

        format_string *= ''

        column_specs.each do |colspec|
          values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len }
          values.unshift colspec[:type]
          tbl.print((format_string % values).gsub(/,\s*$/, ''))
          tbl.puts
        end

        tbl.puts "  end"
        tbl.puts

        indexes(table, tbl)

        tbl.rewind
        stream.print tbl.read
      rescue => e
        stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
        stream.puts "#   #{e.message}"
        stream.puts
      end

      stream
    end    

    def indexes(table, stream)
      if (indexes = @connection.indexes(table)).any?
        add_index_statements = indexes.map do |index|

          if index.name =~ /fulltext/i
            "  execute \"CREATE FULLTEXT INDEX #{index.name} ON #{index.table} (#{index.columns.join(',')})\""
          elsif index.name =~ /spatial/i
            "  execute \"CREATE SPATIAL INDEX #{index.name} ON #{index.table} (#{index.columns.join(',')})\""
          else
            statement_parts = [
              ('add_index ' + remove_prefix_and_suffix(index.table).inspect),
              index.columns.inspect,
              (':name => ' + index.name.inspect),
            ]
            statement_parts << ':unique => true' if index.unique

            index_lengths = (index.lengths || []).compact
            statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty?

            index_orders = (index.orders || {})
            statement_parts << (':order => ' + index.orders.inspect) unless index_orders.empty?

            '  ' + statement_parts.join(', ')
          end
        end

        stream.puts add_index_statements.sort.join("\n")
        stream.puts
      end
    end
  end
end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top