2009-04-15 5 views
24

したがって、StateとAcquisitionという2つのモデルがあります。州has_many買収。私は、51レコードのオートインクリメント整数プライマリキーがかなりばかげているように感じました。だから私は、国が2文字の略語であること(PKように国家のためのモデルを変更し、私はどこでも、実際の状態名を格納していないよ:Railsの主キーを文字列に変更する

class State < ActiveRecord::Base 
    self.primary_key = "state" 
    has_many :acquisition_histories 
end 

問題は、私は私の取得モデルを作成したとき、それが作成されています。外部キー列が整数としてSTATE_ID具体的には、スクリプト生成/移行がやった:。

class CreateAcquisitions < ActiveRecord::Migration 
    def self.up 
    create_table :acquisitions do |t| 
     t.date :date 
     t.string :category 
     t.text :notes 
     t.references :state 
     t.timestamps 
    end 
    end 
end 

私はこの問題は私の私の取得にメソッドを作成していることが、データ型はintにそれを設定しますt.referencesと仮定していますクラスは、テーブル取得のstate_idフィールドに状態の省略形を入れようとしています(そして、そうです、それはs ays:移行スクリプト内の状態)。メソッドは失敗しませんが、state_idフィールドに0を入れ、レコードはetherに入ります。

答えて

-15

デフォルトと競合しないときは、Railsが最適です。あなたの状態テーブルに整数の主キーを持たせるのはどのような害を及ぼしますか?

あなたがコントロールできないレガシーなスキーマに悩まされているのでなければ、Railsのデフォルトの設定よりも—の規則に固執することをお勧めします。 —、UIやビジネスロジックなど、アプリの重要な部分に集中してください。

+0

コードを取得するために状態テーブルを保存しなければならない場合は、(おそらくメモリキャッシュされた、小さな)データベースオーバーヘッドがあります。しかし、おそらく過最適化です。私はそれをしますが、私は年をとっており、VAX 8700日ではもっと重要でした。 –

+2

そのようなことについては、ステートクラス、つまりALL = State.allで定数を定義して、State :: ALLをドロップダウンなどのソースとして使用する傾向があります。そのようにSQLクエリはProductionの起動時にのみ実行されます。 –

+1

私はパフォーマンスについてまったく心配していません。余分な一意の識別子の概念が嫌いです。しかし、私はすべてを取り戻す方法を理解できると仮定して、大会に戻ります。私はRailsにはかなり新しいです。 – fr0man

2

あなたは、Railsの規則に従いたいと思っています。余分な主キーは決して問題ではありません。ちょうどそれを使用します。

+6

保管コスト(明らか)。 計算コスト(クラスタリング+自動インクリメントIDは必ずしも良好ではありません)。 複雑さのコスト(スキーマは、本当にそこに存在する必要があるものよりもノイズがある場合は混乱します)。 UUIDをプライマリキーとして使用すると、後でセントラルDBとデータを関連付ける必要があるオフラインアプリケーションでは非常に意味があります) – sethcall

1

私は主キーとして使用される文字列で少し経験があり、***には苦痛があります。デフォルトでは:controller /:action /:idパターンでオブジェクトを渡したい場合は、:idは文字列になりますが、いくつかのidが奇妙にフォーマットされるとルーティングの問題が発生する可能性があります)

6

私は主キーとしてUUIDを使用するプロジェクトに取り組んでいます。正直なところ、絶対に必要としない限り、推奨しません。文字列を主キーとして使用するデータベースでは修正されていない大量のRailsプラグインがあります。

は、状態の移行を作成します。

1
class CreateAcquisitions < ActiveRecord::Migration 
    def self.up 
     create_table :acquisitions, :id => false do |t| 
      t.date :date 
      t.string :category 
      t.text :notes 
      t.references :state 
      t.timestamps 
     end 
    end 
end 
35

けれども、私はあなたが実際はあなたが求めてきました何をやりたいだけの場合には、これは他の場所でデフォルト不利に働いの余分な労力を考慮しmore trouble than it's worthをかもしれないことに同意します:

class CreateStatesTable < ActiveRecord::Migration 
    def change 
    create_table :states, id: false do |t| 
     t.string :state, limit: 2 
     t.string :name 
     t.index :state, unique: true 
    end 
    end 
end 

状態モデル:

class State < ActiveRecord::Base 
    self.primary_key = :state 
end 
のRails 3.2の前に、これは set_primary_key = :state代わりの self.primary_key=を参照したこと

注:ここで自分自身を見つける場合http://guides.rubyonrails.org/3_2_release_notes.html#active-record-deprecations

2

mkirk's answerが作成しますフェーズの主キー。 ActiveRecordにプライマリキーの内容を伝える必要がある理由を説明します。テーブルの検査が明らかになった

  Table "public.acquisitions" 
Column |   Type   | Modifiers 
--------+----------------------+----------- 
state | character varying(2) | 
name | character varying | 
Indexes: 
    "index_acquisitions_on_state" UNIQUE, btree (state) 

実際にはこれは期待どおりに機能しますが、問題はありませんが、それは良いかもしれません。


我々は* id列を維持し、stringにそのタイプを変更することができます。移行がテーブルを点検

class CreateAcquisitionsTable < ActiveRecord::Migration 
    def change 
    create_table :acquisitions do |t| 
     t.string :name 
    end 
    change_column :acquisitions, :id, :string, limit: 2 
    end 
end 

のように見えることはあなたがそのようなユニークキー制約(一意のインデックスは必要ありません)、NOT NULL制約、および自動インクリメントのキーなど、すべてのグッズで、実際の主キーを持っていることが明らかになりました。

       Table "public.acquisitions" 
Column |   Type   |      Modifiers 
--------+----------------------+--------------------------------------------------- 
id  | character varying(2) | not null default nextval('acquisitions_id_seq'::regclass) 
name | character varying | 
Indexes: 
    "acquisitions_pkey" PRIMARY KEY, btree (id) 

そしてあなたは明示的に主が何であるかのActiveRecordを伝える必要がありません。

何も指定されていない場合は、デフォルトのIDを設定することを検討してください。

class MyModel < ActiveRecord::Base 
    before_create do 
    self.id = SecureRandom.uuid unless self.id 
    end 
end 

*免責事項:あなたはRailsの5.1に

+1

schema.rbファイルで何が生成されたか確認しましたか?これを試してみると、移行は機能しましたが、スキーマには「文字列」変換が含まれていなかったため、列の種類が異なるために外部キー索引が失敗しました。 – Andreas

1

に正当な理由がない限り、あなたは作成時に主キーのタイプを指定することができ、デフォルトのプライマリキーを変更しないでください。

create_table :states, id: :string do |t| 
# ... 
end 

the documentationから:

シンボルできます生成された主キー列のタイプを指定するために使用されます。

関連する問題