중첩된 창 관련 모델에 데이터를 동시에 저장하는 방법(Rails6.0.0)
16575 단어 관계창문체RubyOnRais6RubyRails
결론 친모형 acceptsnested_attributes_for 추가
실증적 환경
・Cloud9 Ubuntu Server
・Rails6.0.0
・Rubby 2.6.3p62(2019-04-16 revision 67580)[x86 64-Linux]
전제 조건
다음 쌍의 다중 관계가 있는 Parent 모델과 Kid 모델을 가정합니다.
※ 1: 혼란을 피하기 위해 "파렌트는 아버지인가요, 어머니인가요?"이런 생각은 없을 것이다.
※ 2: 모델 이름에 불규칙적으로 변하는 명사를 쓰는 것은 번거롭기 때문에 차일드가 아닌 키드를 사용한다.
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
end
models/kid.rbclass Kid < ApplicationRecord
belongs_to :parent
end
플러그인 창의 실현
부모 모델의 데이터를 저장할 때 서브 모델의 데이터를 동시에 저장하기 위해
accepts_nested_attributes_for
Parent 모델에 추가합니다.models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
accepts_nested_attributes_for :kids
end
이렇게 하면 플러그인 창을 사용할 수 있고 한 창에 관련 데이터를 등록할 수 있다.그리고 모종 Parents 컨트롤러를 사용하여 폼 페이지에서 보내온 params를 받는 빈 실례를 만듭니다.
연관된 서브모델의 빈 인스턴스도 생성합니다.
동시에 서브모델의 Prams를 받아들이기 위해string 매개 변수에서 (위)
kids_attributes: [:name, :age, :toy]
여기요.controllers/parents_controller.rb
class ParentsController < ApplicationController
#(中略)
def new
@parent = Parent.new
@parent.kids.build #子モデルの空のインスタンスを作成
end
def create
@parent = Parent.new(parent_params)
if @parent.save
redirect_to root_url
else
render :new
end
end
#(中略)
private
def parent_params
#子モデルのパラメーターを受け取れるようにする
params.require(:parent).permit(
:name, :age, kids_attributes: [:name, :age, :toy]
)
end
end
new.html.erb<div class="container">
<div class="col-sm-10 col-sm-offset-1">
<h1 class="text-center">親登録</h1>
<%= form_with(model: @parent, local: true) do |f| %>
<div class="field form-group">
<%= f.label :name %>
<%= f.text_field :name, class: "form-control" %>
</div>
<div class="field form-group">
<%= f.label :age %>
<%= f.number_field :age, class: "form-control" %>
</div>
<!-- 子モデルのデータを受け取るためのネストされたフォーム -->
<%= f.fields_for :kids do |kf| %>
<h1 class="text-center">子登録</h1>
<div class="field form-group">
<%= kf.label :name %>
<%= kf.text_field :name, class: "form-control" %>
</div>
<div class="field form-group">
<%= kf.label :age %>
<%= kf.number_field :age, class: "form-control" %>
</div>
<div class="field form-group">
<%= kf.label :toy %>
<%= kf.text_field :toy, class: "form-control" %>
</div>
<% end %>
<div class="field form-group">
<%= f.submit "上記内容で登録する", class: "btn btn-primary btn-lg btn-block" %>
</div>
<% end %>
</div>
</div>
Bootstrap이 있는 반은 보기 힘들다. 위의f.fields_for
는 서브모델 데이터를 수신하는 형식이다.데이터 업데이트 시 새로운 관련 데이터 저장
여러 개의 빈 실례를 만듭니다. 보기 자체의 창을 추가하지 않고 입력 표시줄을 추가할 수 있습니다.
예를 들어, Parents 디렉터를 변경하면 새로 등록할 때 서브모델 입력 형식 세트를, 업데이트할 때 서브모델 입력 형식 세트를 표시할 수 있습니다.
controllers/parents_controller.rb
class ParentsController < ApplicationController
#(中略)
def new
@parent = Parent.new
@parent.kids.build #子モデルの空のインスタンスを作成
end
def create
@parent = Parent.new(parent_params)
if @parent.save
redirect_to root_url
else
render :new
end
end
#(中略)
def edit
@parent = Parent.find(params[:id])
@parent.kids.build #子モデルの空のインスタンスを作成
end
def update
@parent = Parent.find(params[:id])
if @parent.update(parent_params)
redirect_to root_url
else
render :edit
end
end
def destroy
@parent = Parent.find(params[:id])
@parent.destroy
redirect_to root_url
end
private
def parent_params
params.require(:parent).permit(
:name, :age, kids_attributes: [:name, :age, :toy]
)
end
end
편집 동작에서 하위 모델의 빈 실례를 만들면 업데이트할 때 '등록된 하위 모델 데이터' +1개의 입력 창을 만들 수 있습니다.이렇게 되면 JS 등을 통한 동적 추가보다 입력 형태를 쉽게 늘릴 수 있다.(개수가 제한되어 병목이지만...)
추가 폼을 추가하려면 빈 실례의 수량을 입력하십시오
@parent.kids.build
부터 시작하다n.times { @parent.kids.build }
n개의 입력 창을 생성할 수 있습니다.입력하지 않았을 때 빈 데이터를 저장하지 않습니다
그러나 추가된 창을 입력하지 않으면 빈 데이터를 저장합니다.
이를 막기 위해 Parent 모델에 추가된
accepts_nested_attributes_for
두 번째 매개변수에 Proc를 넘겼다.models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
accepts_nested_attributes_for :kids, reject_if: lambda {|attributes| attributes['name'].blank?}
end
상기 상황에서 하위 모형이 창의name를 입력하는 것이 비어 있으면 다른 속성을 입력해도 (여기는age,toy) 모두 저장되지 않습니다.name 또는 age를 입력하지 않은 경우 등록하지 않으려면 다음과 같이 변경됩니다.
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
accepts_nested_attributes_for :kids, reject_if: lambda {|attributes| attributes['name'].blank? || attributes['age'].blank?}
end
위 내용 외에 서브모델의 검증을 변경하면 저장된 값을 자유롭게 제어할 수 있다.이외에도 연관된 서브모델의 데이터만 삭제하려는 경우도 있지만, 상세한 경우 Rails 가이드의 "Action View 창 도우미"는 매우 참고할 만하다.
후기
저는 현재 Ruby on Rails에서 공부하는 첫 번째 학자입니다.
나는 내 앱을 만드는 과정에서 며칠 동안 막힌 기능을 발표했다.
잘못된 점이나 건의가 있으면 메시지를 남겨 주세요.
Reference
이 문제에 관하여(중첩된 창 관련 모델에 데이터를 동시에 저장하는 방법(Rails6.0.0)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/_Taturon_/items/961199cdd937be669cc5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)