Rails调用含嵌套数据的API执行db:seed报错TypeError: String无法隐式转为Integer
错误原因
你遇到的报错有三个核心诱因:
- 接口返回结构解析错误:你调用的接口返回的外层不是直接的数组,而是包裹了
data字段的对象,结构为{"data": [quote1, quote2...]}。你直接将JSON解析后的哈希对象当做数组调用each迭代,迭代时拿到的question实际是哈希的键(字符串类型),调用question["id"]相当于尝试用字符串作为索引访问字符串,触发了类型转换错误。 - 字段类型不匹配:你数据库中
character字段是字符串类型,但是API返回的character是嵌套哈希结构,直接赋值给字符串字段无法正常存储,也会触发类型错误。 - 字段名匹配错误:API返回的唯一标识字段是下划线开头的
_id,不是你代码里写的id,取值会为空。
解决方案
步骤1:选择字段存储方案(二选一)
方案A:仅存储完整姓名(适合只需要展示姓名的场景)
不需要修改现有表结构,直接在种子文件中把嵌套哈希拼接为全名字符串即可。
方案B:存储完整character结构(适合需要前端单独获取firstname、lastname的场景)
生成新的迁移文件修改字段类型为jsonb(PostgreSQL原生支持,性能更优):
class ChangeCharacterToBeJsonInQuestions < ActiveRecord::Migration[6.1] def change change_column :questions, :character, :jsonb, default: {} end end
执行迁移命令:rails db:migrate
步骤2:修改种子文件代码
require 'rest-client' resp = RestClient::Request.execute(method: :get, url: "https://officeapi.dev/api/quotes/", headers:{ 'Content-Type': 'application/json' }) resp_hash = JSON.parse(resp) # 取外层data字段拿到实际的quote数组 resp_array = resp_hash["data"] resp_array.each do |question| # 方案A用这段代码拼接姓名 # character_val = "#{question.dig('character', 'firstname')} #{question.dig('character', 'lastname')}" # 方案B用这段代码直接取完整嵌套哈希 character_val = question["character"] Question.create( # 注意API主键是下划线开头的_id id: question["_id"], content: question["content"], character: character_val ) end
如果你不需要和第三方API的ID保持一致,可以删除id: question["_id"]这行,让Rails自动生成自增主键,避免ID冲突问题。
步骤3:可选调整控制器返回
如果选择方案B存储JSON结构,控制器无需修改即可返回完整的character嵌套结构,前端可以直接读取character.firstname、character.lastname使用。
内容的提问来源于stack exchange,提问作者Kiana
相关产品推荐
相关产品推荐

