【发布时间】:2021-12-29 20:19:06
【问题描述】:
我最近开始维护几个带有 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" }
我看不出解释这种行为的两个模型有什么不同。我已经检查了我能想到的所有内容:
- 路线(通过 :resources)
- 控制器
- 过滤器之前/之后
- 强大的参数
- 代码在
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
还有一个按预期工作的:
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
将new/save 替换为create 或create! 不会改变行为,因此我确信问题出在模型定义或元数据的某个地方。
从rails console 创建模型的结果相同,如下所示:
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">
谁能指出我正确的方向?
【问题讨论】:
-
你需要发布模型代码,其中必须有代码,即使只是一个类声明,也请控制器动作
-
感谢@jamesc,我已经更新了帖子。我应该说模型只包含类声明:)
-
你有哪些 JSON 模板?在视图文件夹中
-
如果您只想要模型中的原始 jsin,那么您的操作可以返回对象 to_json 但您可能正在模板中格式化响应,这 8s 通常在 response_to 块中返回
-
现在,这些模型的视图文件夹中什么都没有。原来有一个show.json.builder 没有包含id,但是添加后并没有解决问题,所以我改成
render json:如上图。
标签: ruby-on-rails postgresql activerecord