fields_for로 자식 테이블의 데이터를 단번에 작성(테스트도 쓰고 있습니다) [Rails][Rspec]
전제
한 가게의 데이터를 만들 때 그 가게에 대한 의견도 단번에 만들고 싶습니다. 전제가 되는 환경은 다음과 같습니다.
테이블 정보
테이블의 구조는 이런 느낌입니다.
상위 테이블(shops)
shops
id
이름
자식 테이블(comments)
comments
id
shop_id
콘텐츠
모델
부모 모델, 하위 모델의 model 파일은 각각 이와 같이 되어 있습니다.
부모 모델(Shop)
models/shop.rb
class Shop < ApplicationRecord
has_many :comments
accepts_nested_attributes_for :comments
end
부모 모델에서
accepts_nested_attributes_for :comments
를 지정하고 자식 모델의 데이터를 받아들이도록 하는 것이 포인트입니다.자식 모델(Comment)
아이 모델의 기재에는 특별히 바뀐 것은 없습니다.
models/comment.rb
class Comment < ApplicationRecord
belongs_to :shop
end
컨트롤러
부모 모델 측의 컨트롤러에는 궁리해야 할 점이 몇 가지 있습니다.
controllers/shops_controller.rb
class ShopsController < ApplicationController
def new
@shop = Shop.new
@shop.comments.build # ←一つ目のポイント
end
def create
@shop = Shop.create(shop_params)
if @shop.save
# 成功したときの処理
else
# 成功しなかったときの処理
end
end
private
def shop_params # ↓2つ目のポイント
params.require(:shop).permit(:name, comments_attributes: [:content])
end
end
첫 번째 포인트는
new
액션에서 @shop.comments.build
라고 기재해, 아이 테이블인 comments
의 인스턴스를 build
까지 해 두는 것입니다. 이렇게 하면 상위 테이블에 묶는 comments
를 만들 준비가 됩니다.두 번째 포인트는
shop_params
의 곳에서 comments_attributes: [:content]
라고 기재해, 아이 테이블의 요소도 permit 해 두는 것입니다. 요소가 둘 이상 있을 때는 comments_attributes: [:content, :attr2, :attr3]
와 같이 기재합니다.보기
보기에는 다음과 같이 표시됩니다.
views/shops/new.html.haml
= form_with model: @shop, local: true do |f|
= f.label :name, "店名"
= f.text_field :name
= f.fields_for :comments, local: true do |comments_form|
= comments_form.label :content, "ショップへのコメント"
= comments_form.text_field :content
= f.submit "送信"
이제 자식 테이블의 데이터도 단번에 만들어야합니다.
여담입니다만, 이전
f.fields_for
곳을 fields_for
라고 써 버려, 아이 테이블의 요소가 shop_params
. .f.fields_for
라고 기재하는 것으로, 부모 테이블의 폼 오브젝트에 연결할 수가 있습니다.테스트
테스트도 나름대로 요령이 필요했기 때문에 기재합니다. 여기에서는 요청 spec만을 작성합니다.
factory
부모(shop)
spec/factories/shops.rb
FactoryBot.define do
factory :shop do
name { "テストのお店" }
trait :with_nested_instances do
after( :create ) do |shop|
create :comment, id: shop.id
end
end
end
end
trait
라고 하는 것은, FactoryBot로, 상황에 따라 조금만 다른 데이터를 이용하고 싶을 경우의 설정 방법입니다.after(:create)
는 FactoryBot 콜백입니다. 이 근처는 이 기사 가 참고가 되었습니다.아이(comment)
spec/factories/comments.rb
FactoryBot.define do
factory :comment do
content { "コメント" }
end
end
자식 모델의 factory에 특별한 변화는 없습니다.
요청 spec
spec/requests/shops_request_spec.rb
RSpec.describe "Shops", type: :request do
describe "POST /shops" do
context "依存関係のあるテーブルのparamsが送信されているとき" do
before do
@comment_params = {
comments_attributes: {
"0": FactoryBot.attributes_for(:comment)
}
}
@params_nested = {
shop: FactoryBot.attributes_for(:shop).merge( @comment_params )
}
end
it 'リクエストが成功すること' do
post shops_url, params: @params_nested
expect(response.status).to eq 302
end
it "ショップ情報とコメントが新規作成されること" do
expect do
post shops_url, params: @params_nested
end.to change(Shop, :count).by(1) and change(Comment, :count).by(1)
end
end
end
end
"0"
근처가 조금 특수한 쓰는 방법으로 보입니다만, 이것은, 실제의 데이터 송신시에 보내지는 params
에 맞춘 형태가 됩니다. 길었지만 테스트까지 노력한 덕분에 의존성이 있는 데이터의 작성과 오이타 사이 좋게 되었습니다.참고 기사
여기까지 참고로 한 기사는 이쪽입니다.
RSpec에서 FactoryGirl 사용법 요약
【Rails】 복수의 레코드를 작성한다. 모델 관계에 따라 다른 form_for/fields_for 사용법
↓특히 이 기사에는 신세가 되었습니다! !
[Rails] accepts_nested_attributes_for 사용법
추가 (발전 학습?)
결국은 자신의 범 미스였지만, 마찬가지로 중첩된 테이블에 대해 고민하고 있을 때 학교의 동창생 커뮤니티에 투고하면 다음을 가르쳐 주셨습니다.
▼잘 모르겠지만 폼이 깔끔하게 쓸 수 있는 것 같다(그런 이해로 죄송합니다)
【Rails】FormObject를 사용해주세요.
▼다음의 폼에는 사용해 보고 싶다고 생각하고 있는 gem, 1체다의 구조를 가지는 테이블로, 다수의 아이 테이블 데이터를 단번에 작성할 수 있는 녀석
fields_for를 사용한 아이 모델에 복수 레코드 보존 【cocoon이 편리】
그럼 오늘도 앞으로 일, 노력하겠습니다. 조언 해 주신 여러분, 감사합니다! !
Reference
이 문제에 관하여(fields_for로 자식 테이블의 데이터를 단번에 작성(테스트도 쓰고 있습니다) [Rails][Rspec]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tanutanu/items/c82c1ed2f5fa78a58366텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)