#ruby-on-rails #resources #routes #nested
#ruby-on-rails #Ресурсы #маршруты #вложенный
Вопрос:
Я имею дело с вложенной «фермой» ресурсов в Rails, и моя форма для создания новой фермы выглядит следующим образом:
<%= form_for([@user, @farm], :url=> new_user_farm_path(@user)) do |f| %>
<% if @farm.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@farm.errors.count, "error") %> prohibited this farm from being saved:</h2>
<ul>
<% @farm.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :contact %><br />
<%= f.text_field :contact %>
</div>
<div class="field">
<%= f.label :adress %><br />
<%= f.text_field :adress %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Моя соответствующая «новая» функция в контроллере farms является:
def new
@farm = Farm.new
@user = User.find(current_user)
respond_to do |format|
format.html # new.html.erb
format.json { render json: @farm }
end
end
Форма отображается просто отлично, но после того, как я нажимаю отправить, и она фактически пытается создать новую ферму, я получаю эту ошибку:
No route matches [POST] "/users/2/farm/new"
В моих rake routes у меня четко отображается маршрут:
user_farm POST /users/:user_id/farm(.:format) {:action=
create", :controller=>"farms"}
Я только предполагаю, что проблема в моей функции create:
def create
@farm = Farm.new(params[:farm])
@user = User.find(current_user)
respond_to do |format|
if @farm.save
format.html { redirect_to user_farm(@user, @farm), notice: 'Farm was successfully created.' }
format.json { render json: @farm, status: :created, location: @farm }
else
format.html { render action: "new" }
format.json { render json: @farm.errors, status: :unprocessable_entity }
end
end
end
Мой файл routes.rb:
resources :users do
resource :farm
end
devise_for :users, :path => 'accounts'
Я получаю доступ к своей новой форме фермы по этой ссылке:
<%= link_to "New Farm", new_user_farm_path(current_user) %>
Все мои rake routes:
user_farm POST /users/:user_id/farm(.:format) {:action=>"
create", :controller=>"farms"}
new_user_farm GET /users/:user_id/farm/new(.:format) {:action=>"
new", :controller=>"farms"}
edit_user_farm GET /users/:user_id/farm/edit(.:format) {:action=>"
edit", :controller=>"farms"}
GET /users/:user_id/farm(.:format) {:action=>"
show", :controller=>"farms"}
PUT /users/:user_id/farm(.:format) {:action=>"
update", :controller=>"farms"}
DELETE /users/:user_id/farm(.:format) {:action=>"
destroy", :controller=>"farms"}
users GET /users(.:format) {:action=>"
index", :controller=>"users"}
POST /users(.:format) {:action=>"
create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"
new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"
edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"
show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"
update", :controller=>"users"}
DELETE /users/:id(.:format) {:action=>"
destroy", :controller=>"users"}
new_user_session GET /accounts/sign_in(.:format) {:action=>"
new", :controller=>"devise/sessions"}
user_session POST /accounts/sign_in(.:format) {:action=>"
create", :controller=>"devise/sessions"}
destroy_user_session GET /accounts/sign_out(.:format) {:action=>"
destroy", :controller=>"devise/sessions"}
user_password POST /accounts/password(.:format) {:action=>"
create", :controller=>"devise/passwords"}
new_user_password GET /accounts/password/new(.:format) {:action=>"
new", :controller=>"devise/passwords"}
edit_user_password GET /accounts/password/edit(.:format) {:action=>"
edit", :controller=>"devise/passwords"}
PUT /accounts/password(.:format) {:action=>"
update", :controller=>"devise/passwords"}
cancel_user_registration GET /accounts/cancel(.:format) {:action=>"
cancel", :controller=>"devise/registrations"}
user_registration POST /accounts(.:format) {:action=>"
create", :controller=>"devise/registrations"}
new_user_registration GET /accounts/sign_up(.:format) {:action=>"
new", :controller=>"devise/registrations"}
edit_user_registration GET /accounts/edit(.:format) {:action=>"
edit", :controller=>"devise/registrations"}
PUT /accounts(.:format) {:action=>"
update", :controller=>"devise/registrations"}
DELETE /accounts(.:format) {:action=>"
destroy", :controller=>"devise/registrations"}
user_confirmation POST /accounts/confirmation(.:format) {:action=>"
create", :controller=>"devise/confirmations"}
new_user_confirmation GET /accounts/confirmation/new(.:format) {:action=>"
new", :controller=>"devise/confirmations"}
GET /accounts/confirmation(.:format) {:action=>"
show", :controller=>"devise/confirmations"}
user_unlock POST /accounts/unlock(.:format) {:action=>"
create", :controller=>"devise/unlocks"}
new_user_unlock GET /accounts/unlock/new(.:format) {:action=>"
new", :controller=>"devise/unlocks"}
GET /accounts/unlock(.:format) {:action=>"
show", :controller=>"devise/unlocks"}
home_index GET /home/index(.:format) {:controlle
r=>"home", :action=>"index"}
root / {:controlle
r=>"home", :action=>"index"}
Ответ №1:
Проблема в том, что ваша форма пытается отправить запрос POST на URL, который существует только для запросов GET. Итак, это говорит вам о том, что
[POST] "/users/2/farm/new"
не существует — чего на самом деле нет. И ваш rake routes
вывод подтверждает это — проблема в том, что
new_user_farm GET /users/:user_id/farm/new(.:format)
что является запросом GET.
Формы по умолчанию используют POST для создания новой записи, поэтому вам необходимо указать URL-адрес, на который можно отправить. Или вы можете позволить Rails вычислить это по состоянию ваших объектов. Так что либо
<%= form_for([@user, @farm], :url=> user_farm_path(@user)) do |f| %>
или
<%= form_for([@user, @farm]) do |f| %>
должно сработать. В первом случае мы используем именованный маршрут, который совпадает с маршрутом POST из вашего rake routes
вывода. В последнем случае мы позволяем rails вычислять это на основе состояния вашего @farm
объекта. То есть, если @farm
is a new_record?
, он отправит запрос POST на /users/:user_id/farm
, или если @farm
есть persisted?
, то он отправит запрос PUT на /users/:user_id/farm
. (Тот же путь, просто другой тип запроса.)
Комментарии:
1. Да, это была проблема. Извините, просто еще один вопрос, поскольку я новичок. Почему он не показывает мне ферму, которую я только что создал. В нем говорится: не удалось найти ферму без идентификатора. Я сильно подозреваю, что моя функция create каким-то образом не работает. Не могли бы вы, пожалуйста, проверить это и убедиться, что все в порядке?
2.
@farm = Farm.new(params[:farm])
выглядит правильно … можете ли вы включить отладчик в свое действие create и проверить результат? Я не уверен, почему он запрашивает о поиске фермы, когда вы хотите ее создать. Возможно, вы выполняете неправильное действие? Кроме того, если у вас уже есть,current_user
тогда вам вообще не нужно делать@user = User.find(current_user)
бит — просто используйтеcurrent_user
.3. Я изменил это в своей create farm, но я по-прежнему получаю ту же ошибку. Он перенаправляет меня по этой ссылке: localhost: 3000/users/ 2/farm.11 . Я предполагаю, что мой redirect_to в моей функции create тоже не подходит.
4. О, хорошо. Поэтому примите к сведению мои правки в моем комментарии выше… Я на секунду растерялся. Так что да, redirect_to в вашем действии create должно быть
user_farm_path(@user, @farm)
не простоuser_farm(@user, @farm)
.5. Более того, как сказал @Rich Peck, похоже, что вы хотите
resources :farms
в своем файле routes, а не толькоresource :farm
.
Ответ №2:
Некоторые проблемы:
—
Параметры
При создании нового объекта ActiveRecord в Rails вам захочется использовать strong params
:
#app/controllers/farms_controller.rb
Class FarmsController < ApplicationController
def new
@farm = Farm.new
end
def create
@farm = Farm.new(farm_params)
end
private
def farm_params
params.require(:farm).permit(:params, :for, :farm)
end
end
—
Маршруты
Вы используете вложенную маршрутизацию, что может быть непросто, если вы к этому не привыкли.
Если вы еще этого не сделали, вам следует сделать это со своими маршрутами:
#config/routes.rb
resources :users do
resources :farm #-> /users/3/farm/new
end
Это даст вам возможность достичь этого маршрута либо из вашего контроллера, либо из представлений.
Если вы дадите мне дополнительную информацию (файл Routes), я смогу помочь в дальнейшем!
—
Публикация
Еще раз просмотрев проблему, кажется, я допустил оплошность раньше!!!
Как указано pdbobb
, ошибка, безусловно, говорит о том, что вы пытаетесь достичь /new
с помощью POST
глагола. Это неверно, поскольку в соответствии с соглашениями Rails о маршрутизации ресурсов вам необходимо
Вы сможете использовать ответ pdobb
, но что более важно, нам нужно установить, почему ваша форма пытается отправить в new
post.
Проблема, скорее всего, в вашем nested
ресурсе
Комментарии:
1. Я добавил еще кое-какую информацию, пожалуйста, скажите мне, если вам нужно что-нибудь еще.
2. Точно, форма отображается без проблем. Я заполняю эти три поля, нажимаю «Создать ферму», и это выдает мне эту ошибку.
3. Хм — это ссылается на определенную строку или что-то еще?
4. Ничего, он только говорит: Ошибка маршрутизации, а затем выдает эту ошибку. Это одна из причин, по которой это так запутанно. Я действительно не знаю, что еще попробовать. Кстати, я добавил ваше предложение для сильных параметров, спасибо вам за это. Я действительно надеюсь, что мы сможем это выяснить.
5. Я использовал ответ @pdobb, но теперь он не показывает ферму, как вы можете видеть в моем комментарии к его ответу.