首页 > 解决方案 > Rails 错误找不到没有 ID 的专辑

问题描述

我正在尝试显示用户在用户显示页面上写的所有评论。用户有很多专辑和评论。评论属于专辑和用户。相册有很多评论和用户。我想将 Review.title 链接到属于该评论的专辑显示页面。我对 Rails 还很陌生,所以我不确定要添加什么代码来完成这项工作。

错误:

ActiveRecord::RecordNotFound in UsersController#show
Couldn't find Album without an ID
Extracted source (around line #60):
58
59
60
61
62
63


    def find_album
        @album = Album.find(params[:album_id])
    end

    def user_params

用户控制器

class UsersController < ApplicationController
    before_action :set_current_user, only: [:index, :show, :new, :edit, :destroy]
    #before_action :set_review, only: [:show, :edit, :update, :destroy]
    before_action :set_user, only: [:show, :edit, :update, :destroy]
    before_action :find_album, only: [:show, :create, :edit, :update, :destroy]
    before_action :must_login, only: [:index, :show, :new, :create, :edit, :update, :destroy]

    def index
        @users = User.all
    end

    def show
        @reviews = @user.reviews

    end

    def new
        @user = User.new
    end

    def create
        @user = User.new(user_params)
        if @user.save
            session[:user_id] = @user.id
            redirect_to albums_path
        else
            render :new
        end
    end

    def edit
    end

    def update
        @user.update(user_params(:name, :email, :password_digest))
        redirect_to user_path(@user)
    end

    def destroy
        @user = User.destroy
    end

    private

   # def set_review
   #     @review = Review.find(params[:id])
   # end

    def set_user
        @user = User.find(params[:id])
    end

    def set_current_user
        @user = current_user
    end

    def find_album
        @album = Album.find(params[:album_id])
    end

    def user_params
        params.require(:user).permit(:name, :email, :password, :password_confirmation)
    end
end

用户型号:

class User < ApplicationRecord
    has_secure_password
    validates :email, uniqueness: true, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
    validates :name, uniqueness: true, length: {in: 3..20}, presence: true
    has_many :reviews
    has_many :albums, through: :reviews

    def self.from_omniauth(auth)
        where(provider: auth.provider, uid: auth.uid).first_or_initialize do |user|
          user.provider = auth.provider
          user.uid = auth.uid
          user.name = auth.info.name
          user.oauth_token = auth.credentials.token
          user.oauth_expires_at = Time.at(auth.credentials.expires_at)
          user.save!
        end
      end
end

路线.rb

Rails.application.routes.draw do
  get '/auth/:provider/callback' => 'sessions#omniauth'
  get 'auth/failure', to: redirect('/')
  get '/signup' => 'users#new', as: 'signup'
  post '/signup' => 'users#create'
  get '/signin' => 'sessions#new'
  post '/signin' => 'sessions#create'
  get '/signout' => 'sessions#destroy'
  post '/logout', to: "sessions#destroy"

  resources :albums do
    resources :reviews, except: [:index]
  end
  resources :users, only: [:show, :destroy]
  resources :reviews, only: [:index]

  root to: "albums#index"
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

用户#show.html.erb


<p>Here is a list of Reviews you wrote:</p>
<% @reviews.each do |review| %>
        <%= link_to review.title, album_path(@album) %><br>
        <%= review.content %><br>
        <br>
<% end %>

<br>
<% if @user.reviews == nil? %>
<p>No reviews yet!</p>
<p>Choose from the list of albums to review <%= link_to "here!", albums_path %></p>
<% end %>

相册控制器

class AlbumsController < ApplicationController
    before_action :set_album, only: [:show, :edit, :update, :destroy]
    before_action :must_login, only: [:new, :show, :create, :edit, :update, :destroy]

    def index
        @albums = Album.all
        @user = current_user
    end

    def show
        @review = @album.reviews.build
        @review.user = current_user

        @review.save
        @reviews = Review.recent #scope
    end

    def new
        @album = Album.new
        @review = @album.reviews.build
        @user = current_user
    end

    def create
        #@user = User.find(current_user.id)
        @album = current_user.albums.build(album_params)
        #@album.user_id = current_user.id
        @album.reviews.each { |r| r.user ||= current_user } # I'm using ||= so i can use the same code on update without changing reviews that already have a user
        if @album.save
            redirect_to album_path(@album)
        else
            render :new
        end
    end

    def edit
        @user = current_user
    end

    def update
        #@album = current_user.albums.build(album_params)
        @album.user_id = current_user.id
        if @album.update(album_params)
            redirect_to album_path(@album), notice: "Your album has been updated."
        else
            render 'edit'
        end
    end

    def destroy
        @album.delete
        @album.avatar.purge
        redirect_to albums_path
    end

    private

    def set_album
        @album = Album.find(params[:id])
    end

    def album_params
        params.require(:album).permit(:artist, :title, :avatar, :user_id, reviews_attributes:[:title, :date, :content]) #removed the :user_id and :album_id from the permitted parameters for reviews_attributes, don't want users to exploit that assignation adding those parameters that I'm actually not using
    end
end

评论控制器

class ReviewsController < ApplicationController
    before_action :set_review, only: [:show, :edit, :update, :destroy]
    before_action :set_current_user, only: [:index, :show, :new, :edit, :destroy]
    before_action :find_album, only: [:show, :create, :edit, :update, :destroy]
    before_action :must_login, only: [:index, :show, :new, :create, :edit, :update, :destroy]

    def index
        @albums = Album.with_recent_reviews
    end

    def show

        #@reviews = Review.where("album_id = ?", params[:album_id])
    end

    def new
        if params[:album_id] && @album = Album.find_by(id: params[:client_id])
            @review = @album.reviews.build
        else
            redirect_to albums_path
        end
    end

    def create
        @review = current_user.reviews.build(review_params)
        @review.album = @album
        if @review.save
            redirect_to album_path(@album)
        else
            @album = @review.album
            render :new
        end
    end

    def edit
    end

    def update
        if @review.update(review_params)
            redirect_to album_path(params[:album_id])
        else
            render 'edit'
        end
    end

    def destroy
        if current_user.id == @review.user_id
          @album.reviews.find(params[:id]).destroy
          redirect_to album_path(params[:album_id])
        else
           flash[:error] = "Unable to delete your review. Please try again."
           redirect_to album_reviews_path(@review)
        end
      end

    private

    def set_review
        @review = Review.find(params[:id])
    end

    def set_current_user
        @user = current_user
    end

    def find_album
        @album = Album.find(params[:album_id])
    end

    def review_params
        params.require(:review).permit(:title, :date, :content, album_attributes:[:artist, :title, :user_id])
    end

end


标签: ruby-on-rails

解决方案


既然 usershave_many :reviews和 reviews belong_to :user,你所要做的就是:

def show
  @reviews = @user.reveiws
end

然后在您的show.html.erb文件中,您可以遍历@reviews并从评论中提取您想要的任何内容。

<% @reviews.each do |review| %>
  <p><%= link_to review.title, album_path(review.album) %></p>
  <p><%= review.content %></p>
<% end %>

推荐阅读