wallaby 5.0.1 → 5.1.3

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 (350) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -3
  3. data/app/assets/images/wallaby/404.png +0 -0
  4. data/app/assets/images/wallaby/422.png +0 -0
  5. data/app/assets/images/wallaby/500.png +0 -0
  6. data/app/assets/javascripts/wallaby/application.js +1 -15
  7. data/app/assets/javascripts/wallaby/auto_select.js +77 -0
  8. data/app/assets/javascripts/wallaby/base.js +17 -0
  9. data/app/assets/javascripts/wallaby/setup.js.erb +60 -0
  10. data/app/assets/stylesheets/wallaby/application.scss +1 -51
  11. data/app/assets/stylesheets/wallaby/base/_layout.scss +257 -9
  12. data/app/assets/stylesheets/wallaby/base/_layout_desktop.scss +53 -0
  13. data/app/assets/stylesheets/wallaby/base/_mixins.scss +119 -0
  14. data/app/assets/stylesheets/wallaby/base/_override.scss +10 -0
  15. data/app/assets/stylesheets/wallaby/base/_vars.scss +72 -2
  16. data/app/assets/stylesheets/wallaby/base.scss +27 -0
  17. data/app/assets/stylesheets/wallaby/components/_auto_select.scss +119 -0
  18. data/app/assets/stylesheets/wallaby/components/_auto_select_desktop.scss +7 -0
  19. data/app/assets/stylesheets/wallaby/components/_color_square.scss +8 -0
  20. data/app/assets/stylesheets/wallaby/components/_filters.scss +14 -0
  21. data/app/assets/stylesheets/wallaby/components/_links.scss +25 -0
  22. data/app/assets/stylesheets/wallaby/components/_pagination.scss +35 -91
  23. data/app/assets/stylesheets/wallaby/components/_query.scss +101 -0
  24. data/app/assets/stylesheets/wallaby/components/_text.scss +6 -6
  25. data/app/assets/stylesheets/wallaby/pages/_error.scss +108 -0
  26. data/app/assets/stylesheets/wallaby/pages/_form.scss +40 -0
  27. data/app/assets/stylesheets/wallaby/pages/_index.scss +193 -0
  28. data/app/assets/stylesheets/wallaby/pages/_index_desktop.scss +22 -0
  29. data/app/assets/stylesheets/wallaby/pages/_show.scss +21 -0
  30. data/app/controllers/wallaby/abstract_resources_controller.rb +334 -0
  31. data/app/controllers/wallaby/application_controller.rb +45 -15
  32. data/app/controllers/wallaby/base_controller.rb +30 -0
  33. data/app/controllers/wallaby/resources_controller.rb +2 -131
  34. data/app/controllers/wallaby/secure_controller.rb +38 -24
  35. data/app/routes/wallaby/resources_router.rb +40 -43
  36. data/app/security/ability.rb +4 -28
  37. data/app/views/layouts/wallaby/application.html.erb +11 -6
  38. data/app/views/layouts/wallaby/error.html.erb +26 -4
  39. data/app/views/wallaby/error.html.erb +11 -0
  40. data/app/views/wallaby/error.json.jbuilder +8 -0
  41. data/app/views/wallaby/{shared → resources}/_flash_messages.html.erb +0 -0
  42. data/app/views/wallaby/resources/_footer.html.erb +1 -0
  43. data/app/views/wallaby/resources/_form.html.erb +2 -2
  44. data/app/views/wallaby/resources/_header.html.erb +38 -0
  45. data/app/views/wallaby/resources/_imodal.html.erb +13 -0
  46. data/app/views/wallaby/resources/_index_actions.html.erb +4 -1
  47. data/app/views/wallaby/resources/_index_filters.html.erb +23 -0
  48. data/app/views/wallaby/resources/_index_pagination.html.erb +63 -0
  49. data/app/views/wallaby/resources/_index_query.html.erb +23 -0
  50. data/app/views/wallaby/resources/_logo.html.erb +1 -0
  51. data/app/views/wallaby/resources/_navs.html.erb +9 -0
  52. data/app/views/wallaby/resources/_resource_actions.html.erb +3 -3
  53. data/app/views/wallaby/resources/{shared/_resource_nav.html.erb → _resource_navs.html.erb} +6 -6
  54. data/app/views/wallaby/resources/_title.html.erb +1 -0
  55. data/app/views/wallaby/resources/_user_menu.html.erb +5 -0
  56. data/app/views/wallaby/resources/bad_request.json.jbuilder +7 -0
  57. data/app/views/wallaby/resources/edit.html.erb +16 -12
  58. data/app/views/wallaby/resources/form/_belongs_to.html.erb +63 -12
  59. data/app/views/wallaby/resources/form/_bigint.html.erb +10 -1
  60. data/app/views/wallaby/resources/form/_bigserial.html.erb +18 -0
  61. data/app/views/wallaby/resources/form/_binary.html.erb +11 -2
  62. data/app/views/wallaby/resources/form/_bit.html.erb +10 -1
  63. data/app/views/wallaby/resources/form/_bit_varying.html.erb +10 -1
  64. data/app/views/wallaby/resources/form/_blob.html.erb +21 -0
  65. data/app/views/wallaby/resources/form/_boolean.html.erb +9 -0
  66. data/app/views/wallaby/resources/form/_box.html.erb +21 -0
  67. data/app/views/wallaby/resources/form/_cidr.html.erb +13 -1
  68. data/app/views/wallaby/resources/form/_circle.html.erb +21 -0
  69. data/app/views/wallaby/resources/form/_citext.html.erb +11 -2
  70. data/app/views/wallaby/resources/form/_color.html.erb +11 -2
  71. data/app/views/wallaby/resources/form/_date.html.erb +12 -3
  72. data/app/views/wallaby/resources/form/_daterange.html.erb +14 -5
  73. data/app/views/wallaby/resources/form/_datetime.html.erb +12 -3
  74. data/app/views/wallaby/resources/form/_decimal.html.erb +10 -1
  75. data/app/views/wallaby/resources/form/_dropdown.html.erb +18 -0
  76. data/app/views/wallaby/resources/form/_email.html.erb +9 -0
  77. data/app/views/wallaby/resources/form/_file.html.erb +21 -0
  78. data/app/views/wallaby/resources/form/_float.html.erb +10 -1
  79. data/app/views/wallaby/resources/form/_has_and_belongs_to_many.html.erb +53 -7
  80. data/app/views/wallaby/resources/form/_has_many.html.erb +52 -7
  81. data/app/views/wallaby/resources/form/_has_one.html.erb +10 -2
  82. data/app/views/wallaby/resources/form/_hstore.html.erb +12 -5
  83. data/app/views/wallaby/resources/form/_inet.html.erb +13 -1
  84. data/app/views/wallaby/resources/form/_int4range.html.erb +11 -2
  85. data/app/views/wallaby/resources/form/_int8range.html.erb +11 -2
  86. data/app/views/wallaby/resources/form/_integer.html.erb +10 -1
  87. data/app/views/wallaby/resources/form/_json.html.erb +13 -6
  88. data/app/views/wallaby/resources/form/_jsonb.html.erb +13 -6
  89. data/app/views/wallaby/resources/form/_line.html.erb +21 -0
  90. data/app/views/wallaby/resources/form/_longblob.html.erb +21 -0
  91. data/app/views/wallaby/resources/form/_longtext.html.erb +30 -0
  92. data/app/views/wallaby/resources/form/_lseg.html.erb +21 -0
  93. data/app/views/wallaby/resources/form/_ltree.html.erb +17 -1
  94. data/app/views/wallaby/resources/form/_macaddr.html.erb +13 -1
  95. data/app/views/wallaby/resources/form/_markdown.html.erb +29 -0
  96. data/app/views/wallaby/resources/form/_mediumblob.html.erb +21 -0
  97. data/app/views/wallaby/resources/form/_mediumtext.html.erb +30 -0
  98. data/app/views/wallaby/resources/form/_money.html.erb +10 -1
  99. data/app/views/wallaby/resources/form/_numrange.html.erb +11 -2
  100. data/app/views/wallaby/resources/form/_password.html.erb +14 -1
  101. data/app/views/wallaby/resources/form/_path.html.erb +17 -0
  102. data/app/views/wallaby/resources/form/_point.html.erb +11 -2
  103. data/app/views/wallaby/resources/form/_polygon.html.erb +17 -0
  104. data/app/views/wallaby/resources/form/_serial.html.erb +18 -0
  105. data/app/views/wallaby/resources/form/_sti.html.erb +18 -0
  106. data/app/views/wallaby/resources/form/_string.html.erb +14 -1
  107. data/app/views/wallaby/resources/form/_text.html.erb +11 -2
  108. data/app/views/wallaby/resources/form/_time.html.erb +12 -3
  109. data/app/views/wallaby/resources/form/_tinyblob.html.erb +21 -0
  110. data/app/views/wallaby/resources/form/_tinytext.html.erb +30 -0
  111. data/app/views/wallaby/resources/form/_tsrange.html.erb +14 -5
  112. data/app/views/wallaby/resources/form/_tstzrange.html.erb +14 -5
  113. data/app/views/wallaby/resources/form/_tsvector.html.erb +9 -0
  114. data/app/views/wallaby/resources/form/_unsigned_bigint.html.erb +18 -0
  115. data/app/views/wallaby/resources/form/_unsigned_decimal.html.erb +18 -0
  116. data/app/views/wallaby/resources/form/_unsigned_float.html.erb +18 -0
  117. data/app/views/wallaby/resources/form/_unsigned_integer.html.erb +18 -0
  118. data/app/views/wallaby/resources/form/_uuid.html.erb +10 -1
  119. data/app/views/wallaby/resources/form/_xml.html.erb +11 -5
  120. data/app/views/wallaby/resources/form.json.jbuilder +5 -0
  121. data/app/views/wallaby/{core → resources}/home.html.erb +1 -1
  122. data/app/views/wallaby/resources/index/_belongs_to.html.erb +5 -1
  123. data/app/views/wallaby/resources/index/_bigint.html.erb +4 -0
  124. data/app/views/wallaby/resources/index/_bigserial.html.erb +5 -0
  125. data/app/views/wallaby/resources/index/_binary.html.erb +5 -1
  126. data/app/views/wallaby/resources/index/_bit.html.erb +4 -0
  127. data/app/views/wallaby/resources/index/_bit_varying.html.erb +4 -0
  128. data/app/views/wallaby/resources/index/_blob.html.erb +5 -0
  129. data/app/views/wallaby/resources/index/_boolean.html.erb +5 -1
  130. data/app/views/wallaby/resources/index/_box.html.erb +16 -0
  131. data/app/views/wallaby/resources/index/_cidr.html.erb +5 -1
  132. data/app/views/wallaby/resources/index/_circle.html.erb +16 -0
  133. data/app/views/wallaby/resources/index/_citext.html.erb +5 -1
  134. data/app/views/wallaby/resources/index/_color.html.erb +6 -1
  135. data/app/views/wallaby/resources/index/_date.html.erb +4 -0
  136. data/app/views/wallaby/resources/index/_daterange.html.erb +5 -1
  137. data/app/views/wallaby/resources/index/_datetime.html.erb +5 -1
  138. data/app/views/wallaby/resources/index/_decimal.html.erb +4 -0
  139. data/app/views/wallaby/resources/index/_email.html.erb +4 -0
  140. data/app/views/wallaby/resources/index/_float.html.erb +4 -0
  141. data/app/views/wallaby/resources/index/_has_and_belongs_to_many.html.erb +6 -2
  142. data/app/views/wallaby/resources/index/_has_many.html.erb +6 -2
  143. data/app/views/wallaby/resources/index/_has_one.html.erb +5 -1
  144. data/app/views/wallaby/resources/index/_hstore.html.erb +6 -2
  145. data/app/views/wallaby/resources/index/_inet.html.erb +5 -1
  146. data/app/views/wallaby/resources/index/_int4range.html.erb +4 -0
  147. data/app/views/wallaby/resources/index/_int8range.html.erb +4 -0
  148. data/app/views/wallaby/resources/index/_integer.html.erb +4 -0
  149. data/app/views/wallaby/resources/index/_json.html.erb +5 -2
  150. data/app/views/wallaby/resources/index/_jsonb.html.erb +5 -2
  151. data/app/views/wallaby/resources/index/_line.html.erb +16 -0
  152. data/app/views/wallaby/resources/index/_longblob.html.erb +5 -0
  153. data/app/views/wallaby/resources/index/_longtext.html.erb +16 -0
  154. data/app/views/wallaby/resources/index/_lseg.html.erb +16 -0
  155. data/app/views/wallaby/resources/index/_ltree.html.erb +5 -1
  156. data/app/views/wallaby/resources/index/_macaddr.html.erb +4 -0
  157. data/app/views/wallaby/resources/index/_mediumblob.html.erb +5 -0
  158. data/app/views/wallaby/resources/index/_mediumtext.html.erb +16 -0
  159. data/app/views/wallaby/resources/index/_money.html.erb +4 -0
  160. data/app/views/wallaby/resources/index/_numrange.html.erb +4 -0
  161. data/app/views/wallaby/resources/index/_password.html.erb +9 -0
  162. data/app/views/wallaby/resources/index/_path.html.erb +16 -0
  163. data/app/views/wallaby/resources/index/_point.html.erb +4 -0
  164. data/app/views/wallaby/resources/index/_polygon.html.erb +16 -0
  165. data/app/views/wallaby/resources/index/_raw.html.erb +9 -0
  166. data/app/views/wallaby/resources/index/_serial.html.erb +5 -0
  167. data/app/views/wallaby/resources/index/_sti.html.erb +16 -0
  168. data/app/views/wallaby/resources/index/_string.html.erb +5 -1
  169. data/app/views/wallaby/resources/index/_text.html.erb +5 -1
  170. data/app/views/wallaby/resources/index/_time.html.erb +4 -0
  171. data/app/views/wallaby/resources/index/_tinyblob.html.erb +5 -0
  172. data/app/views/wallaby/resources/index/_tinytext.html.erb +16 -0
  173. data/app/views/wallaby/resources/index/_tsrange.html.erb +5 -1
  174. data/app/views/wallaby/resources/index/_tstzrange.html.erb +5 -1
  175. data/app/views/wallaby/resources/index/_tsvector.html.erb +5 -1
  176. data/app/views/wallaby/resources/index/_unsigned_bigint.html.erb +5 -0
  177. data/app/views/wallaby/resources/index/_unsigned_decimal.html.erb +5 -0
  178. data/app/views/wallaby/resources/index/_unsigned_float.html.erb +5 -0
  179. data/app/views/wallaby/resources/index/_unsigned_integer.html.erb +5 -0
  180. data/app/views/wallaby/resources/index/_uuid.html.erb +5 -1
  181. data/app/views/wallaby/resources/index/_xml.html.erb +5 -1
  182. data/app/views/wallaby/resources/index.csv.erb +26 -0
  183. data/app/views/wallaby/resources/index.html.erb +47 -59
  184. data/app/views/wallaby/resources/index.json.jbuilder +5 -0
  185. data/app/views/wallaby/resources/new.html.erb +12 -11
  186. data/app/views/wallaby/resources/show/_belongs_to.html.erb +5 -1
  187. data/app/views/wallaby/resources/show/_bigint.html.erb +4 -0
  188. data/app/views/wallaby/resources/show/_bigserial.html.erb +5 -0
  189. data/app/views/wallaby/resources/show/_binary.html.erb +5 -1
  190. data/app/views/wallaby/resources/show/_bit.html.erb +4 -0
  191. data/app/views/wallaby/resources/show/_bit_varying.html.erb +4 -0
  192. data/app/views/wallaby/resources/show/_blob.html.erb +5 -0
  193. data/app/views/wallaby/resources/show/_boolean.html.erb +5 -1
  194. data/app/views/wallaby/resources/show/_box.html.erb +9 -0
  195. data/app/views/wallaby/resources/show/_cidr.html.erb +5 -1
  196. data/app/views/wallaby/resources/show/_circle.html.erb +9 -0
  197. data/app/views/wallaby/resources/show/_citext.html.erb +4 -0
  198. data/app/views/wallaby/resources/show/_color.html.erb +6 -1
  199. data/app/views/wallaby/resources/show/_date.html.erb +4 -0
  200. data/app/views/wallaby/resources/show/_daterange.html.erb +4 -0
  201. data/app/views/wallaby/resources/show/_datetime.html.erb +4 -0
  202. data/app/views/wallaby/resources/show/_decimal.html.erb +4 -0
  203. data/app/views/wallaby/resources/show/_email.html.erb +4 -0
  204. data/app/views/wallaby/resources/show/_float.html.erb +4 -0
  205. data/app/views/wallaby/resources/show/_has_and_belongs_to_many.html.erb +6 -2
  206. data/app/views/wallaby/resources/show/_has_many.html.erb +6 -2
  207. data/app/views/wallaby/resources/show/_has_one.html.erb +5 -1
  208. data/app/views/wallaby/resources/show/_hstore.html.erb +4 -0
  209. data/app/views/wallaby/resources/show/_image.html.erb +9 -0
  210. data/app/views/wallaby/resources/show/_inet.html.erb +5 -1
  211. data/app/views/wallaby/resources/show/_int4range.html.erb +4 -0
  212. data/app/views/wallaby/resources/show/_int8range.html.erb +4 -0
  213. data/app/views/wallaby/resources/show/_integer.html.erb +4 -0
  214. data/app/views/wallaby/resources/show/_json.html.erb +4 -0
  215. data/app/views/wallaby/resources/show/_jsonb.html.erb +4 -0
  216. data/app/views/wallaby/resources/show/_line.html.erb +9 -0
  217. data/app/views/wallaby/resources/show/_longblob.html.erb +5 -0
  218. data/app/views/wallaby/resources/show/_longtext.html.erb +5 -0
  219. data/app/views/wallaby/resources/show/_lseg.html.erb +9 -0
  220. data/app/views/wallaby/resources/show/_ltree.html.erb +4 -0
  221. data/app/views/wallaby/resources/show/_macaddr.html.erb +4 -0
  222. data/app/views/wallaby/resources/show/_mediumblob.html.erb +5 -0
  223. data/app/views/wallaby/resources/show/_mediumtext.html.erb +5 -0
  224. data/app/views/wallaby/resources/show/_money.html.erb +4 -0
  225. data/app/views/wallaby/resources/show/_numrange.html.erb +4 -0
  226. data/app/views/wallaby/resources/show/_password.html.erb +9 -0
  227. data/app/views/wallaby/resources/show/_path.html.erb +9 -0
  228. data/app/views/wallaby/resources/show/_point.html.erb +4 -0
  229. data/app/views/wallaby/resources/show/_polygon.html.erb +9 -0
  230. data/app/views/wallaby/resources/show/_raw.html.erb +9 -0
  231. data/app/views/wallaby/resources/show/_serial.html.erb +5 -0
  232. data/app/views/wallaby/resources/show/_sti.html.erb +5 -0
  233. data/app/views/wallaby/resources/show/_string.html.erb +4 -0
  234. data/app/views/wallaby/resources/show/_text.html.erb +4 -0
  235. data/app/views/wallaby/resources/show/_time.html.erb +4 -0
  236. data/app/views/wallaby/resources/show/_tinyblob.html.erb +5 -0
  237. data/app/views/wallaby/resources/show/_tinytext.html.erb +5 -0
  238. data/app/views/wallaby/resources/show/_tsrange.html.erb +4 -0
  239. data/app/views/wallaby/resources/show/_tstzrange.html.erb +4 -0
  240. data/app/views/wallaby/resources/show/_tsvector.html.erb +4 -0
  241. data/app/views/wallaby/resources/show/_unsigned_bigint.html.erb +5 -0
  242. data/app/views/wallaby/resources/show/_unsigned_decimal.html.erb +5 -0
  243. data/app/views/wallaby/resources/show/_unsigned_float.html.erb +5 -0
  244. data/app/views/wallaby/resources/show/_unsigned_integer.html.erb +5 -0
  245. data/app/views/wallaby/resources/show/_uuid.html.erb +4 -0
  246. data/app/views/wallaby/resources/show/_xml.html.erb +4 -0
  247. data/app/views/wallaby/resources/show.html.erb +14 -24
  248. data/app/views/wallaby/resources/show.json.jbuilder +5 -0
  249. data/config/brakeman.ignore +26 -0
  250. data/config/locales/wallaby.en.yml +91 -0
  251. data/config/massa.yml +45 -0
  252. data/config/rails_best_practices.yml +42 -0
  253. data/config/routes.rb +29 -23
  254. data/lib/adaptors/wallaby/active_record/model_decorator/fields_builder/association_builder.rb +39 -0
  255. data/lib/adaptors/wallaby/active_record/model_decorator/fields_builder/polymorphic_builder.rb +44 -0
  256. data/lib/adaptors/wallaby/active_record/model_decorator/fields_builder/sti_builder.rb +42 -0
  257. data/lib/adaptors/wallaby/active_record/model_decorator/fields_builder.rb +41 -94
  258. data/lib/adaptors/wallaby/active_record/model_decorator/title_field_finder.rb +24 -14
  259. data/lib/adaptors/wallaby/active_record/model_decorator.rb +118 -64
  260. data/lib/adaptors/wallaby/active_record/model_finder.rb +44 -15
  261. data/lib/adaptors/wallaby/active_record/model_pagination_provider.rb +30 -0
  262. data/lib/adaptors/wallaby/active_record/model_service_provider/normalizer.rb +42 -0
  263. data/lib/adaptors/wallaby/active_record/model_service_provider/permitter.rb +64 -0
  264. data/lib/adaptors/wallaby/active_record/model_service_provider/querier/transformer.rb +70 -0
  265. data/lib/adaptors/wallaby/active_record/model_service_provider/querier.rb +102 -0
  266. data/lib/adaptors/wallaby/active_record/model_service_provider/validator.rb +29 -0
  267. data/lib/adaptors/wallaby/active_record/model_service_provider.rb +137 -0
  268. data/lib/adaptors/wallaby/active_record.rb +4 -1
  269. data/lib/decorators/wallaby/abstract_resource_decorator.rb +74 -0
  270. data/lib/decorators/wallaby/resource_decorator.rb +5 -76
  271. data/lib/errors/wallaby/model_not_found.rb +5 -1
  272. data/lib/errors/wallaby/not_found.rb +4 -0
  273. data/lib/errors/wallaby/resource_not_found.rb +5 -1
  274. data/lib/forms/wallaby/form_builder.rb +42 -19
  275. data/lib/helpers/wallaby/application_helper.rb +34 -24
  276. data/lib/helpers/wallaby/base_helper.rb +52 -0
  277. data/lib/helpers/wallaby/form_helper.rb +40 -16
  278. data/lib/helpers/wallaby/index_helper.rb +59 -0
  279. data/lib/helpers/wallaby/links_helper.rb +150 -81
  280. data/lib/helpers/wallaby/resources_helper.rb +41 -46
  281. data/lib/helpers/wallaby/secure_helper.rb +36 -19
  282. data/lib/helpers/wallaby/styling_helper.rb +53 -44
  283. data/lib/interfaces/wallaby/mode.rb +19 -12
  284. data/lib/interfaces/wallaby/model_decorator.rb +176 -50
  285. data/lib/interfaces/wallaby/model_finder.rb +7 -3
  286. data/lib/interfaces/wallaby/model_pagination_provider.rb +104 -0
  287. data/lib/interfaces/wallaby/model_service_provider.rb +71 -0
  288. data/lib/paginators/wallaby/abstract_resource_paginator.rb +23 -0
  289. data/lib/paginators/wallaby/resource_paginator.rb +6 -0
  290. data/lib/parsers/wallaby/parser.rb +32 -0
  291. data/lib/responders/wallaby/abstract_responder.rb +68 -0
  292. data/lib/responders/wallaby/resources_responder.rb +6 -0
  293. data/lib/servicers/wallaby/abstract_model_servicer.rb +48 -0
  294. data/lib/servicers/wallaby/model_servicer.rb +5 -0
  295. data/lib/services/wallaby/link_options_normalizer.rb +16 -0
  296. data/lib/services/wallaby/lookup_context_wrapper.rb +23 -30
  297. data/lib/services/wallaby/map/mode_mapper.rb +19 -0
  298. data/lib/services/wallaby/map/model_class_collector.rb +41 -0
  299. data/lib/services/wallaby/map/model_class_mapper.rb +24 -0
  300. data/lib/services/wallaby/map.rb +76 -39
  301. data/lib/services/wallaby/partial_renderer.rb +60 -0
  302. data/lib/services/wallaby/prefixes_builder.rb +54 -0
  303. data/lib/services/wallaby/sorting/hash_builder.rb +16 -0
  304. data/lib/services/wallaby/sorting/link_builder.rb +45 -0
  305. data/lib/services/wallaby/sorting/next_builder.rb +54 -0
  306. data/lib/services/wallaby/url_for.rb +36 -0
  307. data/lib/tree/wallaby/node.rb +17 -0
  308. data/lib/utils/wallaby/utils.rb +67 -22
  309. data/lib/wallaby/configuration/features.rb +12 -0
  310. data/lib/wallaby/configuration/metadata.rb +12 -0
  311. data/lib/wallaby/configuration/models.rb +27 -12
  312. data/lib/wallaby/configuration/pagination.rb +12 -0
  313. data/lib/wallaby/configuration/security.rb +55 -24
  314. data/lib/wallaby/configuration.rb +38 -19
  315. data/lib/wallaby/engine.rb +84 -39
  316. data/lib/wallaby/version.rb +1 -1
  317. data/lib/wallaby.rb +22 -3
  318. metadata +200 -55
  319. data/app/assets/javascripts/wallaby/form.js +0 -8
  320. data/app/assets/stylesheets/wallaby/base/_functions.scss +0 -0
  321. data/app/assets/stylesheets/wallaby/base/_normalize.scss +0 -0
  322. data/app/assets/stylesheets/wallaby/base/_reset.scss +0 -0
  323. data/app/assets/stylesheets/wallaby/components/_forms.scss +0 -53
  324. data/app/assets/stylesheets/wallaby/components/_nav.scss +0 -19
  325. data/app/assets/stylesheets/wallaby/components/_tables.scss +0 -78
  326. data/app/assets/stylesheets/wallaby/form.scss +0 -11
  327. data/app/controllers/wallaby/core_controller.rb +0 -28
  328. data/app/views/layouts/wallaby/_footer.html.erb +0 -2
  329. data/app/views/layouts/wallaby/_header.html.erb +0 -57
  330. data/app/views/layouts/wallaby/_navs.html.erb +0 -1
  331. data/app/views/wallaby/errors/access_denied.html.erb +0 -1
  332. data/app/views/wallaby/errors/not_authenticated.html.erb +0 -1
  333. data/app/views/wallaby/errors/not_found.html.erb +0 -6
  334. data/app/views/wallaby/errors/unprocessable_entity.erb +0 -1
  335. data/config/locales/en.yml +0 -29
  336. data/lib/adaptors/wallaby/active_record/model_operator/normalizer.rb +0 -44
  337. data/lib/adaptors/wallaby/active_record/model_operator/permitter.rb +0 -50
  338. data/lib/adaptors/wallaby/active_record/model_operator/querier.rb +0 -47
  339. data/lib/adaptors/wallaby/active_record/model_operator/validator.rb +0 -16
  340. data/lib/adaptors/wallaby/active_record/model_operator.rb +0 -82
  341. data/lib/errors/wallaby/deprecated.rb +0 -4
  342. data/lib/errors/wallaby/operation_not_found.rb +0 -4
  343. data/lib/handlers/wallaby/cached_compiled_erb.rb +0 -14
  344. data/lib/helpers/wallaby/core_helper.rb +0 -50
  345. data/lib/helpers/wallaby/paginatable_helper.rb +0 -9
  346. data/lib/helpers/wallaby/sorting_helper.rb +0 -43
  347. data/lib/interfaces/wallaby/model_operator.rb +0 -31
  348. data/lib/services/wallaby/decorator_finder.rb +0 -16
  349. data/lib/services/wallaby/model_servicer.rb +0 -38
  350. data/lib/services/wallaby/servicer_finder.rb +0 -5
@@ -0,0 +1,137 @@
1
+ module Wallaby
2
+ class ActiveRecord
3
+ # Model service provider
4
+ # @see Wallaby::ModelServiceProvider
5
+ class ModelServiceProvider < ::Wallaby::ModelServiceProvider
6
+ # @see Wallaby::ModelServiceProvider#permit
7
+ def permit(params)
8
+ return {} if params[param_key].blank?
9
+ # using fetch could avoid ActionController::ParameterMissing
10
+ params.fetch(param_key, {}).permit permitted_fields
11
+ end
12
+
13
+ # @see Wallaby::ModelServiceProvider#collection
14
+ def collection(params, authorizer)
15
+ # NOTE: pagination free here
16
+ # since somewhere might use it without pagination
17
+ query = querier.search params
18
+ query = query.order params[:sort] if params[:sort].present?
19
+ query.accessible_by authorizer
20
+ end
21
+
22
+ # @see Wallaby::ModelServiceProvider#paginate
23
+ def paginate(query, params)
24
+ per = params[:per] || Wallaby.configuration.pagination.page_size
25
+ query = query.page params[:page] if query.respond_to? :page
26
+ query = query.per per if query.respond_to? :per
27
+ query
28
+ end
29
+
30
+ # @see Wallaby::ModelServiceProvider#new
31
+ def new(permitted_params, _authorizer)
32
+ @model_class.new normalize permitted_params
33
+ rescue ::ActiveModel::UnknownAttributeError
34
+ @model_class.new
35
+ end
36
+
37
+ # @see Wallaby::ModelServiceProvider#find
38
+ def find(id, permitted_params, _authorizer)
39
+ resource = @model_class.find id
40
+ resource.assign_attributes normalize permitted_params
41
+ resource
42
+ rescue ::ActiveRecord::RecordNotFound
43
+ raise ResourceNotFound, id
44
+ rescue ::ActiveModel::UnknownAttributeError
45
+ resource
46
+ end
47
+
48
+ # @see Wallaby::ModelServiceProvider#create
49
+ def create(resource_with_new_value, params, authorizer)
50
+ save __callee__, resource_with_new_value, params, authorizer
51
+ end
52
+
53
+ # @see Wallaby::ModelServiceProvider#update
54
+ def update(resource_with_new_value, params, authorizer)
55
+ save __callee__, resource_with_new_value, params, authorizer
56
+ end
57
+
58
+ # @see Wallaby::ModelServiceProvider#destroy
59
+ def destroy(resource, _params, _authorizer)
60
+ resource.destroy
61
+ end
62
+
63
+ protected
64
+
65
+ # Save the active record
66
+ # @param action [String] `create`, `update`
67
+ # @param resource [Object]
68
+ # @param _params [ActionController::Parameters]
69
+ # @param authorizer [Object]
70
+ # @return resource itself
71
+ def save(action, resource, _params, authorizer)
72
+ ensure_attributes_for authorizer, action, resource
73
+ resource.save if valid? resource
74
+ resource
75
+ rescue ::ActiveRecord::StatementInvalid => e
76
+ resource.errors.add :base, e.message
77
+ resource
78
+ end
79
+
80
+ # Normalize params
81
+ # @param params [ActionController::Parameters]
82
+ def normalize(params)
83
+ normalizer.normalize params
84
+ end
85
+
86
+ # See if a resource is valid
87
+ # @param resource [Object]
88
+ # @return [Boolean]
89
+ def valid?(resource)
90
+ validator.valid? resource
91
+ end
92
+
93
+ # To make sure that the record can be updated with the values that are
94
+ # allowed to.
95
+ # @param authorizer [Object]
96
+ # @param action [String]
97
+ # @param resource [Object]
98
+ def ensure_attributes_for(authorizer, action, resource)
99
+ return if authorizer.blank?
100
+ restricted_conditions = authorizer.attributes_for action, resource
101
+ resource.assign_attributes restricted_conditions
102
+ end
103
+
104
+ # The params key
105
+ def param_key
106
+ @model_class.model_name.param_key
107
+ end
108
+
109
+ # The list of attributes to whitelist
110
+ # @return [Array]
111
+ def permitted_fields
112
+ @permitted_fields ||=
113
+ permitter.simple_field_names << permitter.compound_hashed_fields
114
+ end
115
+
116
+ # @see Wallaby::ModelServiceProvider::Permitter
117
+ def permitter
118
+ @permitter ||= Permitter.new @model_decorator
119
+ end
120
+
121
+ # @see Wallaby::ModelServiceProvider::Querier
122
+ def querier
123
+ @querier ||= Querier.new @model_decorator
124
+ end
125
+
126
+ # @see Wallaby::ModelServiceProvider::Normalizer
127
+ def normalizer
128
+ @normalizer ||= Normalizer.new @model_decorator
129
+ end
130
+
131
+ # @see Wallaby::ModelServiceProvider::Validator
132
+ def validator
133
+ @validator ||= Validator.new @model_decorator
134
+ end
135
+ end
136
+ end
137
+ end
@@ -1,2 +1,5 @@
1
- class Wallaby::ActiveRecord < Wallaby::Mode
1
+ module Wallaby
2
+ # Active Record mode
3
+ class ActiveRecord < Mode
4
+ end
2
5
  end
@@ -0,0 +1,74 @@
1
+ module Wallaby
2
+ # Resource Decorator base class
3
+ class AbstractResourceDecorator
4
+ class << self
5
+ # Guess the model class from class name
6
+ # @return [Class]
7
+ def model_class
8
+ return unless self < ::Wallaby::ResourceDecorator
9
+ Map.model_class_map name.gsub 'Decorator', EMPTY_STRING
10
+ end
11
+
12
+ # Get the model decorator for the model class
13
+ # It should be the same as #model_decorator
14
+ # @return Wallaby::ModelDecorator
15
+ def model_decorator
16
+ return unless self < ::Wallaby::ResourceDecorator
17
+ Map.model_decorator_map model_class
18
+ end
19
+
20
+ delegation_methods =
21
+ ModelDecorator.instance_methods \
22
+ - ::Object.instance_methods - %i(model_class)
23
+ delegate(*delegation_methods, to: :model_decorator, allow_nil: true)
24
+ end
25
+
26
+ attr_reader :resource, :model_decorator
27
+
28
+ def initialize(resource)
29
+ @resource = resource
30
+ @model_decorator = Map.model_decorator_map model_class
31
+ end
32
+
33
+ # @return [Class] resource's class
34
+ def model_class
35
+ @resource.class
36
+ end
37
+
38
+ # Guess the title for given resource
39
+ # It falls back to primary key value when no text field is found
40
+ # `.to_s` at the end is to ensure String is returned that won't cause any
41
+ # issue when `#to_label` is used in a link_to block. Coz integer is ignored.
42
+ # @return [String]
43
+ def to_label
44
+ (@model_decorator.guess_title(@resource) || primary_key_value).to_s
45
+ end
46
+
47
+ # Return the validation errors
48
+ # @return [Hash, Array]
49
+ def errors
50
+ @model_decorator.form_active_errors(@resource)
51
+ end
52
+
53
+ # @return [Object] primary key value
54
+ def primary_key_value
55
+ @resource.public_send primary_key
56
+ end
57
+
58
+ delegation_methods =
59
+ ModelDecorator.instance_methods \
60
+ - ::Object.instance_methods - %i(model_class)
61
+ delegate(*delegation_methods, to: :model_decorator)
62
+ delegate :to_s, :to_param, to: :resource
63
+
64
+ # We delegate missing methods to resource
65
+ def method_missing(method_id, *args)
66
+ return super unless @resource.respond_to? method_id
67
+ @resource.public_send method_id, *args
68
+ end
69
+
70
+ def respond_to_missing?(method_id, _include_private)
71
+ @resource.respond_to?(method_id) || super
72
+ end
73
+ end
74
+ end
@@ -1,78 +1,7 @@
1
- class Wallaby::ResourceDecorator
2
- class << self
3
- def model_class
4
- if self < Wallaby::ResourceDecorator
5
- @model_class ||= Wallaby::Utils.to_model_class name.gsub('Decorator', ''), name
6
- end
7
- end
8
-
9
- def model_decorator
10
- if self < Wallaby::ResourceDecorator
11
- @model_decorator ||= Wallaby::DecoratorFinder.new_model model_class
12
- end
13
- end
14
-
15
- def decorate(resource)
16
- return resource if resource.is_a? Wallaby::ResourceDecorator
17
- new resource
18
- end
19
-
20
- delegate *begin
21
- Wallaby::ModelDecorator.instance_methods \
22
- - Object.instance_methods - %i( model_class )
23
- end, to: :model_decorator, allow_nil: true
24
- end
25
-
26
- def initialize(resource)
27
- @resource = resource
28
- @model_decorator = self.class.model_decorator || Wallaby::DecoratorFinder.new_model(model_class)
29
- end
30
-
31
- def method_missing(method_id, *args)
32
- if @resource.respond_to? method_id
33
- @resource.public_send method_id, *args
34
- else
35
- super
36
- end
37
- end
38
-
39
- delegate :to_s, :to_param, :to_params, to: :@resource
40
- delegate *begin
41
- Wallaby::ModelDecorator.instance_methods \
42
- - %i( index_fields index_field_names show_fields show_field_names form_fields form_field_names ) \
43
- - Object.instance_methods
44
- end, to: :@model_decorator
45
- attr_reader :model_decorator
46
-
47
- def model_class
48
- @resource.class
49
- end
50
-
51
- def resource
52
- @resource
53
- end
54
-
55
- def to_label
56
- @model_decorator.guess_title(@resource) || primary_key_value
57
- end
58
-
59
- def errors
60
- @model_decorator.form_active_errors(@resource)
61
- end
62
-
63
- def primary_key_value
64
- @resource.public_send primary_key
65
- end
66
-
67
- [ '', 'index_', 'show_', 'form_' ].each do |prefix|
68
- class_eval <<-RUBY
69
- def #{ prefix }fields
70
- @#{ prefix }fields ||= @model_decorator.#{ prefix }fields.dup.freeze
71
- end
72
-
73
- def #{ prefix }field_names
74
- @#{ prefix }field_names ||= @model_decorator.#{ prefix }field_names.dup.freeze
75
- end
76
- RUBY
1
+ module Wallaby
2
+ # Resource Decorator
3
+ # @see Wallaby::AbstractResourceDecorator
4
+ # @overwritable
5
+ class ResourceDecorator < AbstractResourceDecorator
77
6
  end
78
7
  end
@@ -1,4 +1,8 @@
1
1
  module Wallaby
2
- class ModelNotFound < GeneralError
2
+ # Model not found error
3
+ class ModelNotFound < NotFound
4
+ def message
5
+ I18n.t 'errors.not_found.model', model: super
6
+ end
3
7
  end
4
8
  end
@@ -0,0 +1,4 @@
1
+ module Wallaby
2
+ class NotFound < GeneralError
3
+ end
4
+ end
@@ -1,4 +1,8 @@
1
1
  module Wallaby
2
- class ResourceNotFound < GeneralError
2
+ # Resource not found error
3
+ class ResourceNotFound < NotFound
4
+ def message
5
+ I18n.t 'errors.not_found.resource', resource: super
6
+ end
3
7
  end
4
8
  end
@@ -1,30 +1,53 @@
1
- class Wallaby::FormBuilder < ActionView::Helpers::FormBuilder
2
- def error_class(field_name)
3
- 'has-error' if has_error? field_name
4
- end
1
+ module Wallaby
2
+ # Custom form builder to add more helper functions
3
+ class FormBuilder < ::ActionView::Helpers::FormBuilder
4
+ # Return error class if there is error
5
+ # @param field_name [String/Symbol]
6
+ # @return [String]
7
+ def error_class(field_name)
8
+ 'has-error' if object.errors[field_name].present?
9
+ end
5
10
 
6
- def error_messages(field_name)
7
- errors = Array object.errors[ field_name ]
8
- return if errors.blank?
11
+ # Build up the HTML for displaying error messages
12
+ # @param field_name [String/Symbol]
13
+ # @return [String] HTML
14
+ def error_messages(field_name)
15
+ errors = Array object.errors[field_name]
16
+ return if errors.blank?
9
17
 
10
- content_tag :ul, class: 'text-danger' do
11
- errors.each do |message|
12
- concat content_tag :li, content_tag(:small, raw(message))
18
+ content_tag :ul, class: 'errors' do
19
+ errors.each do |message|
20
+ concat content_tag :li, content_tag(:small, raw(message))
21
+ end
13
22
  end
14
23
  end
15
- end
16
24
 
17
- protected
18
- def method_missing(method, *args, &block)
19
- if @template.respond_to? method
25
+ # Extend label to accept proc type `text` argument
26
+ def label(method, text = nil, options = {}, &block)
27
+ text = instance_exec(&text) if text.respond_to? :call
28
+ super
29
+ end
30
+
31
+ # Extend select to accept proc type `choices` argument
32
+ def select(method, choices = nil, options = {}, html_options = {}, &block)
33
+ choices = instance_exec(&choices) if choices.respond_to? :call
34
+ super
35
+ end
36
+
37
+ protected
38
+
39
+ # Try to delegate method to `@template`
40
+ def method_missing(method, *args, &block)
41
+ return super unless @template.respond_to? method
42
+ # Delegate the method so that we don't come in here the next time
43
+ # same method is called
20
44
  self.class.delegate method, to: :@template
21
45
  @template.public_send method, *args, &block
22
- else
23
- super
24
46
  end
25
- end
26
47
 
27
- def has_error?(field_name)
28
- object.errors[field_name].present?
48
+ # Pair with #method_missing
49
+ def respond_to_missing?(method, _include_private)
50
+ @template.respond_to?(method) || super
51
+ end
29
52
  end
30
53
  end
@@ -1,30 +1,40 @@
1
- module Wallaby::ApplicationHelper
2
- def clean_params
3
- params.except :resources, :action
4
- end
1
+ module Wallaby
2
+ # Application helper
3
+ module ApplicationHelper
4
+ # Override `actionview/lib/action_view/routing_url_for.rb#url_for`
5
+ # to handle the url_for properly for wallaby engine
6
+ def url_for(options = nil)
7
+ # possible Hash or Parameters
8
+ if options.respond_to?(:to_h) \
9
+ && options[:resources].present? && options[:action].present?
10
+ UrlFor.handle wallaby_engine, options
11
+ else
12
+ super options
13
+ end
14
+ end
5
15
 
6
- # override `actionview/lib/action_view/routing_url_for.rb#url_for`
7
- def url_for(options = nil)
8
- if options.is_a?(Hash) && options.slice(:action, :resources).length == 2
9
- return wallaby_resourceful_url_for options
16
+ # Add turbolinks options when it's enabled
17
+ def stylesheet_link_tag(*sources)
18
+ default_options =
19
+ if Wallaby.configuration.features.turbolinks_enabled
20
+ { 'data-turbolinks-track' => true }
21
+ else
22
+ {}
23
+ end
24
+ options = default_options.merge!(sources.extract_options!.stringify_keys)
25
+ super(*sources, options)
10
26
  end
11
- super
12
- end
13
27
 
14
- def wallaby_resourceful_url_for(options = {})
15
- # DEPRECATION WARNING: You are calling a `*_path` helper with the `only_path` option explicitly set to `false`. This option will stop working on path helpers in Rails 5. Use the corresponding `*_url` helper instead.
16
- options = options.except :only_path
17
- case options[:action]
18
- when 'index', 'create'
19
- wallaby_engine.resources_path options
20
- when 'new'
21
- wallaby_engine.new_resource_path options
22
- when 'edit'
23
- wallaby_engine.edit_resource_path options
24
- when 'show', 'update', 'destroy'
25
- wallaby_engine.resource_path options
26
- else
27
- wallaby_engine.url_for options
28
+ # Add turbolinks options when it's enabled
29
+ def javascript_include_tag(*sources)
30
+ default_options =
31
+ if Wallaby.configuration.features.turbolinks_enabled
32
+ { 'data-turbolinks-track' => true, 'data-turbolinks-eval' => false }
33
+ else
34
+ {}
35
+ end
36
+ options = default_options.merge!(sources.extract_options!.stringify_keys)
37
+ super(*sources, options)
28
38
  end
29
39
  end
30
40
  end
@@ -0,0 +1,52 @@
1
+ module Wallaby
2
+ # NOTE: Global helper methods should go in here
3
+ module BaseHelper
4
+ include StylingHelper
5
+ include LinksHelper
6
+
7
+ # @see Utils.to_model_label
8
+ def to_model_label(model_class)
9
+ Utils.to_model_label model_class
10
+ end
11
+
12
+ # @see Map.resources_name_map
13
+ def to_resources_name(model_class)
14
+ Map.resources_name_map model_class
15
+ end
16
+
17
+ # @return [String] css classes for body tag
18
+ def body_class
19
+ [
20
+ params[:action],
21
+ current_resources_name.try(:gsub, COLONS, '__'),
22
+ content_for(:custom_body_class)
23
+ ].compact.join SPACE
24
+ end
25
+
26
+ # Turn a list of classes into tree structure
27
+ # @param classes [Array] a list of all the classes that wallaby supports
28
+ # @return [Array] a tree structure of given classes
29
+ def model_classes(classes = Map.model_classes)
30
+ nested_hash = classes.each_with_object({}) do |klass, hash|
31
+ hash[klass] = Node.new(klass)
32
+ end
33
+ nested_hash.each do |klass, node|
34
+ node.parent = parent = nested_hash[klass.superclass]
35
+ parent.children << node if parent
36
+ end
37
+ nested_hash.values.select { |v| v.parent.nil? }
38
+ end
39
+
40
+ # @param array [Array] root classes
41
+ # @return [String] HTML for the whole tree
42
+ def model_tree(array)
43
+ return EMPTY_STRING.html_safe if array.blank?
44
+ content_tag :ul, class: 'dropdown-menu' do
45
+ array.sort_by(&:name).each do |node|
46
+ content = index_link(node.klass).try :<<, model_tree(node.children)
47
+ concat content_tag(:li, content)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,21 +1,45 @@
1
- module Wallaby::FormHelper
2
- def form_type_partial_render(options = {}, locals = {}, &block)
3
- form = locals[:form]
4
- field_name = locals[:field_name].to_s
5
-
6
- fail ArgumentError unless form.present? && field_name.present? && form.object.is_a?(Wallaby::ResourceDecorator)
7
-
8
- locals[:object] = object = form.object
9
- locals[:metadata] = object.form_metadata_of locals[:field_name]
10
- locals[:value] = object.public_send locals[:field_name]
1
+ module Wallaby
2
+ # Form helper
3
+ module FormHelper
4
+ # @param options [Hash, String]
5
+ # @param locals [Hash] local variables for the partial
6
+ def form_type_partial_render(options = {}, locals = {}, &block)
7
+ PartialRenderer.render_form self, options, locals, &block
8
+ end
11
9
 
12
- render(options, locals, &block) or render('string', locals, &block)
13
- end
10
+ # To generate remote url for auto select plugin.
11
+ # @see app/assets/javascripts/wallaby/auto_select.js
12
+ # @param url [String, nil]
13
+ # if url is nil, it will fall back to default remote url
14
+ # @param model_class [Class]
15
+ # @param wildcard [String] wildcard that auto_select uses to replace with
16
+ # the typed keyword
17
+ def remote_url(url, model_class, wildcard = 'QUERY')
18
+ url ||
19
+ index_path(
20
+ model_class, url_params: {
21
+ q: wildcard, per: Wallaby.configuration.pagination.page_size
22
+ }
23
+ )
24
+ end
14
25
 
15
- def model_choices(model_decorator)
16
- collection = model_servicer(model_decorator).collection Hash.new, current_ability
17
- decorate(collection).map do |decorated|
18
- [ decorated.to_label, decorated.primary_key_value ]
26
+ # To generate dropdown options (class => url) for polymorphic class.
27
+ # @see app/assets/javascripts/wallaby/auto_select.js
28
+ # This function will pull out remote urls from `metadata[:remote_urls]`
29
+ # (Class => url).
30
+ # @param metadata [Hash]
31
+ # @param wildcard [String]
32
+ # @param select_options [Hash]
33
+ # @return [String] HTML
34
+ def polymorphic_options(metadata, wildcard = 'QUERY', select_options = {})
35
+ urls = metadata[:remote_urls] || {}
36
+ options = (metadata[:polymorphic_list] || []).map do |klass|
37
+ [
38
+ klass, klass,
39
+ { data: { url: remote_url(urls[klass], klass, wildcard) } }
40
+ ]
41
+ end
42
+ options_for_select options, select_options
19
43
  end
20
44
  end
21
45
  end
@@ -0,0 +1,59 @@
1
+ module Wallaby
2
+ # Helper methods for index page
3
+ module IndexHelper
4
+ # Wrap the collection with paginator
5
+ # @param model_class [Class]
6
+ # @param collection [#map]
7
+ # @param params [ActionController::Parameters]
8
+ # @return [Wallaby::ResourcePaginator]
9
+ def paginate(model_class, collection, params)
10
+ Map.paginator_map(model_class).new model_class, collection, params
11
+ end
12
+
13
+ # Just a label
14
+ # @return [String]
15
+ def all_label
16
+ t 'filters.all'
17
+ end
18
+
19
+ # Label for a given name
20
+ # @param filter_name [String, Symbol]
21
+ # @param filters [Hash]
22
+ # @return [String]
23
+ def filter_label(filter_name, filters)
24
+ filters[filter_name].try(:[], :label) || filter_name.to_s.humanize
25
+ end
26
+
27
+ # Export link for a given model_class
28
+ # @param model_class [Class]
29
+ # @return [String] HTML anchor link
30
+ def export_link(model_class)
31
+ url_params = index_params.except(:page, :per).merge(format: 'csv')
32
+ index_link model_class, url_params: url_params do
33
+ t 'links.export', ext: 'CSV'
34
+ end
35
+ end
36
+
37
+ # Link for a given model class and filter name
38
+ # @param model_class [Class]
39
+ # @param filter_name [String, Symbol]
40
+ # @param filters [Hash]
41
+ # @return [String] HTML anchor link
42
+ def filter_link(model_class, filter_name, filters)
43
+ is_all = filter_name == :all
44
+ config = filters[filter_name] || {}
45
+ label = is_all ? all_label : filter_label(filter_name, filters)
46
+ url_params = if config[:default] then index_params.except(:filter)
47
+ else index_params.merge(filter: filter_name)
48
+ end
49
+ index_link(model_class, url_params: url_params) { label }
50
+ end
51
+
52
+ # Sort link builder
53
+ # @return [Sorting::LinkBuilder]
54
+ def sort_link_builder
55
+ @sort_link_builder ||=
56
+ Sorting::LinkBuilder.new current_model_decorator, index_params, self
57
+ end
58
+ end
59
+ end