Значение атрибута Name равно нулю?

#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 атрибута — и не допускает простого изменения параметров, как если бы вы передали его через форму.