Rails:无法正确调用嵌套路由

时间:2014-08-02 00:45:28

标签: ruby-on-rails ruby-on-rails-4

我有以下路线:

shallow do
  resources :countries do
    resources :airports
  end
end

我在调用两条路线方面遇到了麻烦。

airports_controller.rb文件开始

def create
  Rails::logger.debug "!!! Building airport with parameters #{params}"
  @country = Country.find(params[:country_id])
  Rails::logger.debug "!!! Found airport #{@country.name}"
  @airport = @country.airports.build(params[:airport])

最后一行给出了错误Minitest::UnexpectedError: ActiveModel::ForbiddenAttributesError: ActiveModel::ForbiddenAttributesError,但我打电话给的参数是

!!! Building airport with parameters {"airport"=>{"iata_code"=>"CCC",
"icao_code"=>"CCCC", "name"=>"Airport 3", "city"=>"City 3", "latitude"=>"1.5",
"longitude"=>"1.5"}, "country_id"=>"980190962", "controller"=>"airports",
"action"=>"create"}

据我所知,所有这些都在我允许的参数范围内:

def airport_params
  params.require(:airport).permit(:iata_code, :icao_code, :name, :city, :latitude, :longitude, :notes, :country_id)
end

其次,我的airports\_form.html.erb开始<%= form_for [@country, @airport] do |f| %>,但这会产生错误Minitest::UnexpectedError: ActionView::Template::Error: undefined method 'airports_path' for #<#<Class:0x4b0ba30>:0x55a2e48>。是的,该路径未定义,但我试图进入路径country_airports_path 已定义。

那我在这里错过了什么?

2 个答案:

答案 0 :(得分:0)

在&#34; def create&#34;

def create
  ...
  @airport = @country.airports.build(airport_params)

您已正确创建了&#34; airport_params&#34;功能,但是你没有调用它。这应该解释ForbiddenAttributesError

对于未定义的方法,乍一看它看起来像是一个错误的关联,你的模型是否正确相关(即belongs_tohas_many)?如果是,您可以尝试将url: country_airports_path添加到form_for字段。

答案 1 :(得分:0)

<强>属性

您收到的属性错误主要是由于您未使用strong_params

造成的

Rails 4引入了strong_params,使您能够定义要传递给模型的特定属性(防止批量分配)。您遇到的问题是您正在使用Rails 3方式 - 传递所有属性而不将它们列入白名单

正如所指出的,你最好这样做:

#app/controllers/airports_controller.rb
Class AirportsController < ApplicationController
   def create
      @airport = Airport.new(airport_params)
   end

   private

   def airport_params
      params.permit(:airport).permit(:your, :params).merge(country_id: params[:country_id])
   end
end

但是,我相信你需要考虑更深层次的东西。

您目前正在使用.build作为机场模型对象。虽然没有什么错误,但你需要考虑你想要实现的 ......

Airport模型对象是一个独立的对象。您可以轻松地将其与Country模型相关联,方法是在强大的参数中设置foreign_key(如上所示)

如果你使用这一行:@airport = @country.airports.build,那么你正在使用Country对象,IMO会自行打开这个对象。如上所述,你所做的事情并没有“错误”;只是我要么直接使用机场模型(如上所述),要么使用accepts_nested_attributes_for来处理Country模型

-

<强>路线

其次,您的路径错误将由您的form_for

引起

form_for从ActiveRecord对象构建一个表单 - 它通过使用诸如model_name之类的参数来构建表单的“url”/“action”。

这意味着每次使用ActiveRecord对象(变量)填充form_for对象时,Rails将根据您传递的内容构建路径(它不知道对象是否嵌套)< / p>

<%= form_for @airport do |f| %>
  # builds route using "airport_path"
<% end %>

如果你想创建一个嵌套的表单,你可以更好地使用一个ActiveRecord对象数组,以便为​​Rails提供你正在使用嵌套的知识资源:

<%= form_for [@country, @airport] do |f| %>
   # builds route using "country_airport_path"
<% end %>