Прежде всего, я рекомендую вам сделать ваши контроллеры более общими, потому что это правильная архитектура, которой вы должны следовать, чтобы ваш контроллер мог называться authors_controller.rb
и управлять всеми авторскими материалами или books_controller.rb
и управлять всеми книгами. И, следуя этому подходу, вы можете иметь метод associate_book
, который получает автора и книгу и создает правильную ассоциацию. Позвольте мне объяснить это с помощью кода:
class Author < ApplicationRecord
has_many :books
# Fields :name
validates :name, presence: true
end
class Book < AoplicationRecord
# Optional because I think you want to add the author after create it
belongs_to :author, optional: true
# Fields :title, :publish_year, :author_id
validates :title, :publish_year, :author_id, presence: true
end
class AuthorsController < ApplicationController
def associate_book
# params here will contain the following [:author_id, book_id]
author = Author.find(params[:author_id])
book = Book.find(params[:book_id])
book.author = author
book.save!
rescue ActiveRecord::RecordInvalid => error
# This will allow you to catch exceptions related to the update
end
end
Затем вы можете протестировать этот метод, выполнив следующее, предполагая, что этот метод будет вызываться из маршрута
# Testing with RSpec
# spec/controllers/authors_controller.rb
RSpec.describe AuthorsController do
let(:author) { Author.first }
let(:book) { Book.first }
it 'Should associate an author with a provided book' do
expect do
post :associate_book, params: { author_id: author.id, book_id: book.id }
end.to change { author.books.count }.by(1)
end
end
Это проверит общее количество книг, связанных с автором.