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

在Rails与Stimulus中读取JSON文件的最优方案咨询

问题分析与最优实现方案

一、前端fetch失败的原因

Rails里db目录是后端数据库专用目录,不会对外开放给前端访问。前端静态资源默认存放在app/assets或public文件夹下,所以直接请求/db/data.json必然会报404错误。

二、当前方案的隐患

你现在把整个JSON对象通过data-value传给Stimulus,存在两个明显问题:

  • 若JSON数据量大,会直接撑大HTML页面体积,导致加载变慢,甚至可能超出浏览器对属性值的长度限制。
  • 所有数据直接暴露在HTML源码中,若包含敏感信息会直接泄露。

三、最优实现方式

推荐采用后端API接口+前端动态请求的模式,既安全又高效:

1. 后端新增API接口

修改MainController,添加专门返回JSON数据的action:

class MainController < ApplicationController
  def index
    # 无需再读取JSON到@itemsJSON
  end

  # 新增接口:返回过滤后的数据
  def items_data
    # 用Rails.root拼接路径,避免不同环境下路径错误
    items = JSON.parse(File.read(Rails.root.join('db', 'data.json')))
    
    # 根据前端传入的type参数过滤数据
    if params[:type].present? && params[:type] != 'all'
      items = items.select { |item| item['type'] == params[:type] }
    end

    # 返回JSON格式响应
    render json: items
  end
end

然后在config/routes.rb中配置路由:

Rails.application.routes.draw do
  get 'main/index'
  # 为新增接口配置路由
  get 'main/items_data', to: 'main#items_data'
end

2. 修改视图代码

移除data-value传递整个JSON的逻辑,仅保留Stimulus控制器与动作绑定:

<%= form_with url: main_index_path, method: :get, local: true do |form| %>
  <%= form.select :type, [['全部', 'all'], ['严重', 'critical'],['错误','error'],['警告','warning'],['信息','info'],['调试','debug']], 
        { prompt: "选择数据类型" },
        data: { controller: "dropdown-table", action: "change->dropdown-table#fetchFilteredData"} %>
<% end %>

注意:Stimulus控制器名推荐使用短横线分隔的kebab-case格式,之前的驼峰命名可能存在兼容性问题。

3. 调整Stimulus控制器

实现下拉切换时请求API并渲染表格:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  fetchFilteredData(event) {
    const selectedType = event.target.value;
    // 请求后端API,携带选中的类型参数
    fetch(`/main/items_data?type=${selectedType}`)
      .then(response => {
        if (!response.ok) throw new Error('数据加载失败');
        return response.json();
      })
      .then(data => {
        // 调用表格渲染方法
        this.renderTable(data);
      })
      .catch(error => console.error('出错了:', error));
  }

  renderTable(data) {
    // 假设表格id为data-table,可根据实际结构调整
    const tableBody = document.querySelector('#data-table tbody');
    // 清空旧数据
    tableBody.innerHTML = '';
    // 遍历数据生成表格行
    data.forEach(item => {
      const row = document.createElement('tr');
      // 根据你的JSON字段结构调整单元格内容
      row.innerHTML = `
        <td>${item.name}</td>
        <td>${item.type}</td>
        <td>${item.description}</td>
      `;
      tableBody.appendChild(row);
    });
  }
}

4. 小数据场景的备选方案

如果JSON数据量极小且无敏感信息,也可在页面初始化时将数据注入全局变量:

<script>
  window.itemsData = <%= raw @itemsJSON.to_json %>;
</script>

之后在Stimulus中直接使用window.itemsData处理,但这种方式仅适合数据量极小的场景,不推荐大规模使用。

总结

  • fetch失败是因为db目录不属于前端可访问的静态资源目录,前端只能访问public或app/assets下的文件。
  • 大/敏感数据优先选择后端API接口方案,既能在后端做数据过滤与权限控制,又能避免HTML体积过大。
  • 小数据可考虑页面注入模式,但需注意数据安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:10:25