【Rails6】cocoon_ 동적으로 양식 추가

17446 단어 Rails6Railscocoon
◆ 개발 환경
  • Rails 6.0.3.4
  • Ruby 2.6.5
  • MySQL 5.6.47

  • ◆목차
    1) cocoon 도입 방법
    2) 동적으로 폼을 추가 ←
     앞두고
     1. 모델 작성
    2. 컨트롤러(액션)
    3. 컨트롤러(스트롱 파라미터)
    4. 보기
     5. 뷰(동적으로 추가하고 싶은 부분)
    3) 추가할 양식에 id 및 data 속성 부여

    ★GIF 화상(이런 느낌이 됩니다)
    *주의 * "당근"을 선택하면 분홍색 상자 뒤에 "책"출력되는 것은 cocoon과는 전혀 관계 없기 때문에 나쁘지 않습니다. cocoon은 추가 버튼을 클릭하면 양식의 일부가 추가되는 gem입니다.


    **【부모】recipe【자】ingredient(재료가 늘어나고 있는 곳)

    2) 동적으로 양식 추가



    1. 모델 작성



    (부모)model/recipe.rb
    class Recipe < ApplicationRecord
      # cocoonで子フォームを親と一緒に保存するための記述。accepts_nested_attributes_forというメソッドを使っています。
      has_many      :ingredients, dependent: :destroy
      accepts_nested_attributes_for :ingredients, allow_destroy: true
    end
    

    (자식)model/ingredient.rb
    class 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]
    

  • 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을 사용하여 중첩 된 양식을 만드는 방법

    이상입니다.
    누락 등 지적 있으면 코멘트 주시면 기쁩니다!

    좋은 웹페이지 즐겨찾기