19

Customer通常の主キーとカスタムの「顧客番号」を格納するための別の列を持つ「」モデルが必要です。さらに、データベースでデフォルトの顧客番号を処理する必要があります。シーケンスを定義することがそれを行うための最良の方法だと思います。私はPostgreSQLを使用しています。私の移行を見てください:

class CreateAccountsCustomers < ActiveRecord::Migration
  def up

    say "Creating sequenze for customer number starting at 1002"
    execute 'CREATE SEQUENCE customer_no_seq START 1002;'

    create_table :accounts_customers do |t|
      t.string :type
      t.integer :customer_no, :unique => true
      t.integer :salutation, :limit => 1
      t.string :cp_name_1
      t.string :cp_name_2
      t.string :cp_name_3
      t.string :cp_name_4
      t.string :name_first, :limit => 55
      t.string :name_last, :limit => 55
      t.timestamps
    end

    say "Adding NEXTVAL('customer_no_seq') to column cust_id"
    execute "ALTER TABLE accounts_customers ALTER COLUMN customer_no SET DEFAULT NEXTVAL('customer_no_seq');"

  end

  def down
    drop_table :accounts_customers
    execute 'DROP SEQUENCE IF EXISTS customer_no_seq;'
  end

end

シーケンスを追加するためのより良い「レールのような」アプローチを知っているなら、私に知らせてください。

今、私が次のようなことをすると

cust = Accounts::Customer.new
cust.save

フィールドcustomer_noには、シーケンスの次の値(1002である必要があります)が事前に入力されていません。

シーケンスを統合する良い方法を知っていますか?または、良いプラグインはありますか?すべての答えに乾杯!

4

4 に答える 4

13

カスタムシーケンスを処理するためのより「レールの方法」についての提案はありませんが、保存後にcustomer_noフィールドに値が入力されていないように見える理由はわかります。

ActiveRecordが新しいレコードを保存するとき、SQLステートメントは新しいレコードのIDのみを返し、そのすべてのフィールドは返しません。これが現在のRailsソースのどこで発生するかはhttps://github.com/rails/rails/で確認できます。 blob / cf013a62686b5156336d57d57cb12e9e17b5d462 / activerecord / lib / active_record / persistence.rb#L313

値を確認するには、オブジェクトをリロードする必要があります...

cust = Accounts::Customer.new
cust.save
cust.reload

常にこれを実行したい場合は、モデルクラスにafter_createフックを追加することを検討してください...

class Accounts::Customer < ActiveRecord::Base
  after_create :reload
end
于 2011-09-30T07:30:02.297 に答える
3

ロボレスの答えは正しくないと思います。

私は自分のアプリケーションにこれを実装しようとしました (まったく同じ環境: RoR+PostgreSQL) save。RoR で空の属性を持つオブジェクトを発行すると、データベースで INSERT を実行しようとすることがわかりました。 NULL に設定されます。問題は、PostgreSQL が NULL を処理する方法です。この場合、新しい行が作成されますが、すべての値が空になります。つまり、DEFAULT は無視されます。saveRoR に入力された INSERT ステートメントの属性のみを記述した場合、これは正常に機能します。

つまり、上記のtypeand属性のみに注目すると、これが PostgreSQL の動作です。customer_no

状況 1:

INSERT INTO accounts_customers (type, customer_no) VALUES (NULL, NULL);

(これがRailsのsave仕組みです)

type結果: 空と空の新しい行customer_no

状況 2:

INSERT INTO accounts_customers (type) VALUES (NULL);

type結果: 空で、シーケンスの NEXTVALでcustomer_no満たされた新しい行

私はこれについて進行中のスレッドを持っています。それをチェックしてください:

Ruby on Rails+PostgreSQL: カスタム シーケンスの使用

于 2011-10-19T15:46:18.157 に答える
2

PostgreSQLを使用している場合は、私が書いたgem、pg_sequencerを確認してください。

https://github.com/code42/pg_sequencer

ActiveRecordの移行でシーケンスを作成、削除、変更するためのDSLを提供します。

于 2012-08-03T15:54:01.677 に答える
2

私も同様の問題に直面し:null => falseましたが、フィールド ホッピングを適用して、nextval が自動入力されるようにしました。

私の場合NULL、リクエストで属性が指定されていない場合でも、AR はまだ挿入しようとしていたため、null でない制約違反の例外が発生しました。

これが私の回避策です。この属性キーを@attributesandから削除したところ@changed_attributes、この場合、postgres は予想されるシーケンス nextval を正しく配置しました。

これをモデルに入れました:

before_save do
  if (@attributes["customer_no"].nil? || @attributes["customer_no"].to_i == 0)
    @attributes.delete("customer_no")
    @changed_attributes.delete("customer_no")
  end
end

Rails 3.2 / Postgres 9.1

于 2012-05-24T13:56:39.300 に答える