Я пытаюсь отобразить все отзывы, написанные пользователем на странице показа пользователей. У пользователей много альбомов и отзывов. Отзывы принадлежат альбомам и пользователям. Альбомы имеют много отзывов и пользователей. Я хочу связать 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
rout.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
users # 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