Rails 不返回特定模型的生成 ID

Posted

技术标签:

【中文标题】Rails 不返回特定模型的生成 ID【英文标题】:Rails not returning generated ID for specific model 【发布时间】: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 替换为createcreate! 不会改变行为,因此我确信问题出在模型定义或元数据的某个地方。

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:如上图。 【参考方案1】:

不同之处在于您将“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://***.com/a/54694863/224837

【讨论】:

【参考方案2】:

这是由于相关表中缺少主键造成的。看起来这些表可能是在项目早期的某个时候手动创建的,并且直到现在才被外部 SQL 脚本写入。

【讨论】:

以上是关于Rails 不返回特定模型的生成 ID的主要内容,如果未能解决你的问题,请参考以下文章

不返回数组 - Rails 模型函数

Ruby On Rails 5,activerecord query其中模型关联id包括数组中的所有id

Rails:friendly_id 和 to_json

rake 不返回任何东西

CodeIgniter 模型无法返回特定记录

如何在 Rails 中缓存模型对象?