2011-06-29 3 views
3

increment_counterを使用していくつかの整数列をインクリメントしていくつかのレコードIDを渡し、次にModel.firstを使用して最初のレコードを取得しようとすると、レコードIDに1を返します。postgreSQLの奇妙な振る舞いを使用してカウンタとレールを最初にインクリメント

このような

何か:

Model.increment_counter :field, id 
Model.first 

それは

Model.find(1) 

しかし

ない返します
Model.find(id+1) 

これはpostgreSQLの特有の問題ですか?

答えて

6

Model.firstは、データベースのデフォルトのソート(ではなく、が必ずIDです)を使用します。

代わりにこれを試してみてください:

Model.order("id").first 
+0

これは私に問題ありません。私は、なぜpostgreSQLのデフォルトソートがidではないのか理解したいだけです。デフォルトのpostgreソートはどれですか? –

+6

PostgreSQLのドキュメント「ソートが選択されていない場合、行は不特定の順序で返されます。私は実際には彼らが作成された順序で返されると思います(IDではなく、IDを変更しない場合は通常同じです)。したがって、あなたがIDでソートされていることを確認する必要があるときはいつでも、 'order(" id ")'を呼び出す必要があります。 –

+1

実際には、ライブ行がディスク上に表示される順序です。フィルファクタはそれにも大きな影響を与えることができます。 –

0

をあなたは、ActiveRecordのにパッチを適用するいくつかのサルを行う

#lib/postgresql_extras.rb 

module ActiveRecord 
    class Base 
    def self.first_by_id 
     order(:id).first 
    end 
    def self.all_by_id 
     order(:id) 
    end 
    end 
end 

し、このものを呼び出すことはありませんいくつかの初期化子

#config/initializer/extensions.rb 

require "postgresql_extras" 

でこれを必要とすることができます最初およびすべてこれは、User.order(:email).limit(1)などの他のクエリーでエラーを生成する原因になります。この場合、User.order(:email)と異なります。 、 私はまだposgresqlに問題のある他のメソッドを見つけられませんでした。テーブルのpkeyを変更して修正しようとしましたが、そこには運がありません。