wallaby 5.0.1 → 5.1.3

Sign up to get free protection for your applications and to get access to all the features.
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