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

Rails 7航班查询应用:解决初始加载显示全部航班问题

解决方案

1. 修正模型作用域(Scope)的返回值问题

你的filter_flights作用域存在返回值异常:当所有参数为空时,最后一行条件不执行会导致作用域返回nil而非合法的关系对象。同时,关联查询无需额外joins(departure_airport_id是Flight的直接字段),优化后的代码如下:

class Flight < ApplicationRecord
  belongs_to :departure_airport, class_name: 'Airport'
  belongs_to :arrival_airport, class_name: 'Airport'

  validates :departure_airport, :arrival_airport, :flight_date, presence: true

  scope :filter_flights, lambda { |departure_airport, arrival_airport, date, passengers|
    flights = all
    flights = flights.where(departure_airport_id: departure_airport) if departure_airport.present?
    flights = flights.where(arrival_airport_id: arrival_airport) if arrival_airport.present?
    flights = flights.where(flight_date: date) if date.present?
    flights = flights.where('available_passenger_seats >= ?', passengers) if passengers.present?
    flights # 确保始终返回ActiveRecord关系对象
  }
end

2. 调整控制器逻辑,区分初始加载与搜索请求

无需拆分index和search动作,在index中直接判断是否存在有效搜索参数即可。注意Rails控制器命名规范应为复数(FlightsController而非FlightController),并正确获取表单提交的嵌套参数:

class FlightsController < ApplicationController
  def index
    @flight = Flight.new # 初始化表单绑定的模型对象
    @flight_dates = Flight.select(:flight_date).distinct.order(:flight_date)

    # 从嵌套的flight参数中提取搜索条件(表单使用model: @flight时参数会自动嵌套)
    search_params = params[:flight]&.permit(:departure_airport_id, :arrival_airport_id, :flight_date, :number_of_passengers)

    if search_params.present? && search_params.values.any?(&:present?)
      # 仅当存在非空搜索参数时,查询航班
      @flights = Flight.filter_flights(
        search_params[:departure_airport_id],
        search_params[:arrival_airport_id],
        search_params[:flight_date],
        search_params[:number_of_passengers]
      ).includes(:departure_airport, :arrival_airport).order(:flight_date)
    else
      # 初始加载或参数全空时,返回空数组
      @flights = []
    end
  end
end

3. 修正表单提交路径与字段绑定

使用Rails路由辅助方法flights_path替代硬编码的'/',确保表单提交到正确的index动作:

<%= form_with model: @flight, url: flights_path, method: :get do |form| %>
  <!-- 示例字段,根据实际需求调整 -->
  <%= form.label :departure_airport_id, "出发机场" %>
  <%= form.select :departure_airport_id, Airport.pluck(:name, :id), include_blank: "请选择" %>

  <%= form.label :arrival_airport_id, "到达机场" %>
  <%= form.select :arrival_airport_id, Airport.pluck(:name, :id), include_blank: "请选择" %>

  <%= form.label :flight_date, "航班日期" %>
  <%= form.select :flight_date, @flight_dates.map { |fd| [fd.flight_date.strftime("%Y-%m-%d"), fd.flight_date] }, include_blank: "请选择" %>

  <%= form.label :number_of_passengers, "乘客数量" %>
  <%= form.number_field :number_of_passengers, min: 1 %>

  <%= form.submit "搜索航班" %>
<% end %>

4. 视图中控制航班列表显示

保持你原本的@flights.present?判断逻辑即可:

<% if @flights.present? %>
  <h3>搜索结果</h3>
  <table>
    <thead>
      <tr>
        <th>出发机场</th>
        <th>到达机场</th>
        <th>日期</th>
        <th>剩余座位</th>
      </tr>
    </thead>
    <tbody>
      <% @flights.each do |flight| %>
        <tr>
          <td><%= flight.departure_airport.name %></td>
          <td><%= flight.arrival_airport.name %></td>
          <td><%= flight.flight_date.strftime("%Y-%m-%d") %></td>
          <td><%= flight.available_passenger_seats %></td>
        </tr>
      <% end %>
    </tbody>
  </table>
<% else %>
  <p>请填写搜索条件查询航班</p>
<% end %>

5. 路由配置

确保config/routes.rb中配置了正确的路由:

Rails.application.routes.draw do
  resources :flights, only: [:index]
end

问题根源说明

  1. 表单参数嵌套:使用model: @flight生成表单时,所有参数会被包裹在params[:flight]哈希中,而非直接在params根节点,之前直接取params[:departure_airport_id]会获取不到值。
  2. 作用域返回值异常:原作用域在参数全空时会返回nil,导致@flights.present?判断失效,修正后确保始终返回ActiveRecord::Relation对象。
  3. 初始加载逻辑缺失:未区分初始加载和搜索请求,导致默认查询所有航班,现在通过判断搜索参数是否存在来控制是否查询航班。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:34:49