Невозможно получить доступ к пользователю в объекте комментария - PullRequest
0 голосов
/ 10 июня 2019

У меня есть следующие модели: Post, Comment и User. Объект Комментарий принадлежит пользователю, и у пользователя есть много комментариев. Тем не менее, при попытке сделать представление для отображения комментариев, пользователь не может получить доступ и показывает неопределенный метод "avatar" для nil: NilClass. Прикрепленный аватар - это метод, связанный с классом User.

Это контроллер комментариев

class CommentsController < ApplicationController

    before_action :authenticate_user!, except: [:index, :show]
    before_action :set_commentable 

    def create
        @comment = @commentable.comments.new comment_params
        @comment.user = current_user
        @comment.save
        redirect_to @commentable, notice: "Comment Posted!"
    end

    def index
        @comments = @commentable.comments.all
        @comment = @commentable.comments.new comment_params
    end



    private

        def comment_params
            params.require(:comment).permit(:body)
        end

        def set_commentable
            @commentable = Post.find(params[:post_id])
        end

end

Вот модель комментария:

class Comment < ApplicationRecord
    belongs_to :user
    belongs_to :commentable, polymorphic: true
end

Вот модель пользователя:

class User < ApplicationRecord

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  acts_as_voter

  has_many :posts
  has_many :comments
  has_one_attached :avatar


  validates :username, uniqueness: true
  validates :email, uniqueness: true

end

Вот представление, которое я пытаюсь отобразить. Я хочу, чтобы комментарии отображались в нижней части представления просмотра сообщения:

<p id="notice"><%= notice %></p>

<div class="w3-container w3-card w3-white w3-round m7" style="margin:auto; display:table; min-width: 500px; max-width: 800px;"><br>
        <% if @post.user.avatar.attached? %>
            <%= image_tag @post.user.avatar, class: "w3-circle avatar w3-left w3-margin-right", :style => "display: inline;" %>
        <% else %>
        <img src="https://www.w3schools.com/w3images/avatar2.png" alt="Avatar" class="w3-left w3-circle w3-margin-right" style="width:60px">
        <% end %>
        <%= link_to @post do %>
        <span class="w3-right w3-opacity"><%= time_ago_in_words(@post.created_at) %> ago</span>
        <% end %>

        <h4><%= @post.user.name %></h4> <h5>@<%= @post.user.username%></h5>
        <hr class="w3-clear">
        <p><%= @post.content %></p>
        <% if user_signed_in? %>
        <hr class="w3-clear">
        <%= link_to like_post_path(@post), method: :put,  class: "w3-button w3-theme-d2 w3-margin-bottom" do%>
            <i class="fa fa-thumbs-up"></i>
            <span class="w3-badgeM"><%= @post.get_upvotes.size %></span>
        <% end %>    
        <button type="button" class="w3-button w3-theme-d2 w3-margin-bottom"><i class="fa fa-comment"></i></button>

        <% if current_user.id == @post.user_id %>
            <%= link_to edit_post_path(@post), class: "w3-button w3-theme-d1 w3-margin-bottom" do %>
                <i class="fas fa-pencil-alt"></i>
            <% end %>
            <%= link_to @post, method: :delete, data: {confirm: "Are you sure you want to delete this post?"}, class: "w3-button w3-theme-d1 w3-margin-bottom" do %>
                <i class="fas fa-trash-alt"></i>
            <% end %>
        <% end %>
        <% else %>
        <br >
        <% end %>

        <%= simple_form_for([@post, @post.comments.build]) do |f| %>
        <div class="field">
            <div class="control">
            <%= f.input :body, input_html: { class: 'textarea' }, wrapper: false, label_html: { class: 'label' }  %>
            </div>
        </div>
        <%= f.button :submit, 'Leave a reply', class: "button is-primary" %>
        <% end %>
        <% @post.comments.each do |comment|%>
        <div class="w3-container w3-card w3-round w3-margin" style="background-color: #f3f3f3; padding: 0px 5px 5px;" ><br>
            <% if comment.user.avatar.attached? %>
                <%= image_tag comment.user.avatar, class: "w3-circle avatar w3-left w3-margin-right", :style => "display: inline;" %>
            <% else %>
                <img src="https://www.w3schools.com/w3images/avatar2.png" alt="Avatar" class="w3-left w3-circle w3-margin-right" style="width:60px">
            <% end %>
            <% if user_signed_in? %>

            <% end %>
            <span class="w3-right w3-opacity"><%= time_ago_in_words(comment.created_at) %> ago</span>
            <h6><%= comment.user.name %></h6> <p><strong>@<%= comment.user.username%></strong></p>
            <p style="max-height: 75px; overflow:auto;"><%= comment.body %></p>

        </div>
        <% end %>

    </div>

Файлways.rb:

Rails.application.routes.draw do
  devise_for :users
  #  :controllers => {registrations: 'registrations'}
  resources :posts do
    member do
      put "like" => "posts#upvote"
      put "unlike" => "posts#downvote"
    end
    resources :comments
  end   
  root "posts#index"
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

Однако, когда я пытаюсь сделать это, я получаю следующую ошибку:

https://i.ibb.co/HV3qkr7/error.jpg

Если я посмотрю в базе данных, запись с комментариями существует с правильными идентификаторами:

https://i.ibb.co/FXvPpSF/db.jpg

Когда я пытаюсь запустить прикрепленный метод аватара в консоли после выбора сообщения, он возвращает true и не выдает никаких ошибок:

https://i.ibb.co/X3k3mBq/console.jpg

Может ли кто-нибудь мне помочь и указать, где я ошибся? Спасибо:)

Ответы [ 3 ]

0 голосов
/ 10 июня 2019

Во-первых: нет такой переменной экземпляра, как @post, поэтому я бы начал с этого:)

Во-вторых: я бы предложил обернуть все в объекты, реализующие шаблон проектирования Presenter. Я бы отделил уровень представления от уровня ведения бизнеса / постоянства.

0 голосов
/ 11 июня 2019

Это было на самом деле простое исправление! Мне просто пришлось обернуть представление комментариев внутри <% if !comment.user.nil? %> По некоторым причинам, первый комментарий, похоже, не связан с пользователем.

0 голосов
/ 10 июня 2019

Похоже, ваше сообщение не имеет пользователя, связанного с ним. Это трудно увидеть, поскольку ваше сообщение об ошибке уже уменьшено, но строка 3 вашего кода:

<% if @post.user.avatar.attached? %>

Где происходит ошибка. Это происходит не потому, что у пользователя нет аватара, а потому, что вы пытаетесь найти аватар nilclass.

Ваши два варианта - исправить рассматриваемый @post, чтобы он ассоциировался с пользователем (вы можете поставить его с консоли через точку), или изменить строку на:

<% if @post.user&.avatar.attached? %>

Это остановит выполнение, если пользователь поста равен нулю, и просто вернет false вместо взрыва. Однако если предполагается, что к вашему сообщению присоединен пользователь, я бы посоветовал исправить это, а не менять логику на учетную запись для сообщений без пользователей.

...