Я пытаюсь создать форму с серией проверок, чтобы предотвратить дублирование при одновременном создании трех записей модели: один для родителя (если он не существует), один для его child (при условии, что он не существует), и один для таблицы соединения между дочерним элементом и пользователем (чтобы позволить Пользователю иметь собственную копию объекта Song).DB rolls back on create action
В текущем состоянии кода, проверяет, казалось бы пройти, но журналов сервера показывают
ROLLBACK
, и ничего не будет сохранено в базу данных, КРОМЕ родительского объекта (художник).Когда я пытаюсь использовать идентификаторы объекта, я получаю сообщение об ошибке
undefined method id for nil:NilClass
или «не удалось найти объект без идентификатора».
Следующий код в мой контроллер:
class SongsController < ApplicationController
before_action :authenticate_user!
def create
@artist = Artist.find_by(name: params[:artist][:name].strip.titleize) #look for the artist
@song = Song.find_by(title: params[:artist][:songs_attributes]["0"][:title].strip.titleize)
if @artist.present? && @song.present?
@user_song = current_user.user_songs.find(@song_id)
if @user_song.present?
render html: "THIS SONG IS ALREADY IN YOUR PLAYLIST"
render action: :new
else
@user_song = UserSong.create(user_id: current_user.id, song_id: @song.id)
redirect_to root_path
end
elsif @artist.present? && [email protected]?
@song = @artist.songs.build(title: params[:artist][:songs_attributes]["0"][:title].strip.titleize, lyrics: params[:artist][:songs_attributes]["0"][:lyrics].strip)
@user_song = UserSong.create(user_id: current_user.id, song_id: @song.id)
redirect_to root_path
elsif [email protected]?
@artist = Artist.create(name: params[:artist][:name].strip.titleize)
@song = @artist.songs.build(title: params[:artist][:songs_attributes]["0"][:title].strip.titleize, lyrics: params[:artist][:songs_attributes]["0"][:lyrics].strip)
@user_song = UserSong.create(user_id: current_user.id, song_id: @song.id)
redirect_to root_path
else
render html: "SOMETHING WENT WRONG. CONTACT ME TO LET ME KNOW IF YOU SEE THIS MESSAGE"
end
end
def index
@songs = Song.all
end
def new
@artist = Artist.new
@artist.songs.build
@user_song = UserSong.new(user_id: current_user.id, song_id: @song_id)
end
def show
@song_id = params["song_id"]
@song = Song.find(params[:id])
end
def destroy
UserSong.where(:song_id => params[:id]).first.destroy
flash[:success] = "The song has been from your playlist"
redirect_to root_path
end
def edit
@song = Song.find(params[:id])
@artist = Artist.find(@song.artist_id)
end
def update
end
private
def set_artist
@artist = Artist.find(params[:id])
end
def artist_params
params.require(:artist).permit(:name, songs_attributes: [:id, :title, :lyrics])
end
def set_song
@song = Song.find(params["song_id"])
end
end
Модели:
class Artist < ApplicationRecord
has_many :songs
accepts_nested_attributes_for :songs, reject_if: proc { |attributes| attributes['lyrics'].blank? }
end
class Song < ApplicationRecord
belongs_to :artist
has_many :user_songs
has_many :users, :through => :user_songs
end
class UserSong < ApplicationRecord
belongs_to :song
belongs_to :user
end
Извините, если я не абстрагируется достаточно. Не совсем уверен, как, учитывая, что нет сообщения об ошибке, просто откат (без каких-либо проверок, присутствующих в любом из контроллеров).
Вот почему никто с любым опытом работы с Rails расскажет вам, не сбрасывать тонны логики в контроллеры. Существует множество стратегий для обработки сложных, вложенных и чрезмерно ограниченных данных, но StackOverflow не является местом, чтобы узнать о них. Как бы то ни было, этот вопрос будет долгим, чтобы ответить, потому что вы не разделили его достаточно далеко, чтобы было легко ответить. Если ничего другого, я рекомендую удалить код с комментариями для ясности. – coreyward
Gotcha. Мои извинения. Я немедленно отредактирую его. – michaelsking1993
Я попытался изо всех сил снять его. Еще раз извините. – michaelsking1993