I have the following routes:
shallow do
resources :countries do
resources :airports
end
end
I'm having trouble with invoking two of the routes.
The airports_controller.rb
file begins
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])
The last line gives the error Minitest::UnexpectedError: ActiveModel::ForbiddenAttributesError: ActiveModel::ForbiddenAttributesError
, but the params I'm calling with are
!!! 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"}
and as far as I can see all of those are in my permitted parameters:
def airport_params
params.require(:airport).permit(:iata_code, :icao_code, :name, :city, :latitude, :longitude, :notes, :country_id)
end
Secondly, my airports\\_form.html.erb
begins <%= form_for [@country, @airport] do |f| %>
<%= form_for [@country, @airport] do |f| %>
, but that gives an error Minitest::UnexpectedError: ActionView::Template::Error: undefined method 'airports_path' for #<#<Class:0x4b0ba30>:0x55a2e48>
. Yes, that path is undefined, but I was trying to get to path country_airports_path
, which is defined.
So what am I missing here?
In "def create"
def create
...
@airport = @country.airports.build(airport_params)
You've correctly created the "airport_params" function, however you're not calling it. That should explain the ForbiddenAttributesError
.
As for the undefined method, at first glance it looks like an incorrect association, are your models correctly related (ie belongs_to
and has_many
)? If so, you could try adding url: country_airports_path
to the form_for
field.
Attributes
The attributes error you've received is basically caused by your non-use of strong_params
.
Rails 4 introduced strong_params
to give you the ability to define specific attributes to pass to your model (prevents mass assignment). The problem you have is that you're using the Rails 3
way - passing all of the attributes without whitelisting them
As pointed out, you'll be better doing this:
#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
However, I believe there's something deeper you need to consider.
You're currently using .build
for your airport model object. Whilst there's nothing wrong with this, you need to consider what you're trying to achieve...
The Airport
model object is a standalone object. You can easily associate it with your Country
model by setting the foreign_key
in your strong params (demonstrated above)
If you use this line: @airport = @country.airports.build
, you're working with the Country
object, which IMO will open yourself up to errors down the line. As mentioned, there's nothing "wrong" with what you're doing; it's just that I'd either work with the Airport model directly (as written above), or use accepts_nested_attributes_for
to work with the Country
model
--
Route
Secondly, your path error is going to be caused by your form_for
form_for
builds a form from an ActiveRecord object - which it does by taking arguments such as model_name
to build the "url" / "action" for the form.
This means every time you populate a form_for
object with an ActiveRecord object (variable), Rails will build a route based off of what you pass it (it does not know whether the object is nested or not)
<%= form_for @airport do |f| %>
# builds route using "airport_path"
<% end %>
If you want to create a nested form, you'll be much better using an array of ActiveRecord objects, as to provide Rails with the knowledge you're using a nested resource:
<%= form_for [@country, @airport] do |f| %>
# builds route using "country_airport_path"
<% end %>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.