【Rails6】cocoon_ 동적으로 양식 추가
◆목차
1) cocoon 도입 방법
2) 동적으로 폼을 추가 ←
앞두고
1. 모델 작성
2. 컨트롤러(액션)
3. 컨트롤러(스트롱 파라미터)
4. 보기
5. 뷰(동적으로 추가하고 싶은 부분)
3) 추가할 양식에 id 및 data 속성 부여
★GIF 화상(이런 느낌이 됩니다)
*주의 * "당근"을 선택하면 분홍색 상자 뒤에 "책"출력되는 것은 cocoon과는 전혀 관계 없기 때문에 나쁘지 않습니다. cocoon은 추가 버튼을 클릭하면 양식의 일부가 추가되는 gem입니다.
**【부모】recipe【자】ingredient(재료가 늘어나고 있는 곳)
2) 동적으로 양식 추가
1. 모델 작성
(부모)model/recipe.rbclass Recipe < ApplicationRecord
# cocoonで子フォームを親と一緒に保存するための記述。accepts_nested_attributes_forというメソッドを使っています。
has_many :ingredients, dependent: :destroy
accepts_nested_attributes_for :ingredients, allow_destroy: true
end
(자식)model/ingredient.rbclass Recipe < ApplicationRecord
belongs_to :recipe
end
2. 컨트롤러(액션)
(부모)controller/recipe_controller.rb
def new
@recipe = Recipe.new
@ingredient = @recipe.ingredients.build
# ↑この記述が大事
# paramsでこのように運ばれるため(カラム等だいぶ省略してます)
# recipe{"title"=>"ポテトサラダ","ingredients_attributes"=> {"thing_name"=>"1", "amount"=>"1" }}
end
def create
@recipe = Recipe.new(recipe_params)
if @recipe.save
# @recipe.saveでrecipeもingredientも同時に保存しています
redirect_to my_recipe_user_path(id: current_user)
else
render :new
end
end
3. 컨트롤러(스트롱 파라미터)
**쓰는 방법 매우 중요합니다! 여기서 많이 막혔습니다...
(부모)controller/recipe_controller.rb private
def recipe_params
params.require(:recipe).permit(
{images: []},:title,:feature,:eat,:category_id,:cold_date,:frozen_date,:time,:text,
ingredients_attributes:[:id, :recipe_id, :thing_id, :amount, :_destroy])
.merge(user_id: current_user.id)
end
가장 중요한 설명 ↓↓↓
ingredients_attributes:[:id, :recipe_id, :thing_id, :amount, :_destroy]
class Recipe < ApplicationRecord
# cocoonで子フォームを親と一緒に保存するための記述。accepts_nested_attributes_forというメソッドを使っています。
has_many :ingredients, dependent: :destroy
accepts_nested_attributes_for :ingredients, allow_destroy: true
end
class Recipe < ApplicationRecord
belongs_to :recipe
end
def new
@recipe = Recipe.new
@ingredient = @recipe.ingredients.build
# ↑この記述が大事
# paramsでこのように運ばれるため(カラム等だいぶ省略してます)
# recipe{"title"=>"ポテトサラダ","ingredients_attributes"=> {"thing_name"=>"1", "amount"=>"1" }}
end
def create
@recipe = Recipe.new(recipe_params)
if @recipe.save
# @recipe.saveでrecipeもingredientも同時に保存しています
redirect_to my_recipe_user_path(id: current_user)
else
render :new
end
end
private
def recipe_params
params.require(:recipe).permit(
{images: []},:title,:feature,:eat,:category_id,:cold_date,:frozen_date,:time,:text,
ingredients_attributes:[:id, :recipe_id, :thing_id, :amount, :_destroy])
.merge(user_id: current_user.id)
end
ingredients_attributes:[:id, :recipe_id, :thing_id, :amount, :_destroy]
ingredients・・・복수형, 단수형은 model과 맞추어 주세요. (아마 복수형이 될 것 같아요)
attributes・・・여기는 model등은 관계없이, 복수형으로 OK입니다.
:id ··· 이유는 모릅니다만, :id의 기술도 필요한 것 같습니다.
:_destroy···cocoon의 삭제 버튼과 관계 있는 것일까라고 생각하고 있습니다. (자세한 분 꼭 가르쳐 주세요)
4. 보기
GIF 동영상의 cocoon으로 작성하고 있는 재료의 부분 이외 생략했습니다.
view/recipe/new.html.erb
<%= form_with(model: @recipe, class:"recipes-post-main", local: true) do |f| %>
<!-- 省略 -->
<div class="parent">
<div class="form-box">
<div class="forms-item">
材料
</div>
<!-- 1)追加ボタンの記述 -->
<div class="add-botton-box">
<%= link_to_add_association "追加ボタン", f, :ingredients,
class: 'add_fields',
id: 'add-btn',
data: {
association_insertion_node: '#detail-association-insertion-point',
association_insertion_method: 'after'
}
%>
</div>
</div>
<!-- 動的に追加するフォームを挿入する箇所(なくてもいい*詳細は1)で説明します) -->
<div id="detail-association-insertion-point"></div>
<!-- 2)動的に追加するフォーム(renderで飛ばしている先が追加される) -->
<%= f.fields_for :ingredients do |form| %>
<%= render "ingredient_fields", f: form %>
<% end %>
</div>
<!-- 省略 -->
<% end %>
순서를 따라 설명
1) 추가 버튼의 기술
<!-- これだけあれば動く。あとはオプション -->
<%= link_to_add_association "追加ボタン", f, :ingredients%>
**보충: 여기의 "f"는 form_with의 블록 변수
**보충 2:필수 부분 이외에 대해서는 공식 사이트의 README에 자세하게 써 있으므로, 간단히 설명.
association_insertion_node: 추가 양식을 삽입할 위치를 지정할 수 있습니다. 위의 예에서는
<div id="detail-association-insertion-point"></div>
위치에 삽입됩니다. association_insertion_method: 추가할 양식을 어디로 늘릴 것인가? 위인지 아래인지... (before, after, append, prepend)Default: before. 이외와 어렵기 때문에 여러 가지 시도해보십시오.
2) 동적으로 추가하는 폼(render로 날고 있는 곳이 추가된다)
추가 양식 부분
<%= f.fields_for :ingredients do |form| %>
<%= render "ingredient_fields", f: form %>
<% end %>
:ingredients 복수형·단수형은 model의 기술에 맞춘다
ingredient_fields 파일명: 「_ingredient_fields.html.erb」는 부모의 디렉토리에 둔다. (이번 경우는 recipe).
5. 뷰(동적으로 추가하고 싶은 부분)
_ingredient_fields.html.erb
<!-- class="nested-fields" ←ここ絶対に必要です -->
<div class="nested-fields">
<table>
<tr>
<td class="td-fixed-select">
<!-- 選択ボックス(プルダウン)の箇所 -->
<% thing_options = Thing.order(:id).map { |c| [c.thing_name, c.id, data: { unit: c.unit, spoon:c.spoon }] } %>
<%= f.select(:thing_id, thing_options, { prompt: "---"}, {class:"select", data:{select:0}, id:"thing-select" }) %>
</td>
<td class="td-fixed-spoon">
<span class="box-spoon" id='spoon-auto' data-spoon='0'></span>
</td>
<td class="td-fixed-amount">
<%= f.number_field :amount, class:"ingredients-amount",id:"ingredient-amount", min:"0",step:"0.1"%>
</td>
<td class="td-fixed-unit">
<span class="box-unit" id='unit-auto' data-unit='0'></span>
</td>
<td class="td-fixed-delete">
<!-- 削除ボタン -->
<%= link_to_remove_association "削除", f %>
</td>
</tr>
</table>
</div>
**보충: 이번에는 동적으로 추가하는 폼을 table로 쓰고 있습니다만, 자유롭게 써도 괜찮습니다.
_ingredient_fields.html.erb 파일명의 규칙을 지킨다. 「ingredient」는 좋아하는 이름으로 해 주세요 *주의 * 「ingredient」의 부분은 model명과 맞출 필요가 있기 때문에, 복수형으로 하지 않는다.
class="nested-fields"추가하고 싶은 폼 내용을 둘러싼다.
link_to_remove_association "삭제", f 삭제 버튼의 기술을 잊지 않는다.
참고문헌
추천순
Qiita_【Rails】cocoon을 이용해 친자손 관계의 테이블에 복수의 데이터를 동시 보존하는 방법
Qiita_【Rails】cocoon 친자손의 복수 테이블&복수 데이터를 동시 보존
Qiita_Rails6에서 cocoon
블로그_Rails 6에서 Cocoon을 사용하여 중첩 된 양식을 만드는 방법
이상입니다.
누락 등 지적 있으면 코멘트 주시면 기쁩니다!
Reference
이 문제에 관하여(【Rails6】cocoon_ 동적으로 양식 추가), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/matata0623/items/8868a7fcb6ec0817d064텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)