Rails, cocoon을 사용하여 다 대다 양식 만들기 (select 태그 사용)

다 대다 저장 처리 구현



Rails는 평소 사용하지 않을 수도 있으며, 항상 다 대다 양식을 만들 때 어떻게 했습니까? 되므로 메모.
이번에는 cocoon으로 구현해 보았다.

2021/01/23 추가
이 기사에서는 cocoon이라는 gem을 사용하여 구현하고 있지만 FormObject를 사용하여 구현하는 것이 좋습니다.
htps : // 넵트 t. 코 m / b ぉ g / 아 c ゔ ぇ 모로

gem에서의 구현은 빠르고 간단합니다만, 메인테리어되지 않을 가능성이나, 다른 사람으로부터 본 코드의 가독성 등을 생각하면, 이번과 같은 케이스에서의 구현은 gem에 맡겨 버리면 위험한 기분 하고 있습니다.

개발 환경



Ruby 2.5.1
Rails 5.1

사양


  • 코스와 스팟의 관계는 다 대다
    walking_course -> walking_course_spots <- walking_spots
  • 코스를 저장할 때 끈 스폿을 선택하여 중간 테이블 만들기
  • 코스에서 스팟 넘버를 붙인다

  • 우선 relation을 붙인다.



    course.rb
    has_many :walking_course_spots
    has_many :walking_spots, through: :walking_course_spots
    

    spot.rb
    has_many :walking_course_spots
    has_many :walking_courses, through: :walking_course_spots
    

    course_spots.rb
    belongs_to :walking_course
    belongs_to :walking_spot
    

    ※주의하지 않으면 안되는 것은 relation의 순서. through 전에 연관된 테이블을 has_many로 선언하지 않으면 오류가 발생합니다.

    여러 테이블에 걸리는 저장은 nest 속성을 붙입니다.



    course.rb
    accepts_nested_attributes_for :walking_course_spots, allow_destroy: true
    

    이와 같이 기술하면, course의 보존을 했을 때, 동시에 walking_course의 테이블에도 보존하도록 할 수 있다

    _form_content.html.erb
    <div class="form-group">
        <%= f.fields_for :walking_course_spots do |course_spot| %>
            <%= course_spot.collection_checkboxes :walking_course_id, WalkingSpot.all %>
        <%- end %>
    </div>
    

    폼으로 항목을 만들 때는 fields_for를 사용하면 좋다. 여기에 체크 박스의 예.
    파라미터로 취득할 때는, 이하와 같이 기술.保存するテーブル: [: カラム名] 형식

    course_controller.rb
    def walking_course_params
        params.require(:walking_course).permit(
             walking_course_spots_attributes: [:walking_spot_id]
        )
    end
    

    이런 식으로, 사용하면, 체크 박스로 중간 테이블을 작성하는 것은 가능.
    다만 이번에는 이것을 select로 만들 수 있도록 하고 싶다.

    젬코쿤 사용



    여러가지 조사해 보면, cocoon이라는 gem을 사용하면 간단하게 select의 폼을 추가하거나 삭제하거나 하여 중간 테이블에 저장하도록 처리를 만들 수 있는 것 같아서 해봤다.

    gemfile
    gem 'cocoon'
    

    application.js
    //= require cocoon
    
    bundle install에서 Gem을 추가 한 후 application.js에 설명

    cocoon으로 view 다시 쓰기



    _form_content.html.erb
    <%= f.fields_for :walking_course_spots do |course_spot| %>
        <div class="field">
            <%= render 'walking_course_spot_fields', f: course_spot %>
        </div>
    <%- end %>
    <div class="links">
        <%= link_to_add_association 'スポットを追加', f, :walking_course_spots %>
    </div>
    
    

    _walking_course_spot_fields.html.erb
    <div class="nested-fields field">
        <div>スポット</div>
        <div class="col-md-6">
            <label class="control-label">スポット名</label>
                <%= f.collection_select :walking_spot_id, WalkingSpot.all, :id, :name %>
        </div>
        <div class="col-md-6">
            <label class="control-label">スポットNo</label>
            <%= f.text_field :spot_number %>
        </div>
        <%= link_to_remove_association '削除', f, class: 'btn btn-danger' %>
    </div>
    

    link_to_add_association은 양식의 추가 버튼 역할을 합니다.
    link_to_add_remove_association 삭제 버튼

    여기서 주의해야 하는 것은 파일명이 관련 모델명+_fields라는 이름으로 하지 않으면 에러가 되는 점이다

    중간 테이블의 레코드를 삭제할 수 있도록 허용



    저장하고 싶은 컬럼명을 추기하는 것. 여기서 walking_spot_id, spot_number.
    또한, 재 보존시에, 화면에서 삭제했을 것이, 테이블에 보존되어 버리는 사태가 발생했다. 분명히 id와 _destroy가 없으면 테이블 삭제가 작동하지 않는 것 같습니다. 결국, 다음과 같이 되었다.

    course_controller.rb
    def walking_course_params
        params.require(:walking_course).permit(
             walking_course_spots_attributes: [:id, :walking_spot_id, :spot_number, :_destroy]
        )
    end
    



    참조



    GitHub - nathanvda/cocoon: Dynamic nested forms using jQuery made easy; works with formtastic, simple_form or default forms
    Rails4에서 양식 요소를 동적으로 추가하거나 삭제합니다. ~ nested_form | | Scimpr Blog
    cocoon을 사용하여 중첩 된 양식 만들기 - 미카즈키 메모

    좋은 웹페이지 즐겨찾기