Я создаю небольшое приложение для управления собственным онлайн-портфолио, но не могу решить проблему с update
.
Основная таблица в моей базе данных - works
, затем есть таблицы authors
и clients
, где я устанавливаю поля authorName
и clientName
как unique
. Авторы и клиенты могут иметь несколько работ, но работа может иметь только одну из них.
В форме, где я создаю работы, у меня есть поле для authorName
и еще одно для clientName
: еслиавтора не существует в таблице авторов, он создается, в противном случае существующий связывается с работой. То же самое с клиентом. Для достижения этого я использую first_or_initialize
, и он работает отлично. Проблемы начинаются, когда я пытаюсь использовать тот же метод внутри действия update
. Это мои модели:
Рабочая модель
class Work < ApplicationRecord
has_one :description
belongs_to :author
belongs_to :client
accepts_nested_attributes_for :client
accepts_nested_attributes_for :author
scope :active, lambda {where(:isActive => true)}
scope :descOrder, lambda {order(:date => :desc)}
scope :cover, lambda {where(:isCover => true)}
end
Автор Модель
class Author < ApplicationRecord
has_many :works
end
Модель клиента
class Client < ApplicationRecord
has_many :works
end
Быстрое редактирование: модели в том виде, в каком вы их видите, точно такие же, как и в моем приложении. Код не был удален.
На мой взгляд, эта форма:
<%= form_for(@work, :url => { :controller => "projects", :action => "update"} ) do |f| %>
<%= f.label("title") %>
<%= f.text_field(:title) %>
<%= f.fields_for(:author) do |author| %>
<%= author.label("author") %>
<%= author.text_field(:authorName) %>
<% end %>
<%= f.fields_for(:client) do |client| %>
<%= client.label("client") %>
<%= client.text_field(:clientName) %>
<% end %>
<%= f.label("date") %>
<%= f.date_field(:date) %>
<%= f.submit("update") %>
<% end %>
И вот как я обращаюсь с ней в контроллере:
def edit
@work = Work.find(params[:id])
if @work.client.nil?
@work.build_client
end
if @work.author.nil?
@work.build_author
end
end
def update
@work = Work.find(params[:id])
@work.client = Client.where(clientName: work_params["client_attributes"]["clientName"]).first_or_initialize
@work.author = Author.where(authorName: work_params["author_attributes"]["authorName"]).first_or_initialize
if @work.update(work_params)
flash[:notice] = "work: #{@work.title} updated successfully."
redirect_to(project_path(@work))
else
redirect_to new_project_path
end
end
private
def work_params
params.require(:work).permit(:title, :date, client_attributes: [:id, :clientName], author_attributes: [:id, :authorName])
end
Это ошибка, которую я получаю:
Started PATCH "/projects/21" for ::1 at 2019-10-14 20:00:27 -0700
Processing by ProjectsController#update as HTML
Parameters: {"authenticity_token"=>"rw3X7VJg8CDnOibniv1jKHTVTGp7pjE4ep6xHpHy0Zp8Xv/0uQd6y5xqq629M2FOOQNoYyOAXH//w5/VoeNEOA==", "work"=>{"title"=>"Progetto1", "author_attributes"=>{"authorName"=>"Autore1", "id"=>"34"}, "client_attributes"=>{"clientName"=>"Cliente4", "id"=>"30"}, "date"=>""}, "commit"=>"update", "id"=>"21"}
Work Load (0.7ms) SELECT `works`.* FROM `works` WHERE `works`.`id` = 21 LIMIT 1
↳ app/controllers/projects_controller.rb:42:in `update'
Client Load (0.6ms) SELECT `clients`.* FROM `clients` WHERE `clients`.`clientName` = 'Cliente4' ORDER BY `clients`.`id` ASC LIMIT 1
↳ app/controllers/projects_controller.rb:44:in `update'
Author Load (0.6ms) SELECT `authors`.* FROM `authors` WHERE `authors`.`authorName` = 'Autore1' ORDER BY `authors`.`id` ASC LIMIT 1
↳ app/controllers/projects_controller.rb:45:in `update'
Completed 404 Not Found in 15ms (ActiveRecord: 1.9ms | Allocations: 3805)
ActiveRecord::RecordNotFound (Couldn't find Client with ID=30 for Work with ID=21):
app/controllers/projects_controller.rb:47:in `update'
Даже если эти записи do существуют в базе данных (с теми идентификаторами, которые вы видите в ошибке) и их внешние ключиправильно хранятся в таблице works
(я проверял в mysql).
Я ожидаю достичь того же поведения действия new
(которое я описал в начале своего поста).
Как я могу решить это? Спасибо!
Небольшое обновление : если я изменяю first_or_initialize
на first_or_create
, это создает автора (или клиента), если он не существует, но в то же времяэто все еще дает мне ту же ошибку.