active_scaffold_sortable 3.6.2 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +267 -0
  3. data/app/views/active_scaffold_overrides/_form_association.html.erb +1 -1
  4. data/frontends/default/active_scaffold_overrides/_list.html.erb +1 -1
  5. data/lib/active_scaffold/config/sortable.rb +5 -5
  6. data/lib/active_scaffold_sortable/version.rb +2 -2
  7. data/lib/active_scaffold_sortable.rb +1 -0
  8. data/test/attribute_params_test.rb +69 -0
  9. data/test/auto_models_controller_test.rb +51 -42
  10. data/test/config_test.rb +44 -37
  11. data/test/controllers/ancestry_models_controller.rb +8 -0
  12. data/test/controllers/auto_models_controller.rb +2 -0
  13. data/test/controllers/models_controller.rb +2 -0
  14. data/test/controllers/nested_set_models_controller.rb +5 -0
  15. data/test/controllers/sortable_models_controller.rb +2 -0
  16. data/test/dummy/app/assets/config/manifest.js +1 -0
  17. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-0/-01A5W7YK9kU3BAS800iZYKE1Jjr-mMTZS7fQ87Rx9Y.cache +0 -0
  18. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-2/-2oLK5aS0W7YRh6DWw7gleUOPUgPQHe3WA-XlTeeQ6I.cache +1 -0
  19. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-3/-3JSgLkvqrbXhc6cV7vAvXuo40s6t9QfDEvko0kGqHY.cache +0 -0
  20. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-5/-5b8vqL4AFE9S1wXk_ZysEvjY3K9KSkap5rhGfqbAns.cache +0 -0
  21. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-D/-DnuHI88d2RugNRU74FFqmOIb9ctTsdUQh0DlMENCyo.cache +2 -0
  22. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-x/-xveB5ZfM-eQ6NKFAdea3lFoN1vnudJ5LvZSRuzKQ_A.cache +0 -0
  23. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0B/0BKtmzv1AlH_D8ePKCo6cK758902Yb9LuqMKD1YYRCI.cache +0 -0
  24. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0R/0RBP8nKamBasZw5QxqMbxS-0qm_HmB-IrbHuLY5EkAE.cache +1 -0
  25. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0o/0oBXAn_gNl9ci2FebzcrXp5muYP0gkwyuICM_2XgZSM.cache +2 -0
  26. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1G/1GbJS0MAW1RcmPPFOzvRIWmCWnuRzHFpzYtbrSf9kn0.cache +3 -0
  27. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1e/1epYXgb89BkEMcjSsF8ZneNxpnJd7CwQYPoeukBAUPk.cache +1 -0
  28. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/24/24C1vwwkvwnqO43YwbPnrtooBEgS2hzFxyGb5UIQ_z8.cache +0 -0
  29. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2F/2FFeltlt3UB92gSStDW3dCExS323nvlf8jnLx0AQT7U.cache +3 -0
  30. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2T/2TEBf82sw5GOia5tXBuC6_qcelFGyl_BiMd5t2mRo3I.cache +1 -0
  31. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2X/2XvO4DdiQnv9iimEOceo5KSLzXyIpsH9zJPy0-G-mWw.cache +0 -0
  32. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2e/2ejWr7IoRaAvGd2C8f9UZYwIeAFYcrQo97m9SM5XvG0.cache +1 -0
  33. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2s/2sGAQ3lUIHy362ttHb99ML7tixBpnZ0gAE_1gjC5QNc.cache +1 -0
  34. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/38/38pY3RTKFmdKPW92BesHrVZZ5hOgBN2ZOMpg8Pfeq8o.cache +0 -0
  35. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3V/3VQHyC_HOI6vTzyOFRqKgqBaibU0LvqY-vHrz2VsLe4.cache +0 -0
  36. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4T/4TPtaEh2eMInSYN2oh7Pc5iDR4qR41inNfWu2Z3-4d4.cache +3 -0
  37. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4Y/4Yd3Q4u1iCSnYLn28-EcjXomhSB9VJvBrsDuT5feMgE.cache +1 -0
  38. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4c/4cYrHjoGTnsvI5Bxiol1DP1Cl17-8kMS0cA9d8QVvl4.cache +1 -0
  39. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4c/4cx0kSMnteO1fMuTu1ldK4SK3T4qBMmFqHpYBEJIl1M.cache +2 -0
  40. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5F/5FPfSxfXAzfMqbv9MYp_oPqDqCp5Ti42XqV96raVNmY.cache +1 -0
  41. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5R/5RmcFexTZX4RML0m9HNAEogOkz6kAUnL1XAycQBQF68.cache +3 -0
  42. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5d/5d7byxXxH0tYfzrL1xmvvOK3IWGWYmbIGYVFfFaE9dY.cache +1 -0
  43. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5g/5g89-0a4fx7-hBM92_O2WNgdJMrUC5NJEbpBvAleVWU.cache +0 -0
  44. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/63/633hFkOuEJb_oUSK8cX03s1n2fLSTEb5NdC4cDIwpwA.cache +1 -0
  45. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6j/6jKoXrSpfNRDsyNX4Zt6bH298l8LflVJ8bYAKsaHzzE.cache +1 -0
  46. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6v/6v3hLMm6-Nd9GuMM_2saYxwsHtPGQIbkupZG2vvqa-c.cache +0 -0
  47. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7P/7PY1-QqnAkLe9n-nRR-vrU2Fzd5MdehED9jP8erf8eo.cache +0 -0
  48. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7a/7a8xYHOtPE4wTHEMmm6noe1konW7gY0PUSm0IBNTMtI.cache +1 -0
  49. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7d/7d4afpWdI5JNwQ5cItnECrWVgm4tCn8n0JvJTD4T3qs.cache +1 -0
  50. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8A/8Awct50GB7qO_BjbGb7z6tLppN4-Zkvgw2MOYqw6YZM.cache +0 -0
  51. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8G/8GByrSoo2FlXP9v-YtRr3mXAlELF8VORWoHShm6nDdA.cache +3 -0
  52. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8c/8c1AnZluzIU5mA6hxvyQIdoKGWB_gGzUtUbmAL-EMi4.cache +0 -0
  53. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8v/8vSTgcVfo7zRgOO9tDN887A2SISF1N6LaLE0SwEienU.cache +1 -0
  54. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9V/9VuN8VYKTVYvAFQ8Og_aBqpRpiGxuy0Et3roDr_okqk.cache +1 -0
  55. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BG/BGKeBGsHVMizN9unVFE6OuxZYBGKG1t6r-cH4MYW3LQ.cache +3 -0
  56. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BQ/BQStLknXZiiwpMoPe6YrBxnBD-1wDEEN8k1mYrJ3Uxw.cache +1 -0
  57. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BW/BWochnvJlhWYZdwSmq6mz-jEixAT70nDd-v2kKu9vqw.cache +0 -0
  58. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/C-/C-7R1F-IclQa7n3Hd4qJnLbBAU5Pcu7LxaVCrdCpGm0.cache +2 -0
  59. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CK/CKhIMyvEb6CDyLEFjVWINYFKmLJ4PP4loyBb9TSRuMY.cache +0 -0
  60. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CP/CPRlIspialBD_8QWdu_BfuiA-0NiaCIAIjENtD1GTVM.cache +2 -0
  61. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CV/CV9H0CtTQ90oOjk85ymAap-0weDW8crx2mv9iWwADxs.cache +1 -0
  62. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Cs/CsQ51viK_aIp-m7ZlSFOnb4sFWpBNWaZblmvpPZAPZM.cache +1 -0
  63. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/D6/D6Qu6xXoQxwWWu9I8MH06EV_ZCDIdkd1C30t_qGVDNI.cache +1 -0
  64. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/DN/DNjqY8NAzkt9P2e6Y6nhm_lDGdHAmeYStAwysDr_XI8.cache +0 -0
  65. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Dv/DvsUO7WNA9YxClJwRzWSEzvC1WbUiIqoELa81jklXnU.cache +0 -0
  66. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fa/Fams27IUjgGgDYh4ZebQLOL2ZVlyXeObh0zGm7L7itY.cache +1 -0
  67. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fd/FdwcZofVKxaRa1PHEqgrVNOb_NfhW7AkOaQr8Jpd8F8.cache +1 -0
  68. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fi/Fix6os7onITNYUoeQXZIZ9ipaPXY8qveVp544iQ2pu0.cache +1 -0
  69. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fo/Foxj9g0CYVowTIQC5l3ont29y6kzyjq1tCto_XmD1Y8.cache +1 -0
  70. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gm/Gmx2uSucvix2U85bFcJwdUiK4W0_l0ktmUpZYH0kuh8.cache +1 -0
  71. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/H5/H5jANW5FBiru_dQ2zHyOLCXrUutOhHWVccsPOlHjPlw.cache +1 -0
  72. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I8/I8Di5A_iVdMQnWl8i0jR1EDPY-zGKXRsX6FrHOUKY_k.cache +0 -0
  73. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/IG/IGLiMvn8Ia3obsUVYlf5H2Pc4hMVBXoHVrCh_BbHeos.cache +1 -0
  74. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/IU/IU3Vj0C_4HJivemzxbufqxLy3uOizcW6mjksAApYonI.cache +3 -0
  75. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/IV/IVzbuuk4Y8uceJaYEi3eHzZ3L3-X9_RyiKuV2mjuq14.cache +0 -0
  76. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Im/ImYjTVLdbIdhT9HmAR5592TGiS6do4CU5aTM57NDtF8.cache +1 -0
  77. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Jo/Joc7W-HUxa_SCuMY1ji3Tb_anGXmH8dXBLEIl7y3qQY.cache +1 -0
  78. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Kp/Kp1mrZLRWB7EWOtPVpLqGWKv-kIAAM_cHpkoYEASq0k.cache +1 -0
  79. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Kp/KpOG7KGgj5QGIvXgdmmMNmNLcDzUNj0-HRArprvTc2M.cache +1 -0
  80. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Kr/KrnWYZN30K4B7kS4tYoFPc2uvUXN4wq4R-zg1s8Pte8.cache +1 -0
  81. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/LB/LBAH0XPkrk6feDLGh6rjc-oRVjDHWf09jT2s1OF0DGk.cache +1 -0
  82. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/LK/LKdhU8uwD92K_SdC7Tg_nnk32QEeIHGK5PnSSsQB1GU.cache +0 -0
  83. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/LX/LXRQyuA2BiXpXNe-2PIOPP_gfu2J9r8ECfinQWs5Pn4.cache +3 -0
  84. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lt/LtK_Npm-kOHPrwrpfOkzvivUSMv9C35TO8kccAJFAoE.cache +0 -0
  85. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/M-/M-zp45dW9TWoC7zAUn3L2BwKG2a6gagSXpG8nSyMg8g.cache +1 -0
  86. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Mv/MvW2Dl5BoobN-SWNyCaxMP47Ihyd8e8UCEcYVeDkEr4.cache +1 -0
  87. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Mw/MwZE2PNpy_0-Qa3_iv7j25MuGl-1OZUO2XkDoomSyQc.cache +1 -0
  88. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/NP/NPs6FRY1WbljwZoGarj2bqozBfutuaWBe3nVfrQ2A-k.cache +2 -0
  89. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/O7/O7ygnT4NqWCR5SU1qTty3j0909VVtEN7SqVI3exJ1Fs.cache +0 -0
  90. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Oj/OjnYwM2pcnX18Fnj3AKBYJslH-_oI-eJFr1jKF_bec0.cache +1 -0
  91. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Om/OmD88cOkZnce7jiIW_uKN5UzecfSk7LPBHUWdr9nuaY.cache +1 -0
  92. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/P1/P1RCU1-eTX730fxykGCghfCTNXe74fdWitwW7p0lux0.cache +1 -0
  93. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/P5/P5ifL2bLkG9zc7oNXwYKCzsAZLzKY_bHqBAQf64TnFo.cache +0 -0
  94. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/PB/PBNeP5ORDO5a3Tn1n5hEA4OS0JTbGgGuyupEljHYK-Q.cache +1 -0
  95. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/PJ/PJDpkmr3C8KVM9BqbaUPLH4L5f0xWtRDo3wc4vuvtTw.cache +0 -0
  96. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pa/Paylg2dvY4FEVeol8QRGXmnlmSxW9iAhrhu8WUIH_2E.cache +1 -0
  97. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pc/Pcgbo3Rysr6BlArqxHR4qLirVHsynsi_FRV-fndn8Hg.cache +0 -0
  98. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Q1/Q1opUEyDInXXYe5UDccDz438AyblZ0oiavmzG2BDFJc.cache +1 -0
  99. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Q7/Q7La6t5hz_qGvKi59nbxxnhObRb0nHwdofHEDbNLYGI.cache +0 -0
  100. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Qh/Qhnmild8NLF6AJmiUOCxEq6l4V9WDM46gt3iKNUpfGE.cache +0 -0
  101. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ra/Ra8PGm0CtdBdRARR5KsiT2Iv-P3wZNe55vCNqu4qdM8.cache +1 -0
  102. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Rx/RxmsaxLeIQ5xwIZ14vz5ehoc_6TjP5Rpa3CRny4tWG8.cache +1 -0
  103. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/SA/SA8b2a-PX1nDgzdCcJaBTW8Y2qQfBeKvrsNd2FHV9kk.cache +3 -0
  104. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/SO/SOAX-5LQ2QKMVKgYM3-vLvqxZEFV7aXqi6T0nHK8JdE.cache +0 -0
  105. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/SS/SSg5bDqJBLv8UDn6NjSt-28FTDnXrmr4lm3-qD-gzlg.cache +1 -0
  106. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Sb/Sb2EeQPQyWe0nb2aId-BRi76gdNMbx-_b7oDXu_--3I.cache +1 -0
  107. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Sh/ShqS7p9Dz8B0KnsOEeur1lGGb96LoW2Tufapu6vRYQQ.cache +3 -0
  108. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Sn/SngbFvFTz9jtho3VfcDRkhi5KvV5mNXHtZ3faRj0mq0.cache +1 -0
  109. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/TJ/TJXSOh8D6dsgfhXh7KlzynHOrYwXy9yi0YKdvZlwS2M.cache +1 -0
  110. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/TR/TRWPFjvokQ5AmFcLYZk5OlgmDulZ1HeMWnwASg_0tDA.cache +2 -0
  111. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/UZ/UZkjDOYpoE1pwHlkI402W8lj58qyM9pbBo0Jmqwnh_M.cache +1 -0
  112. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ut/UtUl8dEEP8OUFS138GTWLf8TE8FhJYK5c1vaXAmRM_E.cache +1 -0
  113. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VR/VRDKUY6-sXjrwpqcbxGHgP9_ONi3gwEVncUA1uzJPV8.cache +3 -0
  114. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wl/WlFfd39WfPdb8ecb3P-6msbwc6U1rpZ67MkPGvuwwPI.cache +1 -0
  115. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wl/WlNGLojqnKVWTZGT6xG9pS4_52XBnkQaDrxPeLOjfG0.cache +0 -0
  116. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wo/Wo7IjVQE59FU0N57DfY8aS_EhOHYTevXt2w-A6GG1OE.cache +0 -0
  117. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wp/Wp_HHYHjzz0iw5PQ3uWhju_JwBeuUmjrFE-w9P7TiJI.cache +1 -0
  118. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wt/WtsclIiibz_nWtYI4bN1ogz2DouCxLxRhZ4To_veN6c.cache +1 -0
  119. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X6/X6rI-YDY0BKCdMA_eQAK3u_bZOrZxe7wtn_t4wjcyGM.cache +3 -0
  120. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Y2/Y2GMeqGBGgWrYZmI2sZO62LNEPoBGJ1bF9nRF5tHo30.cache +1 -0
  121. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/YL/YLRMkD5PzC_acvA63jrF8Q_ImDPecqclwDlUHfU6tFk.cache +2 -0
  122. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/YQ/YQfKqw0LUSliN1R029iBJ-Q5rvPflUcQMcBaQUy9tHI.cache +1 -0
  123. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/YY/YYt9duEQUzPtfzFEbyThgE8axhVDyynnMHRsJ7ivmfU.cache +1 -0
  124. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Yb/Yb6WF-FKlg7AX5I1fBtUVFJwGZ9lZng-WBXOWcNKBFI.cache +1 -0
  125. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Yb/YbSqwPYrjO2_pDN9Gar6NmrSu9uPMQVK6bOg9t6rLQE.cache +0 -0
  126. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZD/ZDax1kp2GkGUgRyO0nM0Rrg_AqtpocNI69dbDijDz-o.cache +3 -0
  127. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Z_/Z_J_urKomTrgc54gT_yMF77dy5dvTc4o8tP9xBT0Ei4.cache +1 -0
  128. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_9/_96XOgK4uLAgBpmlNxMhvpSKR0RACQPa7b8Zs7JvFhM.cache +0 -0
  129. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_e/_eGqFuynzxHdBcyQcb39R3gIpkw8pJHIpIb2d3y4Wgw.cache +1 -0
  130. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_k/_khcJKAEuVGqYQyMhPgrorWWBci3uioHdU_rRWHor5U.cache +3 -0
  131. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aW/aWhzKkJzJA3zSzcyHgvAH6gY0wtH9AvCwrPfGn0yinQ.cache +0 -0
  132. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bf/bfvmq2y8rZqB0uY7rAOUlBowZqo6ufc_5nfG1LYwzBA.cache +0 -0
  133. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bw/bwhovo7do9KWTEDh74VaX0SkTZ9rVlapdjDGGsOkYoA.cache +3 -0
  134. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dA/dAk68mPJqLTk4teOIIYt_aLVM14EOuIxA9fCCeBrKFE.cache +1 -0
  135. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/df/df1Eyp3Nlhb2MpTqIOUTNLPF3zLZm8glepkhoAgalaU.cache +1 -0
  136. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eH/eHywcNwiONssCBDpivCVg95qXNqh3DG7IW-Gn09y_WI.cache +2 -0
  137. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eW/eWSTSytTG9nrCXUXlFyNTT2SnQNavB-7ZHbQJdzRW78.cache +0 -0
  138. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ea/eaG88T0kV6x-aQgXngib2_5TkPRHcQUsNeRwyBFvTxw.cache +1 -0
  139. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fR/fROdNnXbOkrkCX0VjA67bx-85BNOcWA-pr9oNeTX-6U.cache +1 -0
  140. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fZ/fZszKxkZvRa-5uIuGwojHFzFDfTBdaghYq0YuSDd0fg.cache +0 -0
  141. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/h2/h2jllO4xPhzz7DDl4giyfC-M-KE2kBHbFjbKneUaH0s.cache +0 -0
  142. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/hG/hGOgAdR_N4noGNRRx25KqnZDGCE4OtVHqBvMAxHqVCI.cache +1 -0
  143. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iA/iA5sBAvo4LBx2bolG45IV3j3VAir_HgEFaYJSU1CsuI.cache +0 -0
  144. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kA/kAE78w1XBkLkUmFIMRQaeSzbVb4I5djjXPgd9rVMQak.cache +3 -0
  145. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kS/kS3sp7MRq8LQbBTY9WRRMfWcKyqYZG0V9KSs9JlIDPI.cache +1 -0
  146. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ka/ka1yaE-uG5A54kvAVKscIBd4DGwDGOnLpCk6EV4NeK8.cache +0 -0
  147. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kj/kjHBBL52Qb2LGmXskl7pye9EKuqYX23L_DKk5H-jTCY.cache +0 -0
  148. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kt/ktYvvoV5OLXgOJ-0uUmNrJzScE6jrUD1r0VeS7rToRI.cache +0 -0
  149. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kw/kwcepSV0CIKivTUVXF3xfeIHW4sLfQta700qqhtx-PA.cache +0 -0
  150. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/lk/lkd5ZZsrE9KoB6uUBMiHYDIf7nUofIZ0zUzTQhw3q5M.cache +1 -0
  151. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/m5/m5zl3ZQ9497Ws3dcM25-9xPXK7EHZhM8lN_sGgEkDao.cache +1 -0
  152. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nN/nNeCvN6msedBHaJP2LDnQQcMItRJFjRBEoNrxJIJsqA.cache +0 -0
  153. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nj/njx8yCFK0rUv9-EODcBOR1dqntXG_qErD4GKmlLVP5U.cache +3 -0
  154. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/o7/o7uGfsn8XAZCoxgv-xvAx64lNhXKqHROrnQ0eM67ShI.cache +3 -0
  155. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oi/oiR9kx7NN7FtqW4tuxAqKuMbTzntnD4h4vtvnEzHJJs.cache +0 -0
  156. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/om/om6KTDfdJHGdhoscNLPYOkzi9bALNxlUp7Ax_uVS3LY.cache +1 -0
  157. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/op/opp4OeslOryoI1PDbzk_OMlXuQGqNjp5R-BoWFPinqk.cache +1 -0
  158. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ox/oxrsONd2_TIlLWaYwbrbwvAoFIr4XYacRKStijLPMhs.cache +0 -0
  159. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pC/pCI6lsX8vSY57jAP9xHgpaaxzxIv1qwGBtNzxfbtWL0.cache +3 -0
  160. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pD/pDRTkMgfNorje-QH5KBHWyIJr4V7Kk0cektjtCKzsHQ.cache +0 -0
  161. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pS/pStecU0QLgBBJhrlftzFIOIny1_1eJQ1wb006wR6hHI.cache +3 -0
  162. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pc/pcZ1fITskNzguH0ctYLXa_J-6KYGEwEZim8Zi7HHWuw.cache +2 -0
  163. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qC/qCk8n9E10BaN-4MSbOGm-aOocRuvKbUwnEzFSOEnyMk.cache +3 -0
  164. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qF/qF4Jxo_QusqFxZlTUufstoSMqM8BwxOeBYeeaUlMQMM.cache +0 -0
  165. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/rN/rN0TBip7LVkikWIt7pr5pXpebCMu-Vszwr3JtNl85Rg.cache +1 -0
  166. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/re/reY88CfGWWiGlDTj_aT-R1IQ4HwtgJ8M4x2QSZi3g1k.cache +0 -0
  167. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/rf/rf9yIxeJnjcgy1j_Z0ZaBP5o1fRWnI4s6RKqXtXnfNY.cache +0 -0
  168. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/s4/s4H_e7Jtc3bYP6_jcDC1djtCN0zmdIjgfCjszHdyYSU.cache +0 -0
  169. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sb/sbZBtfS1lz5ysnVhxOHQ3uQx2vuw0Dml_N69G5SnVSg.cache +1 -0
  170. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tM/tMjri0obeX3cWblgB5ANaxvz2r1Un5w-kdAgV2mnBUw.cache +1 -0
  171. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tR/tR4pe9KUkOD0dXQr0Rmz49lhvtLaTX2Va99AozZ-_tk.cache +3 -0
  172. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tR/tRmf4Ta_ZHZRBt4KuyLVmN-3QgPG4aCqy3nqmLrjTlE.cache +1 -0
  173. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/u-/u-1XahJaVW5YYTRugzlxdg6JhZoVk2UMhLaJF3O1vg0.cache +0 -0
  174. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ub/ubOIJHHBsVau6eMNKfZu9D07kkX2uEsMNChK5vWQoQU.cache +2 -0
  175. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/uf/ufSwWA73VH7bS7CMeQp_vUlRYsZNh4Hl_SxJORHxBs8.cache +1 -0
  176. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vI/vIR0VWobVpWydqbzq29IQ84VRHCYBzdk3YTRh4UbH1w.cache +1 -0
  177. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x_/x_AI1EzZWPpRoWC6lFtm6rpp5lycO0l-JeoBiiBsQuU.cache +2 -0
  178. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xe/xeBZETuoTTj0K-JS67s72_rtxLpAvc5L731R6Q8CjLw.cache +1 -0
  179. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xl/xlv-FINzwAUI9lLqHtM8Ml6TcP0fI1T7_1hASqmh1uw.cache +1 -0
  180. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xp/xpBi9YqwkljWG2uwGCwVtJFrzwGTNWjKSg_9YqqxsG0.cache +0 -0
  181. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yb/ybfHSoG4-2Xqjkk-hkTD4fAGZIBZWkIyHcBlQjIovJI.cache +3 -0
  182. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yk/ykudLIz9khw9ygFAJSj1FFiZFv8gE8hQqykRNB9gLNI.cache +2 -0
  183. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yr/yrLtWJQXs4lm9sonGNHNkFRzm8xpmrWQwGZHjIh5qXs.cache +0 -0
  184. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/z-/z-PkdiKIZoqXSf6edzu84RnR9qQGGL_iD94rf6GSy-0.cache +1 -0
  185. data/test/models/ancestry_model.rb +16 -0
  186. data/test/models/auto_model.rb +3 -1
  187. data/test/models/model.rb +2 -0
  188. data/test/models/nested_set_model.rb +39 -0
  189. data/test/router_test.rb +10 -3
  190. data/test/schema.rb +9 -6
  191. data/test/test_helper.rb +47 -36
  192. data/test/tree_models_controller_test.rb +70 -0
  193. metadata +357 -10
  194. data/README.textile +0 -76
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e080d7dbf184a9845ee2389bbc5ad590bf50894a30be8a30b9ec512d3c2d2e89
4
- data.tar.gz: 638473b92cb73a2d5f054706dae8850a08b7ac59725f3f6ebd65448d3c4a24a4
3
+ metadata.gz: 33121e6e1386e4f3802c52e705127873fae644c4058fbf76de119494c281c8fa
4
+ data.tar.gz: df471b954ff70f91201355d63deebae589be6410ccd2b518391f7b00dabbfad5
5
5
  SHA512:
6
- metadata.gz: 844cd386840e54256757aca121b0cbb809424ba7fb704bbf7a31c9463b19960f798515dc922e2cedef172cc7e79a1823a6e691d1cc2e95235c3b856490bf2f8d
7
- data.tar.gz: 6f556e8a1e290a0668a9d8e2be40aa275a69ef21232628e7358962426b090822f92f5b07f07fa39e6ad13f9128154c05f84c2cc99b651a0b84d77987bba6689c
6
+ metadata.gz: 24b658744b23cdec8a02d8312810e9577a8a49aeb5a0456d40e8e6c2d791a032497cf33e82428437383aae37fd4c8ebcea21f8d76096828003169b3920ac22bd
7
+ data.tar.gz: e3da06ae6819c09b945eaa66eb9d74df23802e06a952a96f4b7847156d8b064de66ff576a6ecbf73136a9cd688118b6295fd5e23f74bd1a18b81543f691d3911
data/README.md ADDED
@@ -0,0 +1,267 @@
1
+ # Drag-and-drop sorting for Active Scaffold
2
+
3
+ `active_scaffold_sortable` adds AJAX drag-and-drop ordering to Active Scaffold
4
+ lists and association subforms.
5
+
6
+ It supports:
7
+
8
+ - ordinary ordered lists, including automatic setup for `acts_as_list` models;
9
+ - sortable `has_many` association subforms;
10
+ - sibling ordering in nested-set trees using the `awesome_nested_set` API;
11
+ - sibling ordering in [Ancestry](https://github.com/stefankroes/ancestry)
12
+ trees;
13
+ - a dedicated drag-handle column, optional list refreshes, and custom DOM
14
+ selectors for non-standard list markup.
15
+
16
+ ## Requirements
17
+
18
+ - Ruby 2.0 or newer
19
+ - Active Scaffold 4.4.0 or newer
20
+ - a Rails version supported by the selected Active Scaffold version
21
+ - jQuery UI Sortable on pages that use this plugin
22
+
23
+ For Rails 3 applications, use an `active_scaffold_sortable` 3.2.x release.
24
+
25
+ ## Installation
26
+
27
+ Add the gem to the application's `Gemfile`:
28
+
29
+ ```ruby
30
+ gem "active_scaffold_sortable"
31
+ ```
32
+
33
+ Then run:
34
+
35
+ ```console
36
+ bundle install
37
+ ```
38
+
39
+ The engine registers the Active Scaffold action, route, JavaScript,
40
+ stylesheet, and view overrides automatically.
41
+
42
+ ## Ordered lists
43
+
44
+ ### With `acts_as_list`
45
+
46
+ Add a position column and configure the model with
47
+ [`acts_as_list`](https://github.com/brendon/acts_as_list):
48
+
49
+ ```ruby
50
+ # db/migrate/..._add_position_to_entries.rb
51
+ add_column :entries, :position, :integer
52
+ add_index :entries, :position
53
+ ```
54
+
55
+ ```ruby
56
+ class Entry < ApplicationRecord
57
+ acts_as_list
58
+ end
59
+ ```
60
+
61
+ The plugin detects `acts_as_list`, enables the `:sortable` action, and uses
62
+ the model's configured position column. No Active Scaffold controller
63
+ configuration is needed.
64
+
65
+ Scopes configured in `acts_as_list` still define the logical lists. A rendered
66
+ Active Scaffold list should contain records from only one scope so that a drag
67
+ does not mix independent lists.
68
+
69
+ ### Without `acts_as_list`
70
+
71
+ Sorting can use any persisted column that accepts one-based integer positions.
72
+ Enable the action and select the column explicitly:
73
+
74
+ ```ruby
75
+ class EntriesController < ApplicationController
76
+ active_scaffold :entry do |config|
77
+ config.actions << :sortable
78
+ config.sortable.column = :position
79
+ end
80
+ end
81
+ ```
82
+
83
+ On every drop, the visible records receive consecutive values beginning at
84
+ `1`. Updates are made directly with `update_all`, so validations and model
85
+ callbacks do not run. If the table has an `updated_at` column, it is updated.
86
+ The reorder action uses Active Scaffold's update authorization check.
87
+
88
+ ## Sortable association subforms
89
+
90
+ A collection association is draggable in a create or update form when the
91
+ associated model's Active Scaffold configuration includes `:sortable`. This
92
+ works whether sorting was enabled automatically by `acts_as_list` or manually:
93
+
94
+ ```ruby
95
+ class TasksController < ApplicationController
96
+ active_scaffold :task do |config|
97
+ config.actions << :sortable
98
+ config.sortable.column = :position
99
+ end
100
+ end
101
+ ```
102
+
103
+ For example, a `Project` form that renders a `has_many :tasks` subform will
104
+ allow its task rows to be reordered. Dragging updates the hidden position
105
+ fields in the form; the order is persisted when the parent form is submitted,
106
+ not through a separate reorder request. New associated records without a
107
+ position are placed after the highest existing position.
108
+
109
+ The association must be a collection. Singular associations are not sortable.
110
+ The associated scaffold may exclude the `:list` action when sorting is needed
111
+ only in a subform.
112
+
113
+ ## Tree models
114
+
115
+ Tree support reorders nodes only among their current siblings. It does not move
116
+ a node to a different parent.
117
+
118
+ ### Nested sets (`awesome_nested_set`)
119
+
120
+ Models using
121
+ [`awesome_nested_set`](https://github.com/collectiveidea/awesome_nested_set)
122
+ are detected automatically:
123
+
124
+ ```ruby
125
+ class Category < ApplicationRecord
126
+ acts_as_nested_set
127
+ end
128
+ ```
129
+
130
+ The plugin enables `:sortable`, uses the model's configured left column, and
131
+ calls the nested-set movement methods to preserve valid left and right bounds.
132
+ Root nodes can be reordered as siblings as well.
133
+
134
+ Detection is API-based rather than gem-name-based. A different nested-set
135
+ implementation may work only if it provides the same API used here:
136
+ `nested_set_scope`, `left_column_name`, `self_and_siblings`, `move_left`, and
137
+ `move_right`. `awesome_nested_set` is the intended integration; no other
138
+ nested-set gem is explicitly supported by this project.
139
+
140
+ ### Ancestry
141
+
142
+ Ancestry models are recognized during reordering, but they are **not** enabled
143
+ automatically. Add a separate position column and configure sorting manually:
144
+
145
+ ```ruby
146
+ class Category < ApplicationRecord
147
+ has_ancestry
148
+ end
149
+ ```
150
+
151
+ ```ruby
152
+ class CategoriesController < ApplicationController
153
+ active_scaffold :category do |config|
154
+ config.actions << :sortable
155
+ config.sortable.column = :position
156
+ end
157
+ end
158
+ ```
159
+
160
+ The submitted records are reordered within the first record's sibling set.
161
+ Both root nodes and children are supported. The `ancestry` column itself is a
162
+ path, not a sibling position, and should not be configured as the sortable
163
+ column.
164
+
165
+ ## Configuration
166
+
167
+ ### Drag handle
168
+
169
+ By default, the whole row is the drag handle. Add a dedicated handle column at
170
+ the beginning or end of the list with:
171
+
172
+ ```ruby
173
+ config.sortable.add_handle_column = :first
174
+ # or
175
+ config.sortable.add_handle_column = :last
176
+ ```
177
+
178
+ Only `:first`, `:last`, and `false`/`nil` are accepted.
179
+
180
+ ### Refresh after reordering
181
+
182
+ The default response only reapplies alternating row styles. Refresh the entire
183
+ Active Scaffold list after each reorder when other displayed values depend on
184
+ the order:
185
+
186
+ ```ruby
187
+ config.sortable.refresh_list = true
188
+ ```
189
+
190
+ ### Advanced DOM options
191
+
192
+ `config.sortable.options` is merged into the sortable container's `data-*`
193
+ attributes. Supported overrides include:
194
+
195
+ ```ruby
196
+ config.sortable.options = {
197
+ tag: "> tr", # selector for draggable items
198
+ handle: ".my-drag-handle", # selector that starts dragging
199
+ content_selector: ".my-records", # sortable content within the container
200
+ key: "as_entries-tbody", # serialized request parameter base
201
+ format: "^[^_-].*-(.*)-row$", # extracts the record ID from a row ID
202
+ with: "scope_id=42" # extra reorder request parameters
203
+ }
204
+ ```
205
+
206
+ These are integration hooks for custom Active Scaffold markup. They are not a
207
+ general pass-through for every jQuery UI Sortable option. When overriding
208
+ `key`, keep it aligned with the parameter name expected by the reorder action.
209
+
210
+ The same settings can be used as defaults for every sortable scaffold. Set
211
+ them in an initializer before Active Scaffold configurations are built:
212
+
213
+ ```ruby
214
+ ActiveScaffold::Config::Sortable.add_handle_column = :first
215
+ ActiveScaffold::Config::Sortable.refresh_list = true
216
+ ActiveScaffold::Config::Sortable.options = { handle: ".my-drag-handle" }
217
+ ```
218
+
219
+ ### UI adapter support
220
+
221
+ Sortable list and association-subform wrappers expose the
222
+ `sortable_container` UI element. UI framework adapters can add or replace its
223
+ HTML attributes without overriding either partial:
224
+
225
+ ```ruby
226
+ ActiveScaffold.add_element_attributes :sortable_container,
227
+ class: "overflow-auto"
228
+ ```
229
+
230
+ The plugin keeps the `sortable-container` class and `data-*` attributes used
231
+ by its JavaScript and merges them with attributes supplied by the adapter.
232
+
233
+ ## Effects on the Active Scaffold list
234
+
235
+ Enabling `:sortable` also:
236
+
237
+ - disables pagination so all draggable records are present in one list;
238
+ - orders the list ascending by the sortable column;
239
+ - disables sorting by other columns;
240
+ - hides the sortable column from normal action columns and configures its form
241
+ UI as hidden so subforms can carry positions without displaying the column.
242
+
243
+ Because the browser submits only rendered rows, filters and nested views update
244
+ only the matching subset. Non-rendered records retain their stored positions,
245
+ which can produce duplicate positions in an ordinary list. Keep each sortable
246
+ view within one logical list or sibling set, and use filtering with care.
247
+
248
+ ## Support
249
+
250
+ For help, use the
251
+ [Active Scaffold discussion group](https://groups.google.com/group/activescaffold)
252
+ or [open an issue](https://github.com/activescaffold/active_scaffold_sortable/issues).
253
+
254
+ ## Contributing
255
+
256
+ Fork the [repository](https://github.com/activescaffold/active_scaffold_sortable),
257
+ make the change with tests, and open a pull request.
258
+
259
+ ## License
260
+
261
+ Released under the [MIT License](LICENSE.txt).
262
+
263
+ ## Authors
264
+
265
+ - Tim Harper
266
+ - Sergio Cambra
267
+ - Volker Hochstein
@@ -1,6 +1,6 @@
1
1
  <% config = active_scaffold_config_for(column.association.klass) %>
2
2
  <% if config.actions.include? :sortable %>
3
- <%= content_tag :div, render(:super), :class => 'sortable-container', :data => sort_params(config).merge(:tag => "##{sub_form_list_id(:association => column.name, :id => parent_record.try(:id) || generated_id(parent_record) || 99999999999)} > .sub-form-record") %>
3
+ <%= as_element :sortable_container, render(:super), class: 'sortable-container', data: sort_params(config).merge(tag: "##{sub_form_list_id(association: column.name, id: parent_record.try(:id) || generated_id(parent_record) || 99999999999)} > .sub-form-record") %>
4
4
  <% else %>
5
5
  <%= render :super %>
6
6
  <% end %>
@@ -1 +1 @@
1
- <%= content_tag :div, render(:super), :class => 'sortable-container', :data => sort_params %>
1
+ <%= as_element :sortable_container, render(:super), class: 'sortable-container', data: sort_params %>
@@ -17,13 +17,13 @@ module ActiveScaffold::Config
17
17
  cattr_accessor :plugin_directory
18
18
  @@plugin_directory = File.expand_path(__FILE__).match(%{(^.*)/lib/active_scaffold/config/sortable.rb})[1]
19
19
 
20
- cattr_accessor :add_handle_column
20
+ cattr_accessor :add_handle_column, instance_accessor: false
21
21
  @@add_handle_column = false
22
22
 
23
- cattr_accessor :options
23
+ cattr_accessor :options, instance_accessor: false
24
24
  @@options = {}
25
25
 
26
- cattr_accessor :refresh_list
26
+ cattr_accessor :refresh_list, instance_accessor: false
27
27
 
28
28
  self.crud_type = :update
29
29
 
@@ -36,7 +36,7 @@ module ActiveScaffold::Config
36
36
  @column.form_ui = :hidden
37
37
  @column.css_class = 'sortable-handle'
38
38
  @column.label = ''
39
- @column.weight = -2**(0.size * 8 -2)
39
+ @column.weight = -(2**(0.size * 8 - 2))
40
40
  end
41
41
  @column
42
42
  end
@@ -50,7 +50,7 @@ module ActiveScaffold::Config
50
50
  raise(ArgumentError, "Unknown handle column position: #{where}") unless [:first, :last].include?(where)
51
51
  @options[:handle] = 'td.sortable-handle'
52
52
  define_handle_column
53
- @column.weight = 2**(0.size * 8 -2) -1 unless where == :first
53
+ @column.weight = (2**(0.size * 8 - 2)) - 1 unless where == :first
54
54
  if @core.actions.include? :list
55
55
  if where == :first
56
56
  @core.list.columns = [:active_scaffold_sortable] + @core.list.columns.to_a unless @core.list.columns.include? :active_scaffold_sortable
@@ -1,8 +1,8 @@
1
1
  module ActiveScaffoldSortable
2
2
  module Version
3
3
  MAJOR = 3
4
- MINOR = 6
5
- PATCH = 2
4
+ MINOR = 7
5
+ PATCH = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
8
  end
@@ -22,5 +22,6 @@ module ActiveScaffold
22
22
  ActiveScaffold.autoload_subdir('helpers', self, File.dirname(__FILE__))
23
23
  end
24
24
  end
25
+ ActiveScaffold.set_element_tag(:sortable_container, :div)
25
26
  ActiveScaffold.stylesheets << 'active_scaffold_sortable'
26
27
  ActiveScaffold.javascripts << 'active_scaffold_sortable'
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class AttributeParamsTest < Minitest::Test
6
+ Record = Struct.new(:position)
7
+ AssociationConfig = Struct.new(:actions, :sortable)
8
+ SortableConfig = Struct.new(:column)
9
+ ColumnConfig = Struct.new(:name)
10
+ Reflection = Struct.new(:name) do
11
+ def collection?
12
+ true
13
+ end
14
+ end
15
+ FormColumn = Struct.new(:association)
16
+
17
+ class Parent
18
+ attr_reader :target
19
+
20
+ def association(_name)
21
+ self
22
+ end
23
+
24
+ def target=(records)
25
+ @target = records
26
+ end
27
+ end
28
+
29
+ class BaseUpdater
30
+ attr_accessor :submitted_records
31
+
32
+ def update_column_from_params(*)
33
+ submitted_records
34
+ end
35
+ end
36
+
37
+ class Updater < BaseUpdater
38
+ prepend ActiveScaffoldSortable::AttributeParams
39
+
40
+ attr_accessor :associated_config
41
+
42
+ def active_scaffold_config_for(_klass)
43
+ associated_config
44
+ end
45
+ end
46
+
47
+ def test_assigns_missing_subform_positions_and_sorts_the_target
48
+ updater = Updater.new
49
+ records = [Record.new(2), Record.new(nil), Record.new(1)]
50
+ updater.submitted_records = records
51
+ updater.associated_config = AssociationConfig.new(
52
+ [:sortable],
53
+ SortableConfig.new(ColumnConfig.new(:position))
54
+ )
55
+ reflection = Reflection.new(:records)
56
+ reflection.define_singleton_method(:klass) { Record }
57
+ parent = Parent.new
58
+
59
+ result = updater.update_column_from_params(
60
+ parent,
61
+ FormColumn.new(reflection),
62
+ :records
63
+ )
64
+
65
+ assert_same records, result
66
+ assert_equal [2, 3, 1], records.map(&:position)
67
+ assert_equal [1, 2, 3], parent.target.map(&:position)
68
+ end
69
+ end
@@ -1,52 +1,61 @@
1
- require 'test_helper.rb'
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
2
4
 
3
5
  class AutoModelsControllerTest < ActionController::TestCase
4
- @@sortable_regexp = Regexp.new('Sortable.create\("as_auto_models-tbody", \{format:/\^\[\^_-\]\(\?:\[A-Za-z0-9_-\]\*\)-\(\.\*\)-row\$/, onUpdate:function\(\)\{new Ajax.Request\(\'/auto_models/reorder\', \{asynchronous:true, evalScripts:true, parameters:Sortable.serialize\("as_auto_models-tbody"\) \+ \'&controller=\' \+ encodeURIComponent\(\'auto_models\'\)\}\)\}, tag:\'tr\'\}\)')
5
- setup { AutoModel.create :name => 'test', :position => 1 }
6
-
7
- context "reordering" do
8
- setup do
9
- updates = sequence(:updates)
10
- AutoModel.expects(:update_all).with({:position => 1}, 'id' => '2').in_sequence(updates)
11
- AutoModel.expects(:update_all).with({:position => 2}, 'id' => '1').in_sequence(updates)
12
- xhr :post, :reorder, :'as_auto_models-tbody' => ['2', '1']
13
- end
14
- should_respond_with :success
15
- should_render_template :reorder
16
- should "update stripe" do
17
- assert_equal 'ActiveScaffold.stripe(\'as_auto_models-tbody\');', @response.body
18
- end
6
+ tests AutoModelsController
7
+
8
+ setup do
9
+ AutoModel.delete_all
10
+ @first = AutoModel.create!(name: "first", position: 1)
11
+ @second = AutoModel.create!(name: "second", position: 2)
12
+ end
13
+
14
+ test "reorders records and renders the reorder response" do
15
+ post :reorder,
16
+ params: { "as_auto_models-tbody" => [@second.id, @first.id] },
17
+ xhr: true
18
+
19
+ assert_response :success
20
+ assert_equal 2, @first.reload.position
21
+ assert_equal 1, @second.reload.position
22
+ assert_operator @first.updated_at, :>, @first.created_at
23
+ assert_includes response.body, "ActiveScaffold.stripe('as_auto_models-tbody');"
24
+ end
25
+
26
+ test "renders sortable metadata and a row drag handle" do
27
+ get :index
28
+
29
+ assert_response :success
30
+ assert_select ".sortable-container[data-reorder-url='/auto_models/reorder']"
31
+ assert_select ".sortable-container[data-column='position']"
32
+ assert_select ".records tr.record.sortable-handle", count: 2
19
33
  end
20
34
 
21
- context "listing" do
22
- setup { get :index }
23
- should "render record with sortable class" do
24
- assert_select '.records tr.record.sortable'
25
- end
26
- should "render sortable script" do
27
- assert_select 'script[type=text/javascript]', @@sortable_regexp
28
- end
35
+ test "applies UI adapter attributes to the sortable container" do
36
+ ActiveScaffold.add_element_attributes(:sortable_container, class: "adapter-container")
37
+
38
+ get :index
39
+
40
+ assert_response :success
41
+ assert_select ".sortable-container.adapter-container"
42
+ ensure
43
+ ActiveScaffold.set_element(:sortable_container, tag: :div)
29
44
  end
30
45
 
31
- context "creating" do
32
- setup { xhr :post, :create, :record => {:name => 'test2', :position => 2} }
33
- should_respond_with :success
34
- should "insert at top" do
35
- assert_match "$(\"as_auto_models-tbody\").insert(\"as_auto_models-list-#{assigns(:record).id}-row\");", @response.body
36
- end
37
- should "update stripe" do
38
- assert_match 'ActiveScaffold.stripe(\'as_auto_models-tbody\');', @response.body
39
- end
40
- should "update sortable" do
41
- assert_match @@sortable_regexp, @response.body
42
- end
46
+ test "keeps sorting active after creating a record" do
47
+ post :create, params: { record: { name: "third", position: 3 } }, xhr: true
48
+
49
+ assert_response :success
50
+ assert_equal 3, AutoModel.count
51
+ assert_includes response.body, "ActiveScaffold.sortable('as_auto_models-tbody');"
43
52
  end
44
53
 
45
- context "updating" do
46
- setup { xhr :put, :update, :id => 1, :record => {:name => 'test updated'} }
47
- should_respond_with :success
48
- should "update sortable" do
49
- assert_match @@sortable_regexp, @response.body
50
- end
54
+ test "keeps sorting active after updating a record" do
55
+ put :update, params: { id: @first.id, record: { name: "updated" } }, xhr: true
56
+
57
+ assert_response :success
58
+ assert_equal "updated", @first.reload.name
59
+ assert_includes response.body, "ActiveScaffold.sortable('as_auto_models-tbody');"
51
60
  end
52
61
  end
data/test/config_test.rb CHANGED
@@ -1,15 +1,11 @@
1
- require 'test_helper.rb'
1
+ # frozen_string_literal: true
2
2
 
3
- class ConfigTest < Test::Unit::TestCase
4
- def test_not_enable_sortable
5
- assert !ModelsController.active_scaffold_config.actions.include?(:sortable)
6
- end
3
+ require "test_helper"
7
4
 
8
- def test_auto_enable_sortable
5
+ class ConfigTest < Minitest::Test
6
+ def test_sortable_activation
7
+ refute ModelsController.active_scaffold_config.actions.include?(:sortable)
9
8
  assert AutoModelsController.active_scaffold_config.actions.include?(:sortable)
10
- end
11
-
12
- def test_manual_enable_sortable
13
9
  assert SortableModelsController.active_scaffold_config.actions.include?(:sortable)
14
10
  end
15
11
 
@@ -18,42 +14,53 @@ class ConfigTest < Test::Unit::TestCase
18
14
  assert_equal :name, SortableModelsController.active_scaffold_config.sortable.column.name
19
15
  end
20
16
 
21
- def test_position_column_not_included
22
- assert !AutoModelsController.active_scaffold_config.list.columns.include?(:position)
23
- assert !AutoModelsController.active_scaffold_config.update.columns.include?(:position)
24
- assert !AutoModelsController.active_scaffold_config.create.columns.include?(:position)
25
- assert !AutoModelsController.active_scaffold_config.show.columns.include?(:position)
26
- assert !AutoModelsController.active_scaffold_config.subform.columns.include?(:position)
27
- assert !AutoModelsController.active_scaffold_config.search.columns.include?(:position)
28
-
29
- assert !SortableModelsController.active_scaffold_config.list.columns.include?(:name)
30
- assert !SortableModelsController.active_scaffold_config.update.columns.include?(:name)
31
- assert !SortableModelsController.active_scaffold_config.create.columns.include?(:name)
32
- assert !SortableModelsController.active_scaffold_config.show.columns.include?(:name)
17
+ def test_position_column_is_hidden_from_actions
18
+ config = AutoModelsController.active_scaffold_config
19
+
20
+ %i[list update create show search subform].each do |action|
21
+ refute config.public_send(action).columns.include?(:position), action
22
+ end
23
+ assert_equal :hidden, config.columns[:position].form_ui
33
24
  end
34
25
 
35
- def test_sorting
36
- assert_equal('"models"."id" ASC', ModelsController.active_scaffold_config.list.sorting.clause)
37
- assert ModelsController.active_scaffold_config.columns[:name].sortable?
38
- assert ModelsController.active_scaffold_config.columns[:position].sortable?
26
+ def test_manually_selected_column_is_hidden
27
+ config = SortableModelsController.active_scaffold_config
39
28
 
40
- assert_equal('"models"."position" ASC', AutoModelsController.active_scaffold_config.list.sorting.clause)
41
- assert !AutoModelsController.active_scaffold_config.columns[:name].sortable?
29
+ %i[list update create show].each do |action|
30
+ refute config.public_send(action).columns.include?(:name), action
31
+ end
32
+ end
42
33
 
43
- assert_equal('"models"."name" ASC', SortableModelsController.active_scaffold_config.list.sorting.clause)
44
- assert !SortableModelsController.active_scaffold_config.columns[:position].sortable?
34
+ def test_sorting_configuration
35
+ regular = ModelsController.active_scaffold_config
36
+ automatic = AutoModelsController.active_scaffold_config
37
+ manual = SortableModelsController.active_scaffold_config
38
+
39
+ assert_equal [{id: "ASC"}], regular.list.sorting.clause
40
+ assert regular.columns[:name].sortable?
41
+ assert regular.columns[:position].sortable?
42
+
43
+ assert_equal [{position: "ASC"}], automatic.list.sorting.clause
44
+ refute automatic.columns[:name].sortable?
45
+
46
+ assert_equal [{name: "ASC"}], manual.list.sorting.clause
47
+ refute manual.columns[:position].sortable?
45
48
  end
46
49
 
47
- def test_pagination
50
+ def test_sortable_lists_disable_pagination
48
51
  assert ModelsController.active_scaffold_config.list.pagination
49
- assert !AutoModelsController.active_scaffold_config.list.pagination
50
- assert !SortableModelsController.active_scaffold_config.list.pagination
52
+ refute AutoModelsController.active_scaffold_config.list.pagination
53
+ refute SortableModelsController.active_scaffold_config.list.pagination
51
54
  end
52
55
 
53
- def test_active_scaffold_paths
54
- path = File.join(Rails.root, 'vendor/plugins/active_scaffold_sortable/frontends/default/views')
55
- assert !ModelsController.active_scaffold_paths.include?(path)
56
- assert AutoModelsController.active_scaffold_paths.include?(path)
57
- assert SortableModelsController.active_scaffold_paths.include?(path)
56
+ def test_sortable_controllers_register_the_plugin_view_path
57
+ plugin_path = File.join(
58
+ ActiveScaffold::Config::Sortable.plugin_directory,
59
+ "frontends/default"
60
+ )
61
+
62
+ refute ModelsController.view_paths.map(&:to_s).include?(plugin_path)
63
+ assert AutoModelsController.view_paths.map(&:to_s).include?(plugin_path)
64
+ assert SortableModelsController.view_paths.map(&:to_s).include?(plugin_path)
58
65
  end
59
66
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AncestryModelsController < ActionController::Base
4
+ active_scaffold :ancestry_model do |config|
5
+ config.actions << :sortable
6
+ config.sortable.column = :position
7
+ end
8
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AutoModelsController < ActionController::Base
2
4
  active_scaffold :auto_model
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ModelsController < ActionController::Base
2
4
  active_scaffold
3
5
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NestedSetModelsController < ActionController::Base
4
+ active_scaffold :nested_set_model
5
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class SortableModelsController < ActionController::Base
2
4
  active_scaffold :model do |config|
3
5
  config.actions.exclude :search
@@ -0,0 +1 @@
1
+ //= link active_scaffold/manifest.js