Frage

Ich bin mit JRuby und Schienen 2.2.2. Mein Problem ist, ich habe eine Migration, die nicht auf das Datenbankschema korrekt geschrieben werden.

Hier ist meine Migration:

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

Hier ist, was es produziert auf in 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"

Ich habe zwei Fragen:

  • Wie kann ich 'ENGINE=MyISAM' in das Schema bekommen?
  • Warum wird ausführen Statement add_index "notes", ["title", "body"], :name => "title"? und wie kann ich Migrationen zwingen zu lassen, wie eine Ausführungsanweisung?

Dank Christian Lescuyer für die Antwort. Allerdings, wenn ich versuchte, diese nichts geändert. Ich unkommentiert die config.active_record ... Linie aber, mein Schema nicht geändert hat. Ich habe dies in jruby versucht und auf Rubin 1.8.6 mit Schienen 2.2.2 und Kantenschienen und es gibt keine Änderungen im Schema. Kann mir jemand sagen, was ich falsch mache?

War es hilfreich?

Lösung

Als ich für Fremdschlüssel verwenden, verwende ich das SQL-Format für Migrationen. In 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

Andere Tipps

Auch ich erwartete eine neue SQL-Datei erscheint nach einem sehen „rake db: wandern“, wenn ich gesetzt

config.active_record.schema_format = :sql

in config / environment.rb.

Das ist offenbar nicht, wie es funktioniert, aber. Ich habe dies zu tun explizit eine db / [Entwicklung | Test | Produktion] zu erhalten _structure.sql Datei:

rake db:structure:dump

Nur ein Update für die auf Rails 3 (beta 4, zur Zeit) - Christian-Lösung ist nach wie vor richtig, nur der richtige Ort, um die Linie zu setzen ist in config/application.rb, unter dem Anwendungsbereich der Application Klasse, die in einem Modul definiert werden soll benannt nach dem Rails-Projekt.

christian richtig ist.

do

config.active_record.schema_format = SQL

in environment.rb

aber dann müssen Sie ein anderes Schema Dump-Format und Speicherort der Datei verwenden. versuchen Sie die Migration und die Suche nach „schema.sql“ statt scehema.rb tun

der Grund für all dies ist, dass der Punkt der Schemadatei eine Datenbank unspezifisch Datei (für alle Arten von Datenbanken funktioniert). so, wenn Sie Funktionen, die nur auf MySQL arbeiten durch eine unsupoorted Anweisung ausführen, können sie nicht in bugsiert werden, um schema.rb

Um die SQL-Variante zum Testen (statt schema.rb) zu verwenden, werden Sie verwenden müssen, um

  

rake db: test: clone_structure

Unser Schema verwendet UUID (UUID gem) und auch Red Hill on Rails (Rhor) nice FK-Plug-in. Unglücklicherweise erfordern die FKs PKs, die nur mit FÜHRT in den Migrationen hinzugefügt werden können.

Es ist bekannt, dass diese ausführt zum schema.rb macht es nicht; war es jedoch schwieriger, die Harke Alternative zu finden auf dem db: test:. Vorbereitung für Anwendungen, die nicht schema.rb verwenden

Das folgende monkeypatch löst sowohl den Volltextindex Ausgabe und DB-Engine-Option für Ihr Schema dumper (Rails 3.2). Sie können es in config/initializers/ setzen (z 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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top