ruby-on-rails - 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
解决方案
既然 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 %>
推荐阅读
- assembly - 定义数据段时,DATA SEGMENT USE16 PARA PUBLIC 'DATA' 是什么意思?
- jquery - 组织图 - 第二次单击父节点时,所有节点都应打开
- mysql - 在其中一个表中组合两个表和两列的 MySQL 查询
- javascript - 来自 Web 表单的数据未添加到 Firebase
- spring - Spring-JDBC-Session 与 Hibernate 多租户
- c - Why do I keep getting a segmentation dump?
- java - 这些方法有什么用?
- python - 在 for 循环中使用输入值附加列表
- c# - 设置 HttpRuntime.WebObjectActivator 会使 HttpApplication.InitModulesCommon 抛出 NullReferenceException
- react-native - 如何使文本与行对齐?