我最近開始維護幾個帶有 PostgreSQL 后端的 Rails 5.2 應用程式。我是 Rails 的新手,但我在各種 Microsoft 平臺上有相當多的經驗。
我正在嘗試向現有模型添加 API 呼叫。當我嘗試創建一個新實體時,我沒有取回資料庫生成的 ID:
POST /invoices
{ "amount": 12.34 }
Invoice Create (4.0ms)
INSERT INTO "invoices" ("amount", "created_at", "updated_at")
VALUES ($1, $2, $3)
[["amount", 12.34], ["created_at", "..."], ["updated_at", "..."]]
201 Created
{ "id": null, "amount": 12.34 }
檢查資料庫,新行存在,具有唯一 ID。
同一應用程式中的不同模型生成不同的 SQL 并按預期作業:
POST /customer
{ "name": "ACME" }
Customer Create (1.4ms)
INSERT INTO "customers" ("name", "created_at", "updated_at")
VALUES ($1, $2, $3)
** RETURNING "id" **
[["name", "ACME"], ["created_at", "..."], ["updated_at", "..."]]
201 Created
{ "id": 111, "name": "ACME" }
我看不出解釋這種行為的兩個模型有什么不同。我已經檢查了所有我能想到的:
- 路線(通過:資源)
- 控制器
- 過濾器前/后
- 強引數
- 輸入代碼
create
- 模型
- 都不包含任何代碼
- 模式
- 列定義在 schema.rb 和 information_schema.columns 中具有可比性
這是行為不端型別的模型和控制器:
class Invoice < ActiveRecord::Base
end
class InvoiceController < ApplicationController
def create
invoice = Invoice.new(invoice_params)
if invoice.save
# invoice.id.nil? => true
render json: invoice, status: :created
end
end
def invoice_params
params.permit(:amount)
end
end
# schema.rb
create_table "invoices", id: false, force: :cascade do |t|
t.serial "id", null: false
t.float "amount"
t.datetime "created_at"
t.datetime "updated_at"
end
And the one that works as expected:
class Customer < ActiveRecord::Base
end
class CustomerController < ApplicationController
def create
customer = Customer.new(customer_params)
if customer.save
# customer.id.nil? => false
render json: customer, status: :created
end
end
def customer_params
params.permit(:name)
end
end
# schema.rb
create_table "customers", id: :serial, force: :cascade do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
Replacing new/save with create or create! doesn't change the behavior, so I'm convinced that the problem is somewhere in the model definition or metadata.
Creating the models from rails console has the same result as shown below:
irb(main):001:0> Invoice.create(amount:12.34)
(0.8ms) BEGIN
Invoice Create (1.1ms) INSERT INTO "invoices" ("amount", "created_at", "updated_at") VALUES ($1, $2, $3) [["amount", 12.34], ["created_at", "2021-11-19 09:10:33.490117"], ["updated_at", "2021-11-19 09:10:33.490117"]]
(5.8ms) COMMIT
=> #<Invoice id: nil, amount: 12.34, created_at: "2021-11-19 09:10:33", updated_at: "2021-11-19 09:10:33">
irb(main):002:0> Customer.create(name: "ACME")
(0.9ms) BEGIN
Customer Create (1.5ms) INSERT INTO "customers" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["name", "ACME"], ["created_at", "2021-11-19 09:12:50.492927"], ["updated_at", "2021-11-19 09:12:50.492927"]]
(13.3ms) COMMIT
=> #<Customer id: 24, name: "ACME", created_at: "2021-11-19 09:12:50", updated_at: "2021-11-19 09:12:50">
Can anyone point me in the right direction?
uj5u.com熱心網友回復:
不同之處在于您明確地將“id”宣告為一列,并禁用了默認的主鍵“id”宣告/處理。
如果您更改為:
create_table "invoices", id: :serial, force: :cascade do |t|
t.float "amount"
# These are normally created automatically so not sure why they are here
# t.datetime "created_at"
# t.datetime "updated_at"
end
它應該作業。
這個答案也可能有幫助:https : //stackoverflow.com/a/54694863/224837
uj5u.com熱心網友回復:
這是由相關表上缺少主鍵引起的。看起來這些表可能是在專案早期的某個時候手動創建的,并且直到現在才由外部 SQL 腳本寫入。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/364626.html
標籤:ruby-on-rails postgresql activerecord
