为什么这个Rails collection_select没有渲染关联属性?

问题描述 投票:0回答:1

航班 -

belongs_to :departure_airport
,机场
has_many :departing_flights

我正在尝试在 Rails 中创建一个下拉选择表单元素

form_with
,其中每个选项的关联的 :city 值是关联上的一个属性:

查看表单代码 - Flight#index:

<%= form_with(url: flights_path, method: :get) do |form| %>
  <div>
    <%= form.label :departure_airport, 'Departure Airport' %>
    <%= form.collection_select :departure_airport, @flights, :departure_airport_id, :departure_airport.city, prompt: 'Select Departure Airport' %>    
  </div>
  <div>
    <%= form.submit 'Search Flights' %>
  </div>
<% end %>

飞控代码:

class FlightsController < ApplicationController
  def index
    @flights = Flight.all
  end
end

航班.rb:

class Flight < ApplicationRecord
  belongs_to :departure_airport, class_name: 'Airport'
  validates_presence_of :departure_airport
end

机场.rb:

class Airport < ApplicationRecord
  has_many :departing_flights, class_name: 'Flight', foreign_key: 'departure_airport_id'
end

我可以看到该关联正在起作用,因为 html 将实际的机场对象引用字符串显示为每个下拉选项的名称/标签。但在我的一生中,我无法让每个选项都用关联上的属性命名:

Html 呈现形式摘录:

<form action="/flights" accept-charset="UTF-8" method="get">
  <div>
    <label for="departure_airport">Departure Airport</label>
    <select name="departure_airport" id="departure_airport"><option value="">Select Departure Airport</option>
<option value="8">#&lt;Airport:0x00000001126f0730&gt;</option>
<option value="60">#&lt;Airport:0x0000000112728630&gt;</option>
<option value="47">#&lt;Airport:0x0000000112713140&gt;</option>
<option value="33">#&lt;Airport:0x00000001126fbdd8&gt;</option>
etc ...
<option value="42">#&lt;Airport:0x0000000112c9b568&gt;</option></select>    
  </div>
  <div>
    <input type="submit" name="commit" value="Search Flights" data-disable-with="Search Flights">
  </div>
</form>

我已经尝试过机场对象的任何各种属性/列(例如

:departure_airport.name
:departure_airport.country
),但没有一个会显示为单个选项的标签。

有人能看到我在这里做错了什么吗?

关联肯定存在模型级别,如以下 Rails 控制台对象和关联查询所示:

3.1.2 :012 > f = Flight.first
  Flight Load (1.4ms)  SELECT "flights".* FROM "flights" ORDER BY "flights"."id" ASC LIMIT $1  [["LIMIT", 1]]
 => 
#<Flight:0x000000010280c9a8
... 
3.1.2 :013 > f.departure_airport_id
 => 8 
3.1.2 :014 > f.departure_airport.name
  Airport Load (1.0ms)  SELECT "airports".* FROM "airports" WHERE "airports"."id" = $1 LIMIT $2  [["id", 8], ["LIMIT", 1]]
 => "Bordeaux Airport" 
3.1.2 :015 > f.departure_airport.city
 => "Bordeaux" 
3.1.2 :016 > f.departure_airport.country
 => "France" 

3.1.2:017>

ruby-on-rails rails-activerecord
1个回答
0
投票

:departure_airport.city
这会调用符号
city
上的
:departure_airport
方法,而不是关联。

您必须使用

Flight
模型中的属性和方法:

<%= form.collection_select :departure_airport_id, @flights,
  :departure_airport_id,
  :departure_airport_city
%>
class Flight < ApplicationRecord
  belongs_to :departure_airport, class_name: 'Airport'
  # this validation is redundant, belongs_to association is required by default
  # validates_presence_of :departure_airport

  # this is the same as
  #
  #   def departure_airport_city
  #     departure_airport.city
  #   end
  #
  delegate :city, to: :departure_airport, prefix: true
end

https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select

© www.soinside.com 2019 - 2024. All rights reserved.