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

Rails 7控制器无法识别format.json请求求助

Rails 7 + Stimulus表格无数据:JSON请求未触发问题

我用Rails 7和Ruby 3.2.1开发应用,写了个OrderItemsController给Stimulus控制器提供数据,数据通过::DtfsOrders::OrderItemSerializer序列化后用于AgGrid表格展示,但表格完全没内容。我怀疑控制器有问题——在format.json块里加了binding.pry但程序根本没暂停,说明JSON请求根本没被识别到。

我的OrderItemsController代码

class OrderItemsController < ApplicationController
  def index # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
    skip_policy_scope
    authorize(:order_item, :index?)

    @order_items_params = params.permit(:page).merge(limit: OrderItems::ListComponent::LIMIT)

    respond_to do |format|
      format.html do
        @order_item_list = fetch_order_items(@order_items_params.merge(limit: 1).to_h)
      end
      format.json do
        render json: fetch_order_items(@order_items_params.to_h)
          .serialize(::DtfsOrders::OrderItemSerializer, scope: view_context)
          .as_json
      end
    end
  rescue ::DtfsOrders::Error => e
    redirect_to root_path, alert: api_error_message(e)
  end

  private

  def api_error_message(error) = I18n.t('api_error', error: error.message, scope: 'order_items')
  def fetch_order_items(params) = FactoryBot.build(:dtfs_orders_order_item_list, :with_next_page, total_count: 1)

  def client = @client ||= ::DtfsOrders::Client.with_account(current_account)
end

路由配置(routes.rb)

Rails.application.routes.draw do
  mount Rswag::Api::Engine => '/api-docs'
  mount Rswag::Ui::Engine => '/api-docs'
  mount Core::Engine, at: '/'

  resources :order_items, only: %i[index]
end

补充:Stimulus控制器代码

import { Controller } from 'stimulus';
import Rails from '@rails/ujs';

import * as AgGrid from 'ag-grid-community';

import {
  DEFAULT_GRID_OPTIONS,
  buildColumnDefs,
  GridDatasource,
  updateColumnPositionsInCookies,
} from 'core/utils/grid';

const columnOptions = {
  columnDefs: {
    order_reference: { cellClass: 'font-mono', cellRenderer: 'flexCellRenderer', sortable: false },
    order_date: { cellClass: 'font-mono', maxWidth: 300, sortable: false },
    description: { cellClass: 'font-mono', maxWidth: 300, sortable: false },
    quantity: { cellClass: 'font-mono', maxWidth: 300, sortable: false },
    amount: {
      cellClass: 'ag-right-aligned-cell font-mono', maxWidth: 200, sortable: false,
      headerClass: 'ag-header-cell ag-header-cell-sortable text-xs font-medium text-gray-500 uppercase bg-gray-100'
                   + ' ag-focus-managed ag-right-aligned-header' },
    currency: { cellClass: 'font-mono', maxWidth: 100, sortable: false },
    vat: { cellClass: 'font-mono', maxWidth: 100, sortable: false },
    actions: { cellClass: 'ag-right-aligned-cell font-mono', maxWidth: 120, sortable: false, withoutHeader: true },
  },
  cookiesName: 'order_items_columns_positions',
  defaultSorting: [
    'order_reference',
    'order_date',
    'amount',
    'quantity',
    'currency',
    'vat',
    'description',
    'actions'
  ],
};

function buildGrid(gridElement) {
  console.log('Building grid with element:', gridElement);

  const {indexUrl, paginationPageSize, i18nJson} = gridElement.dataset;

  console.log('indexUrl:', indexUrl);
  console.log('paginationPageSize:', paginationPageSize);
  console.log('i18nJson:', i18nJson);

  const options = {
    ...DEFAULT_GRID_OPTIONS,
    cacheBlockSize: paginationPageSize,
    maxConcurrentDatasourceRequests: 2,
    columnDefs: buildColumnDefs(columnOptions, i18nJson),
    datasource: new GridDatasource({ indexUrl }),
    onColumnMoved(params) { updateColumnPositionsInCookies(columnOptions, params) },
  };

  console.log('Options:', options);

  return new AgGrid.Grid(gridElement, options);
}

export default class extends Controller {
  connect() {
    const gridElement = this.element.querySelector('#order_itemsGrid');

    if (gridElement) {
      this.gridObject = buildGrid(gridElement)
    }
  }

  disconnect() {
    if (this.gridObject) {
      this.gridObject.destroy();
    }
  }
}

可能的问题点及解决建议

  • 请求格式不匹配:Stimulus的GridDatasource可能没设置正确的请求头,导致Rails默认返回HTML而非JSON。可以在indexUrl后加上.json后缀(比如/order_items.json),或者检查GridDatasource的请求逻辑,确保带上Accept: application/json头。
  • 路由被覆盖:你挂载了Core::Engine在根路径,该引擎可能定义了同名路由,覆盖了你的order_items路由。执行rails routes命令查看实际生效的路由,确认order_items#index的JSON路由是否存在。
  • 权限验证未捕获错误:authorize(:order_item, :index?)触发的权限错误(比如Pundit的NotAuthorizedError)不在你的rescue捕获范围内,会直接中断请求,导致无法进入JSON响应块。可以暂时注释权限代码测试,或者添加对应的rescue逻辑。
  • 测试数据序列化问题:fetch_order_items返回的FactoryBot测试对象,其serialize方法可能没有生成符合要求的JSON结构。在Rails控制台手动调用fetch_order_items({}).serialize(::DtfsOrders::OrderItemSerializer, scope: view_context).as_json,查看输出是否包含表格所需字段。
  • AgGrid数据源解析问题:检查GridDatasource的实现,确认它能正确处理后端返回的JSON格式,比如是否期望数据包含items和total_count这类顶层字段,而你的序列化输出不符合该结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:05:10