You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails新手求助:从URL读取JSON并创建数据库记录

Ruby on Rails 从远程API自动创建Product记录方案

1. 从远程URL读取JSON数据(Controller & View 实现)

Controller层实现(推荐)

在Controller中封装数据获取逻辑,符合MVC原则,避免View层处理复杂业务:

# app/controllers/products_controller.rb
class ProductsController < ApplicationController
  # ... 其他CRUD方法 ...

  def create
    # 后续会在这部分调用数据获取方法
  end

  private

  # 封装远程JSON数据获取方法
  def fetch_product_data(url)
    uri = URI(url)
    response = Net::HTTP.get_response(uri)
    
    # 检查请求是否成功
    unless response.is_a?(Net::HTTPSuccess)
      raise "API请求失败,状态码: #{response.code}"
    end

    # 使用ActiveSupport::JSON解析响应,和标准库JSON.parse功能一致,兼容Rails类型
    ActiveSupport::JSON.decode(response.body)
  end
end

View层实现(不推荐,仅作演示)

不建议在View中直接发起HTTP请求(会拖慢页面、违反MVC设计),如果仅用于临时测试:

<!-- app/views/products/test.html.erb -->
<% require 'net/http' %>
<% url = 'http://world.openfoodfacts.org/api/v0/product/3661112054465.json' %>
<% response = Net::HTTP.get(URI(url)) %>
<% product_data = JSON.parse(response)['product'] %>

<h3>产品信息</h3>
<p>名称:<%= product_data['product_name'] %></p>
<p>图片:<%= image_tag product_data['image_url'] if product_data['image_url'] %></p>

2. 提取指定字段数据

OpenFoodFacts的API返回结构中,核心数据嵌套在product字段下,需按路径提取,同时建议添加默认值避免空值报错:

# 在fetch_product_data调用后提取字段
parsed_data = fetch_product_data('http://world.openfoodfacts.org/api/v0/product/3661112054465.json')
product_info = parsed_data['product']

product_name = product_info['product_name'] || '未命名产品'
image_url = product_info['image_url']
description = product_info['description'] || '暂无产品描述'

3. 修改Create方法实现自动创建记录

Rails的强参数(product_params)是不可修改的哈希,需重新构建符合模型要求的参数哈希,同时添加异常处理避免API请求失败导致程序崩溃:

# app/controllers/products_controller.rb
def create
  # 可通过前端提交API URL,或固定默认URL
  api_url = params[:product][:api_url] || 'http://world.openfoodfacts.org/api/v0/product/3661112054465.json'
  
  begin
    parsed_data = fetch_product_data(api_url)
    product_info = parsed_data['product']

    # 构建Product模型所需的参数哈希
    product_attributes = {
      product_name: product_info['product_name'],
      image_url: product_info['image_url'],
      description: product_info['description']
    }

    @product = Product.new(product_attributes)

    respond_to do |format|
      if @product.save
        format.html { redirect_to @product, notice: '产品创建成功。' }
        format.json { render :show, status: :created, location: @product }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  rescue StandardError => e
    # 捕获API请求、解析等异常,返回友好提示
    respond_to do |format|
      format.html { render :new, notice: "获取产品数据失败: #{e.message}" }
      format.json { render json: { error: "获取产品数据失败: #{e.message}" }, status: :bad_request }
    end
  end
end

# 保留强参数方法,若允许前端提交API URL则添加对应字段
private

def product_params
  params.require(:product).permit(:api_url)
end

额外注意事项

  • 若你的Product模型字段名与API返回字段不一致,需调整product_attributes中的键名
  • 可将fetch_product_data方法迁移至Product模型,进一步解耦Controller逻辑
  • 建议添加API请求超时设置,避免长时间阻塞请求

内容的提问来源于stack exchange,提问作者Owen Lie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:25:17