Question

J'utilise JRuby et Rails 2.2.2. Mon problème est que j'ai une migration qui n'est pas écrit correctement au schéma de base de données.

Voici ma 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

Voici ce qu'elle produit dans 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"

J'ai deux questions:

  • Comment puis-je obtenir 'ENGINE=MyISAM' dans le schéma?
  • Pourquoi mon instruction execute devenir add_index "notes", ["title", "body"], :name => "title"? et comment puis-je forcer les migrations de le laisser comme instruction execute?

Merci à Christian Lescuyer pour la réponse. Cependant, quand j'ai essayé ce rien changé. Je décommenté la config.active_record ... mais la ligne, mon schéma n'a pas changé. Je l'ai essayé en JRuby et Ruby 1.8.6 avec rails 2.2.2 et rails de bord et il n'y a pas de changements dans le schéma. Quelqu'un peut-il me dire ce que je fais mal?

Était-ce utile?

La solution

Comme je l'utilise les clés étrangères, j'utilise le format SQL pour les migrations. Dans 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

Autres conseils

Moi aussi je pensais voir un nouveau fichier sql apparaissent après un « rake db: migrate », une fois que je mets

config.active_record.schema_format = :sql

dans config / environment.rb.

Apparemment, ce n'est pas comment cela fonctionne, cependant. Je dois faire explicitement pour obtenir un db / [développement | Test | production] Fichier _structure.sql:

rake db:structure:dump

Juste une mise à jour pour ceux qui Rails 3 (beta 4, actuellement) - La solution de Christian est encore correcte, seul le bon endroit pour mettre la ligne est config/application.rb, sous la portée de la classe Application qui doit être défini dans un module du nom de votre projet Rails.

chrétien est droit.

do

config.active_record.schema_format =: sql

dans environment.rb

mais alors vous devez utiliser un autre format de vidage de schéma et l'emplacement du fichier. essayez de faire votre migration et la recherche de « schema.sql » au lieu de scehema.rb

la raison de tout cela est que le point du fichier système est une base de données non spécifique (fonctionne pour tous les types de bases de données) fichier. donc quand vous utilisez des fonctions qui ne fonctionnent que sur MySQL par une déclaration unsupoorted exécuter, ils ne peuvent pas être shoehorned pour schema.rb

Pour utiliser la variante SQL pour tester (au lieu de schema.rb), vous devrez utiliser

  

rake db: Test: clone_structure

Notre schéma utilise UUID (gem UUID) et aussi Red Hill on Rails (Rhôr) nice plug-in __gVirt_NP_NN_NNPS<__ FK. Malheureusement, les clefs étrangères exigent que seuls PKs peuvent être ajoutées à l'aide des migrations EXÉCUTE.

Il est bien connu que ces exécute ne permettent pas à la schema.rb; cependant, il est plus difficile de trouver l'alternative rake db: test:. préparer pour les applications qui ne peuvent pas utiliser schema.rb

Le suivant résout à la fois monkey-patch la question de l'index FULLTEXT et option de moteur DB pour votre schéma dumper (Rails 3.2). Vous pouvez le mettre dans config/initializers/ (par exemple 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top