Send three pieces of information, "user information", "book", and "genre" from one form, Implement the function to save in separate table using ** Form object **.
Specifically, the class defined by myself is provided with the function corresponding to the form_with method and the function to perform validation, and the instance method of the class is used to save to multiple tables.
A Form object is one of Rails' design patterns.
This design pattern is "when you want to operate multiple models with one form submission", It is used when you want to validate the information that is not saved in the table. It means that the same process can be used in many models by cutting out the one in which various processes such as validation are originally written in the form layer.
Model file to be cut out in the form layer Set to include "ActiveModel :: Model" and "attr_accessor"
user_book.rb
class UserBook
include ActiveModel::Model
attr_accessor :nickname, :age, :gender, :book_title, :genre
end
○ActiveModel::Model When you include ActiveModel :: Model in a class, the instance of that class can be treated as an argument of helper methods such as form_with and render like the instance of the class that inherits ActiveRecord, and the validation function can be used. A class that includes ActiveModel :: Model to implement the Form object pattern is sometimes called a "Form object".
○attr_accessor It is a method that defines getters and setters in the written class. It sets attributes based on the given arguments and defines a method (getter) to get them and a method (setter) to update them.
-Definition of method that can get value (getter) -Definition of a method that can update the value (setter)
By defining getters and setters for all attributes used in this form (that is, all column names of each table you want to save), you can use them as arguments of form_with when you create an instance of this Form object. I will.
user_book.rb
class UserBook
include ActiveModel::Model
attr_accessor :nickname, :age, :gender, :book_title, :genre
with_options presence: true do
validates :nickname
validates :age
validates :genre
end
def save
user = User.create(nickname: nickname, age: age, gender: gender)
Book.create(book_title: book_title, user_id: user.id)
Genre.create(genre: genre, user_id: user.id)
end
end
With all the validations you want to set In def save ~ end I am writing a process to save the information sent as a parameter from the form in a table.
Define book_params to format all the information sent from the form into hash format, It is used to call this in the create action to create an instance of the UserBook class.
books_controller.rb
class BooksController < ApplicationController
def index
end
def new
@user_book = UserBook.new
end
def create
@user_book = UserBook.new(book_params)
if @user_book.valid?
@user_book.save
redirect_to action: :index
else
render action: :new
end
end
private
def book_params
params.require(:user_book).permit(:nickname, :age, :gender, :book_title, :genre)
end
end
Pass the created Form object instance as an argument to the form_with method of new.html.erb so that the input information will be processed through MVC.
ruby:app/views/books/new.html.erb
<%= form_with(model: @user_book, url: donations_path, local: true) do |form| %>
<%= render 'error_messages', model: @user_book %>
#Form contents
<% end %>
This article is based on the following. https://product-development.io/posts/rails-design-pattern-form-objects
Recommended Posts