Enums를 사용하는 속성에 따라 Active Admin에서 확인란 필터 만들기

12766 단어 Railsactiveadmin
  • Rails 6.0.1
  • Active Admin 2.4.0
  • .

    결론


    Active Admin에서 Active Record를 사용하는 EnumsActiveRecord::Enum의 모델의 속성을 사용하는 필터를 콤보 상자 형식으로 만들려면 Enums의 키-value 매핑을 건네주는Hash.
    # app/models/user.rb
    class User
      enum status: { active: 0, suspended: 1, inactive: 2 }
    end
    
    # app/admin/user.rb
    ActiveAdmin.register User do
      filter :status, as: :check_boxes, collection: User.statuses
      # User.statuses #=> { active: 0, suspended: 1, inactive: 2 }
    end
    
    active/suspended에서 검색

    다음은 순조롭지 못한 상황에 대해 설명한다.

    불순한 상황


    키 목록만 전달User.statuses.keys하면 키 목록만 전달할 때 생성된 폼으로 서버에 제출하면 서버 측이 Ransack을 통해 검색할 때 순조롭게 진행되지 않습니다.
    # app/admin/user.rb
    ActiveAdmin.register User do
      filter :status, as: :check_boxes, collection: User.statuses.keys
      # User.statuses.keys #=> ["active", "suspended", "inactive"]
    end
    
    suspended에서 검색된 레코드만 표시active

    무슨 문제 있어요?


    생성된 창 구조

    check_boxes Enums 키 목록만 Filter에 전달하면 생성된 폼의 input 탭value은 상태 문자열을 유지합니다.
    <div class="check_boxes input optional filter_form_field filter_check_boxes" id="q_status_input">
      <fieldset class="choices">
        <legend class="label">
          <label>Status</label>
        </legend>
        <label for="q_status_preparing">
          <input type="checkbox" name="q[status_in][]" id="q_status_preparing" value="preparing"> preparing
        </label>
        <label for="q_status_transferring">
          <input type="checkbox" name="q[status_in][]" id="q_status_transferring" value="transferring">transferring
        </label>
        <label for="q_status_succeeded">
          <input type="checkbox" name="q[status_in][]" id="q_status_succeeded" value="succeeded">succeeded
        </label>
        <label for="q_status_failed"><input type="checkbox" name="q[status_in][]" id="q_status_failed" value="failed"> failed
        </label>
      </fieldset>
    </div>
    
    input 탭의 valuestatus 키입니다.커밋하면 서버측 Ransack이 이 값에 따라 레코드를 찾습니다.이때 Enums의 속성은 원래 수치로 검색되었지만 문자열을 교부하면 Enums의 최초 요소의 값(지금은 0)이 사용되었다.이 로그는 다음과 같습니다.
    Started GET "/admin/users?q%5Bstatus_in%5D%5B%5D=active&q%5Bstatus_in%5D%5B%5D=suspended&commit=Filter&order=id_desc" for ::1 at 2019-11-22 10:24:30 +0900
    Processing by Admin::UsersController#index as HTML
      Parameters: {"q"=>{"status_in"=>["active", "suspended"]}, "commit"=>"Filter", "order"=>"id_desc"}
      Rendering /Users/kymmt90/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activeadmin-2.4.0/app/views/active_admin/resource/index.html.arb
       (0.2ms)  SELECT COUNT(*) FROM (SELECT 1 AS one FROM "users" WHERE "users"."status" IN (0, 0) LIMIT ? OFFSET ?) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
      CACHE  (0.0ms)  SELECT COUNT(*) FROM (SELECT 1 AS one FROM "users" WHERE "users"."status" IN (0, 0) LIMIT ? OFFSET ?) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
       (0.1ms)  SELECT COUNT(*) FROM "users" WHERE "users"."status" IN (0, 0)
      CACHE  (0.0ms)  SELECT COUNT(*) FROM (SELECT 1 AS one FROM "users" WHERE "users"."status" IN (0, 0) LIMIT ? OFFSET ?) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
      User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."status" IN (0, 0) ORDER BY "users"."id" desc LIMIT ? OFFSET ?  [["LIMIT", 30], ["OFFSET", 0]]
      Rendered /Users/kymmt90/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activeadmin-2.4.0/app/views/active_admin/resource/index.html.arb (Duration: 145.3ms | Allocations: 117153)
    Completed 200 OK in 147ms (Views: 145.2ms | ActiveRecord: 0.6ms | Allocations: 118179)
    
    이렇게 하면 어떤 체크 상자로 필터를 하든지 최초의 요소만 검색합니다.
    정답인 경우 다음 테이블이 생성됩니다.
    <div class="check_boxes input optional filter_form_field filter_check_boxes" id="q_status_input">
      <fieldset class="choices">
        <legend class="label">
          <label>Status</label>
        </legend>
        <label for="q_status_0">
          <input type="checkbox" name="q[status_in][]" id="q_status_0" value="0"> preparing
        </label>
        <label for="q_status_1">
          <input type="checkbox" name="q[status_in][]" id="q_status_1" value="1"> transferring
        </label>
        <label for="q_status_2">
          <input type="checkbox" name="q[status_in][]" id="q_status_2" value="2"> succeeded
        </label>
        <label for="q_status_3">
          <input type="checkbox" name="q[status_in][]" id="q_status_3" value="3"> failed
        </label>
      </fieldset>
    </div>
    
    input 탭의 value 는 정수값입니다. 이 옵션을 제출하면 정확하게 검색할 수 있습니다.이 로그는 다음과 같습니다.
    Started GET "/admin/users?q%5Bstatus_in%5D%5B%5D=0&q%5Bstatus_in%5D%5B%5D=1&commit=Filter&order=id_desc" for ::1 at 2019-11-22 10:22:18 +0900
    Processing by Admin::UsersController#index as HTML
      Parameters: {"q"=>{"status_in"=>["0", "1"]}, "commit"=>"Filter", "order"=>"id_desc"}
      Rendering /Users/kymmt90/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activeadmin-2.4.0/app/views/active_admin/resource/index.html.arb
       (0.2ms)  SELECT COUNT(*) FROM (SELECT 1 AS one FROM "users" WHERE "users"."status" IN (0, 1) LIMIT ? OFFSET ?) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
      CACHE  (0.0ms)  SELECT COUNT(*) FROM (SELECT 1 AS one FROM "users" WHERE "users"."status" IN (0, 1) LIMIT ? OFFSET ?) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
       (0.1ms)  SELECT COUNT(*) FROM "users" WHERE "users"."status" IN (0, 1)
      CACHE  (0.0ms)  SELECT COUNT(*) FROM (SELECT 1 AS one FROM "users" WHERE "users"."status" IN (0, 1) LIMIT ? OFFSET ?) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
      User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."status" IN (0, 1) ORDER BY "users"."id" desc LIMIT ? OFFSET ?  [["LIMIT", 30], ["OFFSET", 0]]
      Rendered /Users/kymmt90/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activeadmin-2.4.0/app/views/active_admin/resource/index.html.arb (Duration: 142.3ms | Allocations: 117716)
    Completed 200 OK in 144ms (Views: 142.2ms | ActiveRecord: 0.5ms | Allocations: 118736)
    

    참고 자료

  • Active Administration frame work for Ruby on Rails의 "Custoomizing the IndexPage" 페이지
  • 좋은 웹페이지 즐겨찾기