Ruby on Rails项目中Google Places API创建Restaurant对象报错求助
问题排查与修复方案
1. 解决INVALID_REQUEST错误(字段参数问题)
Google Places API的fields参数有严格的字段名规范,不存在的字段会直接返回无效请求:
- 确认你调用的是Place Details API(用于获取餐厅详情),该API允许的字段包括
name、formatted_address、website、geometry、photos等,注意字段名全小写,无拼写错误 - 若误用了Geocoding API,它不支持
fields参数,需切换到正确的Place Details端点:https://maps.googleapis.com/maps/api/place/details/json,且必须携带有效的place_id参数(不能直接传地址)
2. 解决无候选结果问题
Place Details API无法直接解析地址,必须先将地址转换为place_id:
- 使用Geocoding API将精确地址转成
place_id,示例代码:geocode_url = "https://maps.googleapis.com/maps/api/geocode/json?address=#{URI.encode(params[:restaurant][:address])}&key=#{ENV['GOOGLE_PLACES_API_KEY']}" response = HTTParty.get(geocode_url) place_id = response['results'].first['place_id'] if response['status'] == 'OK' - 确保地址格式完整(包含国家、城市等信息),若Geocoding API也返回无结果,检查地址是否准确,或API密钥是否启用了Geocoding API权限
3. 潜在问题排查与优化
3.1 API密钥与权限
- 确认Google Cloud项目已启用Places API和Geocoding API
- 检查API密钥的限制规则(如IP限制、API范围限制),避免因权限不足导致请求失败
3.2 Active Storage图片处理
从Places API获取图片需处理photo_reference字段:
- 拼接图片URL:
photo_ref = place_data['photos'].first['photo_reference'] photo_url = "https://maps.googleapis.com/maps/api/place/photo?maxwidth=800&photoreference=#{photo_ref}&key=#{ENV['GOOGLE_PLACES_API_KEY']}" - 下载并附加到Active Storage,同时处理无图片的情况:
require 'open-uri' if place_data['photos'].present? begin @restaurant.image.attach(io: URI.open(photo_url), filename: "#{@restaurant.name}_photo.jpg", content_type: 'image/jpeg') rescue => e Rails.logger.error "图片下载失败:#{e.message}" end end
3.3 错误处理
必须覆盖API返回的所有状态码,避免空指针或逻辑崩溃:
case response['status'] when 'OK' # 正常处理数据 when 'ZERO_RESULTS' flash[:alert] = "无法识别该地址" when 'OVER_QUERY_LIMIT' flash[:alert] = "API配额不足,请稍后再试" when 'REQUEST_DENIED' flash[:alert] = "API密钥无效或权限不足" else flash[:alert] = "请求失败:#{response['status']}" end
3.4 环境变量管理
不要硬编码API密钥,用dotenv-rails gem管理环境变量,通过ENV['GOOGLE_PLACES_API_KEY']调用,避免密钥泄露
完整流程示例代码
class RestaurantsController < ApplicationController def create address = params[:restaurant][:address] # 1. 地址转place_id geocode_response = HTTParty.get("https://maps.googleapis.com/maps/api/geocode/json?address=#{URI.encode(address)}&key=#{ENV['GOOGLE_PLACES_API_KEY']}") if geocode_response['status'] != 'OK' || geocode_response['results'].empty? flash[:alert] = "无法识别该地址,请检查输入" redirect_to new_restaurant_path and return end place_id = geocode_response['results'].first['place_id'] # 2. 获取餐厅详情 place_response = HTTParty.get("https://maps.googleapis.com/maps/api/place/details/json?place_id=#{place_id}&fields=name,formatted_address,website,photos&key=#{ENV['GOOGLE_PLACES_API_KEY']}") if place_response['status'] != 'OK' flash[:alert] = "获取餐厅信息失败:#{place_response['status']}" redirect_to new_restaurant_path and return end place_data = place_response['result'] # 3. 创建Restaurant实例 @restaurant = Restaurant.new( name: place_data['name'], address: place_data['formatted_address'], website: place_data['website'] ) # 4. 处理图片 if place_data['photos'].present? photo_ref = place_data['photos'].first['photo_reference'] photo_url = "https://maps.googleapis.com/maps/api/place/photo?maxwidth=800&photoreference=#{photo_ref}&key=#{ENV['GOOGLE_PLACES_API_KEY']}" begin @restaurant.image.attach(io: URI.open(photo_url), filename: "#{@restaurant.name}_main.jpg", content_type: 'image/jpeg') rescue => e Rails.logger.error "图片下载失败:#{e.message}" end end if @restaurant.save redirect_to @restaurant, notice: "餐厅创建成功" else render :new end end end
内容的提问来源于stack exchange,提问作者BrownKid
相关产品推荐
相关产品推荐

