#ruby-on-rails #ruby
#ruby-on-rails #ruby
Вопрос:
Я пытаюсь создать пункт назначения, но он продолжает сообщать мне в моем браузере, что ‘name’ равно нулю, когда перенаправляет перенаправления на мое представление ‘show’.
Я получаю ошибку
undefined method `name' for nil:NilClass
Вот мои действия контроллера для new, create и show:
def show
@destination = Destination.find_by(id: params[:id])
end
def new
@destination = Destination.new
end
def create
@destination = Destination.create(dest_params)
redirect_to user_destination_path(current_user, @destination.id )
end
private
def dest_params
params.require(:destination).permit(:name,:user_id)
end
Моя новая форма, в которой я ввожу имя назначения:
<h2>Add a destination</h2>
<div>
<%= form_for @destination do |f|%>
<%= f.label :name %>
<%= f.text_field :name %><br>
<%= f.submit %>
<% end %>
</div>
вот мое представление для чтения / показа:
<h3>Added destination</h3>
<div>
<p><%= @destination.name %></p>
</div>
Перед всем этим я получал ошибки с отсутствующими обязательными ключами [: id], но я, казалось, исправил это, но по какой-то причине я подозреваю, что это может быть как-то связано с проблемой, с которой я сталкиваюсь сейчас. Дайте мне знать, если вы сможете обнаружить проблему
Обновлена ошибка
No route matches {:action=>"show", :controller=>"destinations", :id=>nil, :user_id=>"1"}, missing required keys: [:id]
Комментарии:
1. Можете ли вы опубликовать точную ошибку, которую вы получаете? Дело в том, что вы вызываете метод
name
для нулевого объекта?2. @RockwellRice Я обновил его для вас. Это не должен быть объект nil, но это может быть.
3. В вашем перенаправлении вы передаете символ
:id
в качестве второго параметра, а не фактический идентификатор записи, поэтому ваш.find_by
in.show
возвращаетnil
. Должно бытьuser_destination_path(current_user, @destination.id)
4. @rmlockerd, я внес эту корректировку, и это выдало мне другую ошибку. Я опубликую это в верхней части для вашего обзора.
5. @rmlockerd это проблема, с которой я сталкивался до той, которую я впервые опубликовал. Атрибут id назначения каким-то образом не установлен.
Ответ №1:
Основной проблемой здесь является полное отсутствие обработки ошибок. Вы вообще не проверяете, правильно ли пользователь ввел входные данные или запись вообще была сохранена в вашем методе create.
def create
@destination = Destination.create(dest_params)
redirect_to user_destination_path(current_user, @destination.id )
end
Если запись не сохранена, например, из-за неудачной проверки @destination.id
, значение равно нулю.
В вашем show
методе, который вы используете find_by
вместо find
, который просто пропускает ошибку вместо того, чтобы вызывать ActiveRecord::RecordNotFound
ошибку.
Ваш контроллер на самом деле должен выглядеть как:
class DestinationsController
def show
# will raise if the record is not found and return a 404 not found response
# instead of just exploding
@destination = Destination.find(params[:id])
end
def new
@destination = Destination.new
end
def create
# never just assume that the record is created unless you want
# to get kicked in the pants.
@destination = Destination.new(dest_params)
if @destination.save
# this route really does not need to be nested.
# see https://guides.rubyonrails.org/routing.html#shallow-nesting
redirect_to user_destination_path(current_user, @destination)
else
# re-render the form with errors
render :new
end
end
private
def dest_params
params.require(:destination).permit(:name,:user_id)
end
end
Комментарии:
1. Почти сработало, но у меня все еще возникает проблема с проверкой. Я определенно понимаю вашу точку зрения.
2. Я действительно не могу сказать вам, что не так, основываясь на таком расплывчатом описании. Вам нужны тесты, чтобы фактически автоматически проверять, что запись создана с допустимыми атрибутами, а не с недопустимыми атрибутами. guides.rubyonrails.org/testing.html#integration-testing
3. На данный момент я сделал проверку необязательной в моем пункте назначения для belongs_to: user association, пока не разберусь с этим получше. Теперь он делает то, что ему нужно, но не уверен, как это происходит с точки зрения наилучшей практики.
4. blog.bigbinary.com/2016/02/15/…
5. Если вы хотите, чтобы адресат создавался текущим пользователем, вам следует настроить
has_many :destinations
ассоциацию в вашей пользовательской модели, а затем изменить первую строку метода create на@destination = current_user.destinations.new(dest_params)
. Это приведет к присвоениюuser_id
атрибута — и не допускает простого изменения параметров, как если бы вы передали его через форму.