2009-02-05 8 views
8

Ich habe eine DB-Migration wie so:id-Feld ohne Autoinkrement Option in der Migration

class CreateParticipations < ActiveRecord::Migration 
     def self.up 
     create_table(:participations, :primary_key => 'Seat') do |t|  
      t.integer :Seat 
      t.string :Nickname 
      t.string :Clan 
      t.string :FirstName 
      t.string :LastName 
      t.string :Email 
      t.boolean :Payed 

      t.timestamps 
     end 
     end 

     def self.down 
     drop_table :participations 
     end 
    end 

Nun Sitz ist mit einem Autoinkrement erstellt. Das will ich aber nicht. Ich möchte es ohne eine automatische Erhöhung. Ich werde Seat selbst in meiner Logik definieren.

Ich habe mich umgesehen, aber ich kann nicht finden, wie Auto_increment zu deaktivieren.

Wie mache ich das? Außer dass es manuell in MySQL gemacht wird.

+0

Bist du wirklich sicher, dass du das machen willst? Es widerspricht der Konvention, die sehr gut in allen Rails funktioniert und Ihnen im Rest Ihrer Anwendung viel zusätzliche Arbeit verursachen wird, die diese Ausnahme von der Regel überall funktionieren lässt. Vielleicht "Sitz" in nur einem Feld auf diesem Tisch mit einem eindeutigen Index statt. Sofern Sie dies nicht benötigen, um sich an ein herkömmliches Legacy-Schema anzupassen, ist dies normalerweise eine schlechte Idee. Leider weiß ich nicht die tatsächliche Antwort auf Ihre Frage. –

+0

Ich weiß, dass hier die Toten animiert werden, aber ein relativ triviales Beispiel könnte ein Modell sein, das an einen Nicht-Rails-Service gebunden ist, der IDs in diesem Service verwaltet. In Rails wäre keine automatische Inkrementierung erforderlich, da es am sinnvollsten wäre, die Rails-Repräsentation mit der ID der Nicht-Rails-Service-Repräsentation zu verknüpfen, anstatt eine ANDERE ID zu generieren und ANDERE Constraints zu verwalten. Ohne weitere Details über die Notwendigkeit in den ursprünglichen Umständen des Fragestellers, würde ich im Allgemeinen mit Ihnen übereinstimmen. –

Antwort

1

Gibt es einen Grund, warum Sie den ID-Schlüssel von rails nicht verwenden können und manuell einen Index namens Seat hinzufügen?

Ich habe einige Hacks gesehen, nur um Rails zu bekommen, um auf Nicht-Inkrement-PK-Datenbanken zu arbeiten. Ich denke nicht, dass es eine Option ist. Wenn ich mich erinnere, greift rails so auf alle seine Funktionen pro Zeile zu.

Ehrlich, wie - absolut - brauchen Sie die leichte Steigerung der Effizienz der Ignorierung der Schienen Struktur?

Ich denke, die wahre Antwort ist "Sie können nicht." Activetrecord hat ein paar Dinge, an die es sich nicht anschmiegt.

+0

Ich portiere eine ASP.MVC-Anwendung, wo ich meine BLL und DAL-eigene Logik hatte, aber es macht jetzt Sinn – IceHeat

17

Für das Protokoll, wenn Sie unbedingt das tun müssen, (es ist nicht oft passieren soll), dann ist hier die Möglichkeit, einen nicht-selbstinkrementierende Primärschlüssel mit der Rails Migration DSL zu tun:

create_table(:table_name, :id => false) do |t| 
    t.integer :id, :options => 'PRIMARY KEY' 
end 

Das wird Arbeitet sowieso für MySQL, wenn Ihre Datenbank eine andere Syntax verwendet, um einen Primärschlüssel anzugeben, ersetzen Sie die :options => 'PRIMARY KEY' durch was auch immer das ist.

+1

Beachten Sie, dass dies noch einige Probleme hat, weil Rails die Namens-ID ein bisschen magisch behandelt. Während es Benennungskonventionen durchbricht, in Bezug auf das Umcodieren von Dingen, ist es wahrscheinlich vorzuziehen, das Primärschlüsselfeld etwas anderes als ID zu nennen. –

+1

Wenn ich es zu etwas anderem nenne, müsste ich meine route.rb ändern, Cancan 'load_resource' und so weiter? Danke ~ – lulalala

2

Diese Frage ist 3 Jahre alt, aber incase jemand fragt, 3 Jahre später, wie ich war, alles, was Sie tun, ist „change_column“ im Falle der Tabelle bereits erstellt:

change_column(:table_name, :id, :integer, :null => false) 

Dies sollte funktionieren in Rails 2.x und 3.x.

O

0

sein nicht eine gute Idee zu sagen, aber hier ist, wie ich es für SQLite3 tat - ersetzen Sie einfach, dass SQLiteAdapter mit Adapter Ihre DB - Sie könnten diese Reiniger tun/kurz mit einem Aufruf

class AbstractAdapter 
end 

module ActiveRecord 
    module ConnectionAdapters 
    class SQLiteAdapter < AbstractAdapter 
     def supports_autoincrement? 
     false 
     end 
    end 
    end 
end 

<then you migration> 
define_method

oder

class SomeMigration < ActiveRecord::Migration 
    def change 
    create_table :table do |t| 
     ActiveRecord::ConnectionAdapters::SQLiteAdapter.send :define_method, :supports_autoincrement? do false end 
     t.integer etc 
    end 
    end 
end 

natürlich ändern Sie einfach den Adapter für andere DBs