rails_admin-lbgraham 0.4.2

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 (416) hide show
  1. data/Gemfile +51 -0
  2. data/LICENSE.md +20 -0
  3. data/README.md +175 -0
  4. data/Rakefile +19 -0
  5. data/app/assets/images/rails_admin/aristo/images/bg_fallback.png +0 -0
  6. data/app/assets/images/rails_admin/aristo/images/icon_sprite.png +0 -0
  7. data/app/assets/images/rails_admin/aristo/images/progress_bar.gif +0 -0
  8. data/app/assets/images/rails_admin/aristo/images/slider_handles.png +0 -0
  9. data/app/assets/images/rails_admin/aristo/images/ui-icons_222222_256x240.png +0 -0
  10. data/app/assets/images/rails_admin/aristo/images/ui-icons_454545_256x240.png +0 -0
  11. data/app/assets/images/rails_admin/bullet_black.png +0 -0
  12. data/app/assets/images/rails_admin/bullet_white.png +0 -0
  13. data/app/assets/images/rails_admin/calendar.png +0 -0
  14. data/app/assets/images/rails_admin/clock.png +0 -0
  15. data/app/assets/images/rails_admin/colorpicker/colorpicker_background.png +0 -0
  16. data/app/assets/images/rails_admin/colorpicker/colorpicker_hex.png +0 -0
  17. data/app/assets/images/rails_admin/colorpicker/colorpicker_hsb_b.png +0 -0
  18. data/app/assets/images/rails_admin/colorpicker/colorpicker_hsb_h.png +0 -0
  19. data/app/assets/images/rails_admin/colorpicker/colorpicker_hsb_s.png +0 -0
  20. data/app/assets/images/rails_admin/colorpicker/colorpicker_indic.gif +0 -0
  21. data/app/assets/images/rails_admin/colorpicker/colorpicker_overlay.png +0 -0
  22. data/app/assets/images/rails_admin/colorpicker/colorpicker_rgb_b.png +0 -0
  23. data/app/assets/images/rails_admin/colorpicker/colorpicker_rgb_g.png +0 -0
  24. data/app/assets/images/rails_admin/colorpicker/colorpicker_rgb_r.png +0 -0
  25. data/app/assets/images/rails_admin/colorpicker/colorpicker_select.gif +0 -0
  26. data/app/assets/images/rails_admin/colorpicker/colorpicker_submit.png +0 -0
  27. data/app/assets/images/rails_admin/colorpicker/custom_background.png +0 -0
  28. data/app/assets/images/rails_admin/colorpicker/custom_hex.png +0 -0
  29. data/app/assets/images/rails_admin/colorpicker/custom_hsb_b.png +0 -0
  30. data/app/assets/images/rails_admin/colorpicker/custom_hsb_h.png +0 -0
  31. data/app/assets/images/rails_admin/colorpicker/custom_hsb_s.png +0 -0
  32. data/app/assets/images/rails_admin/colorpicker/custom_indic.gif +0 -0
  33. data/app/assets/images/rails_admin/colorpicker/custom_rgb_b.png +0 -0
  34. data/app/assets/images/rails_admin/colorpicker/custom_rgb_g.png +0 -0
  35. data/app/assets/images/rails_admin/colorpicker/custom_rgb_r.png +0 -0
  36. data/app/assets/images/rails_admin/colorpicker/custom_submit.png +0 -0
  37. data/app/assets/images/rails_admin/colorpicker/select.png +0 -0
  38. data/app/assets/images/rails_admin/colorpicker/select2.png +0 -0
  39. data/app/assets/images/rails_admin/colorpicker/slider.png +0 -0
  40. data/app/assets/images/rails_admin/logo.png +0 -0
  41. data/app/assets/images/rails_admin/magnifier.png +0 -0
  42. data/app/assets/images/rails_admin/multiselect/icon_sprite.png +0 -0
  43. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-n-dark.png +0 -0
  44. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-n-light.png +0 -0
  45. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-s-dark.png +0 -0
  46. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-s-light.png +0 -0
  47. data/app/assets/javascripts/rails_admin/custom/ui.js +12 -0
  48. data/app/assets/javascripts/rails_admin/jquery.colorpicker.js +484 -0
  49. data/app/assets/javascripts/rails_admin/jquery.pjax.js +743 -0
  50. data/app/assets/javascripts/rails_admin/jquery.ui.timepicker.js +1371 -0
  51. data/app/assets/javascripts/rails_admin/ra.datetimepicker.js +67 -0
  52. data/app/assets/javascripts/rails_admin/ra.filter-box.js +142 -0
  53. data/app/assets/javascripts/rails_admin/ra.filtering-multiselect.js +292 -0
  54. data/app/assets/javascripts/rails_admin/ra.filtering-select.js +190 -0
  55. data/app/assets/javascripts/rails_admin/ra.nested-form-hooks.coffee +41 -0
  56. data/app/assets/javascripts/rails_admin/ra.remote-form.js +151 -0
  57. data/app/assets/javascripts/rails_admin/ra.widgets.coffee +210 -0
  58. data/app/assets/javascripts/rails_admin/rails_admin.js.erb +28 -0
  59. data/app/assets/javascripts/rails_admin/themes/cerulean/ui.js +0 -0
  60. data/app/assets/javascripts/rails_admin/themes/default/ui.js +12 -0
  61. data/app/assets/javascripts/rails_admin/ui.js.coffee +66 -0
  62. data/app/assets/stylesheets/rails_admin/aristo/images/bg_fallback.png +0 -0
  63. data/app/assets/stylesheets/rails_admin/aristo/images/icon_sprite.png +0 -0
  64. data/app/assets/stylesheets/rails_admin/aristo/images/progress_bar.gif +0 -0
  65. data/app/assets/stylesheets/rails_admin/aristo/images/slider_handles.png +0 -0
  66. data/app/assets/stylesheets/rails_admin/aristo/images/ui-icons_222222_256x240.png +0 -0
  67. data/app/assets/stylesheets/rails_admin/aristo/images/ui-icons_454545_256x240.png +0 -0
  68. data/app/assets/stylesheets/rails_admin/aristo/jquery-ui-1.8.7.custom.css.scss +733 -0
  69. data/app/assets/stylesheets/rails_admin/base/README.txt +2 -0
  70. data/app/assets/stylesheets/rails_admin/base/mixins.css.scss +1 -0
  71. data/app/assets/stylesheets/rails_admin/base/theming.css.scss +270 -0
  72. data/app/assets/stylesheets/rails_admin/base/variables.css.scss +1 -0
  73. data/app/assets/stylesheets/rails_admin/custom/mixins.css.scss +12 -0
  74. data/app/assets/stylesheets/rails_admin/custom/theming.css.scss +13 -0
  75. data/app/assets/stylesheets/rails_admin/custom/variables.css.scss +15 -0
  76. data/app/assets/stylesheets/rails_admin/imports.css.scss.erb +82 -0
  77. data/app/assets/stylesheets/rails_admin/jquery.colorpicker.css.scss +182 -0
  78. data/app/assets/stylesheets/rails_admin/jquery.ui.timepicker.css.scss +69 -0
  79. data/app/assets/stylesheets/rails_admin/ra.calendar-additions.css.scss +25 -0
  80. data/app/assets/stylesheets/rails_admin/ra.filtering-multiselect.css.scss +90 -0
  81. data/app/assets/stylesheets/rails_admin/ra.widgets.css.scss +8 -0
  82. data/app/assets/stylesheets/rails_admin/rails_admin.css +4 -0
  83. data/app/assets/stylesheets/rails_admin/themes/cerulean/mixins.css.scss +0 -0
  84. data/app/assets/stylesheets/rails_admin/themes/cerulean/theming.css.scss +97 -0
  85. data/app/assets/stylesheets/rails_admin/themes/cerulean/variables.css.scss +168 -0
  86. data/app/assets/stylesheets/rails_admin/themes/default/mixins.css.scss +8 -0
  87. data/app/assets/stylesheets/rails_admin/themes/default/theming.css.scss +11 -0
  88. data/app/assets/stylesheets/rails_admin/themes/default/variables.css.scss +12 -0
  89. data/app/controllers/rails_admin/application_controller.rb +84 -0
  90. data/app/controllers/rails_admin/main_controller.rb +153 -0
  91. data/app/helpers/rails_admin/application_helper.rb +147 -0
  92. data/app/helpers/rails_admin/form_builder.rb +117 -0
  93. data/app/helpers/rails_admin/main_helper.rb +36 -0
  94. data/app/views/kaminari/twitter-bootstrap/_gap.html.haml +2 -0
  95. data/app/views/kaminari/twitter-bootstrap/_next_page.html.haml +4 -0
  96. data/app/views/kaminari/twitter-bootstrap/_page.html.haml +4 -0
  97. data/app/views/kaminari/twitter-bootstrap/_paginator.html.haml +10 -0
  98. data/app/views/kaminari/twitter-bootstrap/_prev_page.html.haml +4 -0
  99. data/app/views/layouts/rails_admin/_secondary_navigation.html.haml +12 -0
  100. data/app/views/layouts/rails_admin/application.html.haml +27 -0
  101. data/app/views/layouts/rails_admin/pjax.html.haml +16 -0
  102. data/app/views/rails_admin/main/_dashboard_history.html.haml +20 -0
  103. data/app/views/rails_admin/main/_delete_notice.html.haml +19 -0
  104. data/app/views/rails_admin/main/_form_colorpicker.html.haml +1 -0
  105. data/app/views/rails_admin/main/_form_datetime.html.haml +1 -0
  106. data/app/views/rails_admin/main/_form_enumeration.html.haml +18 -0
  107. data/app/views/rails_admin/main/_form_field.html.haml +1 -0
  108. data/app/views/rails_admin/main/_form_file_upload.html.haml +13 -0
  109. data/app/views/rails_admin/main/_form_filtering_multiselect.html.haml +47 -0
  110. data/app/views/rails_admin/main/_form_filtering_select.html.haml +37 -0
  111. data/app/views/rails_admin/main/_form_nested_many.html.haml +14 -0
  112. data/app/views/rails_admin/main/_form_nested_one.html.haml +10 -0
  113. data/app/views/rails_admin/main/_form_polymorphic_association.html.haml +10 -0
  114. data/app/views/rails_admin/main/_form_text.html.haml +31 -0
  115. data/app/views/rails_admin/main/_submit_buttons.html.haml +15 -0
  116. data/app/views/rails_admin/main/bulk_delete.html.haml +11 -0
  117. data/app/views/rails_admin/main/dashboard.html.haml +35 -0
  118. data/app/views/rails_admin/main/delete.html.haml +18 -0
  119. data/app/views/rails_admin/main/edit.html.haml +2 -0
  120. data/app/views/rails_admin/main/export.html.haml +75 -0
  121. data/app/views/rails_admin/main/history.html.haml +49 -0
  122. data/app/views/rails_admin/main/index.html.haml +140 -0
  123. data/app/views/rails_admin/main/new.html.haml +2 -0
  124. data/app/views/rails_admin/main/show.html.haml +16 -0
  125. data/config/initializers/active_record_extensions.rb +19 -0
  126. data/config/initializers/devise_patch.rb +9 -0
  127. data/config/initializers/haml.rb +2 -0
  128. data/config/initializers/mongoid_extensions.rb +4 -0
  129. data/config/locales/rails_admin.en.yml +130 -0
  130. data/config/routes.rb +12 -0
  131. data/lib/generators/rails_admin/install_generator.rb +85 -0
  132. data/lib/generators/rails_admin/templates/drop.rb +18 -0
  133. data/lib/generators/rails_admin/templates/initializer.erb +100 -0
  134. data/lib/generators/rails_admin/templates/migration.rb +18 -0
  135. data/lib/generators/rails_admin/uninstall_generator.rb +22 -0
  136. data/lib/generators/rails_admin/utils.rb +30 -0
  137. data/lib/rails_admin.rb +34 -0
  138. data/lib/rails_admin/abstract_model.rb +128 -0
  139. data/lib/rails_admin/adapters/active_record.rb +296 -0
  140. data/lib/rails_admin/adapters/active_record/abstract_object.rb +32 -0
  141. data/lib/rails_admin/adapters/mongoid.rb +430 -0
  142. data/lib/rails_admin/adapters/mongoid/abstract_object.rb +43 -0
  143. data/lib/rails_admin/adapters/mongoid/extension.rb +45 -0
  144. data/lib/rails_admin/config.rb +333 -0
  145. data/lib/rails_admin/config/actions.rb +121 -0
  146. data/lib/rails_admin/config/actions/base.rb +132 -0
  147. data/lib/rails_admin/config/actions/bulk_delete.rb +55 -0
  148. data/lib/rails_admin/config/actions/dashboard.rb +52 -0
  149. data/lib/rails_admin/config/actions/delete.rb +56 -0
  150. data/lib/rails_admin/config/actions/edit.rb +55 -0
  151. data/lib/rails_admin/config/actions/export.rb +40 -0
  152. data/lib/rails_admin/config/actions/history_index.rb +38 -0
  153. data/lib/rails_admin/config/actions/history_show.rb +38 -0
  154. data/lib/rails_admin/config/actions/index.rb +85 -0
  155. data/lib/rails_admin/config/actions/new.rb +65 -0
  156. data/lib/rails_admin/config/actions/show.rb +34 -0
  157. data/lib/rails_admin/config/actions/show_in_app.rb +27 -0
  158. data/lib/rails_admin/config/configurable.rb +92 -0
  159. data/lib/rails_admin/config/fields.rb +87 -0
  160. data/lib/rails_admin/config/fields/association.rb +107 -0
  161. data/lib/rails_admin/config/fields/base.rb +320 -0
  162. data/lib/rails_admin/config/fields/factories/association.rb +32 -0
  163. data/lib/rails_admin/config/fields/factories/carrierwave.rb +31 -0
  164. data/lib/rails_admin/config/fields/factories/devise.rb +27 -0
  165. data/lib/rails_admin/config/fields/factories/dragonfly.rb +27 -0
  166. data/lib/rails_admin/config/fields/factories/enum.rb +11 -0
  167. data/lib/rails_admin/config/fields/factories/paperclip.rb +26 -0
  168. data/lib/rails_admin/config/fields/factories/password.rb +17 -0
  169. data/lib/rails_admin/config/fields/group.rb +78 -0
  170. data/lib/rails_admin/config/fields/types.rb +27 -0
  171. data/lib/rails_admin/config/fields/types/all.rb +25 -0
  172. data/lib/rails_admin/config/fields/types/belongs_to_association.rb +41 -0
  173. data/lib/rails_admin/config/fields/types/boolean.rb +38 -0
  174. data/lib/rails_admin/config/fields/types/bson_object_id.rb +45 -0
  175. data/lib/rails_admin/config/fields/types/carrierwave.rb +31 -0
  176. data/lib/rails_admin/config/fields/types/color.rb +37 -0
  177. data/lib/rails_admin/config/fields/types/date.rb +24 -0
  178. data/lib/rails_admin/config/fields/types/datetime.rb +164 -0
  179. data/lib/rails_admin/config/fields/types/decimal.rb +14 -0
  180. data/lib/rails_admin/config/fields/types/dragonfly.rb +41 -0
  181. data/lib/rails_admin/config/fields/types/enum.rb +39 -0
  182. data/lib/rails_admin/config/fields/types/file_upload.rb +65 -0
  183. data/lib/rails_admin/config/fields/types/float.rb +14 -0
  184. data/lib/rails_admin/config/fields/types/has_and_belongs_to_many_association.rb +14 -0
  185. data/lib/rails_admin/config/fields/types/has_many_association.rb +32 -0
  186. data/lib/rails_admin/config/fields/types/has_one_association.rb +39 -0
  187. data/lib/rails_admin/config/fields/types/hidden.rb +27 -0
  188. data/lib/rails_admin/config/fields/types/integer.rb +22 -0
  189. data/lib/rails_admin/config/fields/types/paperclip.rb +28 -0
  190. data/lib/rails_admin/config/fields/types/password.rb +39 -0
  191. data/lib/rails_admin/config/fields/types/polymorphic_association.rb +80 -0
  192. data/lib/rails_admin/config/fields/types/serialized.rb +22 -0
  193. data/lib/rails_admin/config/fields/types/string.rb +43 -0
  194. data/lib/rails_admin/config/fields/types/text.rb +97 -0
  195. data/lib/rails_admin/config/fields/types/time.rb +36 -0
  196. data/lib/rails_admin/config/fields/types/timestamp.rb +18 -0
  197. data/lib/rails_admin/config/groupable.rb +18 -0
  198. data/lib/rails_admin/config/has_fields.rb +136 -0
  199. data/lib/rails_admin/config/has_groups.rb +23 -0
  200. data/lib/rails_admin/config/hideable.rb +28 -0
  201. data/lib/rails_admin/config/lazy_model.rb +21 -0
  202. data/lib/rails_admin/config/model.rb +109 -0
  203. data/lib/rails_admin/config/proxyable.rb +12 -0
  204. data/lib/rails_admin/config/proxyable/proxy.rb +43 -0
  205. data/lib/rails_admin/config/sections.rb +39 -0
  206. data/lib/rails_admin/config/sections/base.rb +46 -0
  207. data/lib/rails_admin/config/sections/create.rb +11 -0
  208. data/lib/rails_admin/config/sections/edit.rb +11 -0
  209. data/lib/rails_admin/config/sections/export.rb +11 -0
  210. data/lib/rails_admin/config/sections/list.rb +27 -0
  211. data/lib/rails_admin/config/sections/modal.rb +10 -0
  212. data/lib/rails_admin/config/sections/nested.rb +10 -0
  213. data/lib/rails_admin/config/sections/show.rb +10 -0
  214. data/lib/rails_admin/config/sections/update.rb +10 -0
  215. data/lib/rails_admin/engine.rb +27 -0
  216. data/lib/rails_admin/extension.rb +29 -0
  217. data/lib/rails_admin/extensions/cancan.rb +5 -0
  218. data/lib/rails_admin/extensions/cancan/authorization_adapter.rb +59 -0
  219. data/lib/rails_admin/extensions/history.rb +5 -0
  220. data/lib/rails_admin/extensions/history/auditing_adapter.rb +37 -0
  221. data/lib/rails_admin/extensions/history/history.rb +36 -0
  222. data/lib/rails_admin/extensions/paper_trail.rb +5 -0
  223. data/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +93 -0
  224. data/lib/rails_admin/i18n_support.rb +43 -0
  225. data/lib/rails_admin/support/core_extensions.rb +44 -0
  226. data/lib/rails_admin/support/csv_converter.rb +105 -0
  227. data/lib/rails_admin/version.rb +18 -0
  228. data/lib/tasks/rails_admin.rake +48 -0
  229. data/spec/ci.sh +2 -0
  230. data/spec/controllers/rails_admin/application_controller_spec.rb +30 -0
  231. data/spec/controllers/rails_admin/main_controller_spec.rb +337 -0
  232. data/spec/dummy_app/Gemfile +48 -0
  233. data/spec/dummy_app/Rakefile +7 -0
  234. data/spec/dummy_app/app/active_record/abstract.rb +5 -0
  235. data/spec/dummy_app/app/active_record/another_field_test.rb +4 -0
  236. data/spec/dummy_app/app/active_record/ball.rb +9 -0
  237. data/spec/dummy_app/app/active_record/carrierwave_uploader.rb +53 -0
  238. data/spec/dummy_app/app/active_record/category.rb +5 -0
  239. data/spec/dummy_app/app/active_record/cms.rb +5 -0
  240. data/spec/dummy_app/app/active_record/cms/basic_page.rb +9 -0
  241. data/spec/dummy_app/app/active_record/cms/unscoped_page.rb +3 -0
  242. data/spec/dummy_app/app/active_record/comment.rb +5 -0
  243. data/spec/dummy_app/app/active_record/comment/confirmed.rb +3 -0
  244. data/spec/dummy_app/app/active_record/division.rb +15 -0
  245. data/spec/dummy_app/app/active_record/draft.rb +13 -0
  246. data/spec/dummy_app/app/active_record/fan.rb +7 -0
  247. data/spec/dummy_app/app/active_record/field_test.rb +19 -0
  248. data/spec/dummy_app/app/active_record/hardball.rb +2 -0
  249. data/spec/dummy_app/app/active_record/image.rb +6 -0
  250. data/spec/dummy_app/app/active_record/league.rb +12 -0
  251. data/spec/dummy_app/app/active_record/nested_field_test.rb +8 -0
  252. data/spec/dummy_app/app/active_record/player.rb +27 -0
  253. data/spec/dummy_app/app/active_record/team.rb +28 -0
  254. data/spec/dummy_app/app/active_record/user.rb +25 -0
  255. data/spec/dummy_app/app/assets/images/rails.png +0 -0
  256. data/spec/dummy_app/app/assets/javascripts/application.js +15 -0
  257. data/spec/dummy_app/app/assets/stylesheets/application.css +13 -0
  258. data/spec/dummy_app/app/controllers/application_controller.rb +3 -0
  259. data/spec/dummy_app/app/controllers/players_controller.rb +5 -0
  260. data/spec/dummy_app/app/locales/models.en.yml +20 -0
  261. data/spec/dummy_app/app/mongoid/another_field_test.rb +6 -0
  262. data/spec/dummy_app/app/mongoid/ball.rb +14 -0
  263. data/spec/dummy_app/app/mongoid/carrierwave_uploader.rb +53 -0
  264. data/spec/dummy_app/app/mongoid/category.rb +7 -0
  265. data/spec/dummy_app/app/mongoid/cms.rb +5 -0
  266. data/spec/dummy_app/app/mongoid/cms/basic_page.rb +12 -0
  267. data/spec/dummy_app/app/mongoid/cms/unscoped_page.rb +5 -0
  268. data/spec/dummy_app/app/mongoid/comment.rb +9 -0
  269. data/spec/dummy_app/app/mongoid/comment/confirmed.rb +3 -0
  270. data/spec/dummy_app/app/mongoid/division.rb +14 -0
  271. data/spec/dummy_app/app/mongoid/draft.rb +22 -0
  272. data/spec/dummy_app/app/mongoid/embed.rb +6 -0
  273. data/spec/dummy_app/app/mongoid/fan.rb +12 -0
  274. data/spec/dummy_app/app/mongoid/field_test.rb +57 -0
  275. data/spec/dummy_app/app/mongoid/hardball.rb +2 -0
  276. data/spec/dummy_app/app/mongoid/image.rb +9 -0
  277. data/spec/dummy_app/app/mongoid/league.rb +16 -0
  278. data/spec/dummy_app/app/mongoid/nested_field_test.rb +13 -0
  279. data/spec/dummy_app/app/mongoid/player.rb +41 -0
  280. data/spec/dummy_app/app/mongoid/team.rb +47 -0
  281. data/spec/dummy_app/app/mongoid/user.rb +61 -0
  282. data/spec/dummy_app/app/views/layouts/application.html.erb +14 -0
  283. data/spec/dummy_app/app/views/players/show.html.haml +1 -0
  284. data/spec/dummy_app/config.ru +4 -0
  285. data/spec/dummy_app/config/application.rb +69 -0
  286. data/spec/dummy_app/config/boot.rb +9 -0
  287. data/spec/dummy_app/config/database.yml +25 -0
  288. data/spec/dummy_app/config/environment.rb +5 -0
  289. data/spec/dummy_app/config/environments/development.rb +37 -0
  290. data/spec/dummy_app/config/environments/production.rb +67 -0
  291. data/spec/dummy_app/config/environments/test.rb +37 -0
  292. data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
  293. data/spec/dummy_app/config/initializers/devise.rb +216 -0
  294. data/spec/dummy_app/config/initializers/dragonfly.rb +11 -0
  295. data/spec/dummy_app/config/initializers/inflections.rb +15 -0
  296. data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
  297. data/spec/dummy_app/config/initializers/rails_admin.rb +8 -0
  298. data/spec/dummy_app/config/initializers/secret_token.rb +7 -0
  299. data/spec/dummy_app/config/initializers/session_patch.rb +16 -0
  300. data/spec/dummy_app/config/initializers/session_store.rb +8 -0
  301. data/spec/dummy_app/config/initializers/strong_parameters.rb +2 -0
  302. data/spec/dummy_app/config/initializers/wrap_parameters.rb +14 -0
  303. data/spec/dummy_app/config/locales/fr.yml +24 -0
  304. data/spec/dummy_app/config/mongoid.yml +22 -0
  305. data/spec/dummy_app/config/routes.rb +10 -0
  306. data/spec/dummy_app/db/migrate/00000000000001_create_divisions_migration.rb +13 -0
  307. data/spec/dummy_app/db/migrate/00000000000002_create_drafts_migration.rb +19 -0
  308. data/spec/dummy_app/db/migrate/00000000000003_create_leagues_migration.rb +12 -0
  309. data/spec/dummy_app/db/migrate/00000000000004_create_players_migration.rb +20 -0
  310. data/spec/dummy_app/db/migrate/00000000000005_create_teams_migration.rb +22 -0
  311. data/spec/dummy_app/db/migrate/00000000000006_devise_create_users.rb +49 -0
  312. data/spec/dummy_app/db/migrate/00000000000007_create_histories_table.rb +16 -0
  313. data/spec/dummy_app/db/migrate/00000000000008_create_fans_migration.rb +12 -0
  314. data/spec/dummy_app/db/migrate/00000000000009_create_fans_teams_migration.rb +11 -0
  315. data/spec/dummy_app/db/migrate/00000000000010_add_revenue_to_team_migration.rb +9 -0
  316. data/spec/dummy_app/db/migrate/00000000000011_add_suspended_to_player_migration.rb +9 -0
  317. data/spec/dummy_app/db/migrate/00000000000012_add_avatar_columns_to_user.rb +16 -0
  318. data/spec/dummy_app/db/migrate/00000000000013_add_roles_to_user.rb +9 -0
  319. data/spec/dummy_app/db/migrate/00000000000014_add_color_to_team_migration.rb +9 -0
  320. data/spec/dummy_app/db/migrate/20101223222233_create_rel_tests.rb +15 -0
  321. data/spec/dummy_app/db/migrate/20110103205808_create_comments.rb +15 -0
  322. data/spec/dummy_app/db/migrate/20110123042530_rename_histories_to_rails_admin_histories.rb +9 -0
  323. data/spec/dummy_app/db/migrate/20110224184303_create_field_tests.rb +22 -0
  324. data/spec/dummy_app/db/migrate/20110328193014_create_cms_basic_pages.rb +14 -0
  325. data/spec/dummy_app/db/migrate/20110329183136_remove_league_id_from_teams.rb +9 -0
  326. data/spec/dummy_app/db/migrate/20110607152842_add_format_to_field_test.rb +9 -0
  327. data/spec/dummy_app/db/migrate/20110714095433_create_balls.rb +12 -0
  328. data/spec/dummy_app/db/migrate/20110831090841_add_protected_field_and_restricted_field_to_field_tests.rb +6 -0
  329. data/spec/dummy_app/db/migrate/20110901131551_change_division_primary_key.rb +19 -0
  330. data/spec/dummy_app/db/migrate/20110901142530_rename_league_id_foreign_key_on_divisions.rb +5 -0
  331. data/spec/dummy_app/db/migrate/20110901150912_set_primary_key_not_null_for_divisions.rb +21 -0
  332. data/spec/dummy_app/db/migrate/20110901154834_change_length_for_rails_admin_histories.rb +9 -0
  333. data/spec/dummy_app/db/migrate/20111103174459_create_unscoped_pages.rb +9 -0
  334. data/spec/dummy_app/db/migrate/20111108143642_add_dragonfly_and_carrierwave_to_field_tests.rb +7 -0
  335. data/spec/dummy_app/db/migrate/20111115041025_add_type_to_balls.rb +5 -0
  336. data/spec/dummy_app/db/migrate/20111123092549_create_nested_field_tests.rb +10 -0
  337. data/spec/dummy_app/db/migrate/20111130075338_add_dragonfly_asset_name_to_field_tests.rb +5 -0
  338. data/spec/dummy_app/db/migrate/20111215083258_create_foo_bars.rb +8 -0
  339. data/spec/dummy_app/db/migrate/20120117151733_add_custom_field_to_teams.rb +5 -0
  340. data/spec/dummy_app/db/migrate/20120118122004_add_categories.rb +7 -0
  341. data/spec/dummy_app/db/migrate/20120319041705_drop_rel_tests.rb +15 -0
  342. data/spec/dummy_app/db/migrate/20120720075608_create_another_field_tests.rb +8 -0
  343. data/spec/dummy_app/db/migrate/20120928075608_create_images.rb +8 -0
  344. data/spec/dummy_app/db/seeds.rb +29 -0
  345. data/spec/dummy_app/doc/README_FOR_APP +2 -0
  346. data/spec/dummy_app/public/404.html +26 -0
  347. data/spec/dummy_app/public/422.html +26 -0
  348. data/spec/dummy_app/public/500.html +25 -0
  349. data/spec/dummy_app/public/favicon.ico +0 -0
  350. data/spec/dummy_app/public/robots.txt +5 -0
  351. data/spec/dummy_app/public/system/dragonfly/development/2011/11/24/10_36_27_888_Pensive_Parakeet.jpg +0 -0
  352. data/spec/dummy_app/public/system/dragonfly/development/2011/11/24/10_36_27_888_Pensive_Parakeet.jpg.meta +1 -0
  353. data/spec/dummy_app/public/system/dragonfly/development/2011/11/30/08_54_39_906_Costa_Rican_Frog.jpg +0 -0
  354. data/spec/dummy_app/public/system/dragonfly/development/2011/11/30/08_54_39_906_Costa_Rican_Frog.jpg.meta +1 -0
  355. data/spec/dummy_app/public/system/paperclip_assets/1/original/Boston City Flow.jpg +0 -0
  356. data/spec/dummy_app/public/system/paperclip_assets/1/thumb/Boston City Flow.jpg +0 -0
  357. data/spec/dummy_app/public/system/paperclip_assets/3/original/Costa Rican Frog.jpg +0 -0
  358. data/spec/dummy_app/public/system/paperclip_assets/3/thumb/Costa Rican Frog.jpg +0 -0
  359. data/spec/dummy_app/public/system/paperclip_assets/6/original/liste-electorale.pdf +0 -0
  360. data/spec/dummy_app/public/system/paperclip_assets/6/thumb/liste-electorale.pdf +148 -0
  361. data/spec/dummy_app/public/uploads/field_test/carrierwave_asset/3/Boston_City_Flow.jpg +0 -0
  362. data/spec/dummy_app/public/uploads/field_test/carrierwave_asset/3/thumb_Boston_City_Flow.jpg +0 -0
  363. data/spec/dummy_app/public/uploads/field_test/carrierwave_asset/4/Costa_Rican_Frog.jpg +0 -0
  364. data/spec/dummy_app/public/uploads/field_test/carrierwave_asset/4/thumb_Costa_Rican_Frog.jpg +0 -0
  365. data/spec/dummy_app/public/uploads/field_test/carrierwave_asset/6/Pensive_Parakeet.jpg +0 -0
  366. data/spec/dummy_app/public/uploads/field_test/carrierwave_asset/6/thumb_Pensive_Parakeet.jpg +0 -0
  367. data/spec/dummy_app/script/rails +6 -0
  368. data/spec/factories.rb +75 -0
  369. data/spec/helpers/rails_admin/application_helper_spec.rb +353 -0
  370. data/spec/helpers/rails_admin/form_builder_spec.rb +17 -0
  371. data/spec/integration/authorization/cancan_spec.rb +366 -0
  372. data/spec/integration/basic/bulk_action/rails_admin_basic_bulk_action_spec.rb +25 -0
  373. data/spec/integration/basic/bulk_destroy/rails_admin_basic_bulk_destroy_spec.rb +53 -0
  374. data/spec/integration/basic/create/rails_admin_basic_create_spec.rb +140 -0
  375. data/spec/integration/basic/create/rails_admin_namespaced_model_create_spec.rb +16 -0
  376. data/spec/integration/basic/delete/rails_admin_basic_delete_spec.rb +64 -0
  377. data/spec/integration/basic/destroy/rails_admin_basic_destroy_spec.rb +84 -0
  378. data/spec/integration/basic/edit/rails_admin_basic_edit_spec.rb +109 -0
  379. data/spec/integration/basic/export/rails_admin_basic_export_spec.rb +106 -0
  380. data/spec/integration/basic/list/rails_admin_basic_list_spec.rb +444 -0
  381. data/spec/integration/basic/new/rails_admin_basic_new_spec.rb +73 -0
  382. data/spec/integration/basic/new/rails_admin_namespaced_model_new_spec.rb +31 -0
  383. data/spec/integration/basic/show/rails_admin_basic_show_spec.rb +82 -0
  384. data/spec/integration/basic/update/rails_admin_basic_update_spec.rb +229 -0
  385. data/spec/integration/config/edit/rails_admin_config_edit_spec.rb +1026 -0
  386. data/spec/integration/config/list/rails_admin_config_list_spec.rb +441 -0
  387. data/spec/integration/config/show/rails_admin_config_show_spec.rb +331 -0
  388. data/spec/integration/history/rails_admin_history_spec.rb +88 -0
  389. data/spec/integration/rails_admin_spec.rb +150 -0
  390. data/spec/integration/relation_spec.rb +35 -0
  391. data/spec/orm/active_record.rb +42 -0
  392. data/spec/orm/mongoid.rb +21 -0
  393. data/spec/rails_admin/abstract_model_spec.rb +75 -0
  394. data/spec/rails_admin/active_record_extension_spec.rb +16 -0
  395. data/spec/rails_admin/adapters/active_record/abstract_object_spec.rb +132 -0
  396. data/spec/rails_admin/adapters/active_record_spec.rb +409 -0
  397. data/spec/rails_admin/adapters/mongoid/abstract_object_spec.rb +31 -0
  398. data/spec/rails_admin/adapters/mongoid_spec.rb +776 -0
  399. data/spec/rails_admin/config/actions/base_spec.rb +32 -0
  400. data/spec/rails_admin/config/actions_spec.rb +180 -0
  401. data/spec/rails_admin/config/fields/base_spec.rb +421 -0
  402. data/spec/rails_admin/config/fields/date_spec.rb +74 -0
  403. data/spec/rails_admin/config/fields/datetime_spec.rb +55 -0
  404. data/spec/rails_admin/config/fields/file_upload_spec.rb +21 -0
  405. data/spec/rails_admin/config/fields/time_spec.rb +39 -0
  406. data/spec/rails_admin/config/fields/timestamp_spec.rb +20 -0
  407. data/spec/rails_admin/config/fields/types/datetime_spec.rb +18 -0
  408. data/spec/rails_admin/config/fields_spec.rb +15 -0
  409. data/spec/rails_admin/config/has_fields_spec.rb +30 -0
  410. data/spec/rails_admin/config/lazy_model_spec.rb +29 -0
  411. data/spec/rails_admin/config/model_spec.rb +75 -0
  412. data/spec/rails_admin/config/sections_spec.rb +123 -0
  413. data/spec/rails_admin/config_spec.rb +277 -0
  414. data/spec/rails_admin/support/csv_converter_spec.rb +16 -0
  415. data/spec/spec_helper.rb +84 -0
  416. metadata +868 -0
@@ -0,0 +1,409 @@
1
+ require 'spec_helper'
2
+ require 'timecop'
3
+
4
+ describe "RailsAdmin::Adapters::ActiveRecord", :active_record => true do
5
+ before do
6
+ @like = ::ActiveRecord::Base.configurations[Rails.env]['adapter'] == "postgresql" ? 'ILIKE' : 'LIKE'
7
+ end
8
+
9
+ describe "#associations" do
10
+ before :all do
11
+ RailsAdmin::AbstractModel.reset_polymorphic_parents
12
+
13
+ class ARBlog < ActiveRecord::Base
14
+ has_many :a_r_posts
15
+ has_many :a_r_comments, :as => :commentable
16
+ belongs_to :librarian, :polymorphic => true
17
+ end
18
+
19
+ class ARPost < ActiveRecord::Base
20
+ belongs_to :a_r_blog
21
+ has_and_belongs_to_many :a_r_categories
22
+ has_many :a_r_comments, :as => :commentable
23
+ end
24
+
25
+ class ARCategory < ActiveRecord::Base
26
+ has_and_belongs_to_many :a_r_posts
27
+ belongs_to :librarian, :polymorphic => true
28
+ end
29
+
30
+ class ARUser < ActiveRecord::Base
31
+ has_one :a_r_profile
32
+ has_many :a_r_categories, :as => :librarian
33
+ end
34
+
35
+ class ARProfile < ActiveRecord::Base
36
+ belongs_to :a_r_user
37
+ has_many :a_r_blogs, :as => :librarian
38
+ end
39
+
40
+ class ARComment < ActiveRecord::Base
41
+ belongs_to :commentable, :polymorphic => true
42
+ end
43
+
44
+ @blog = RailsAdmin::AbstractModel.new(ARBlog)
45
+ @post = RailsAdmin::AbstractModel.new(ARPost)
46
+ @category = RailsAdmin::AbstractModel.new(ARCategory)
47
+ @user = RailsAdmin::AbstractModel.new(ARUser)
48
+ @profile = RailsAdmin::AbstractModel.new(ARProfile)
49
+ @comment = RailsAdmin::AbstractModel.new(ARComment)
50
+ end
51
+
52
+ after :all do
53
+ RailsAdmin::AbstractModel.reset_polymorphic_parents
54
+ end
55
+
56
+ it "lists associations" do
57
+ expect(@post.associations.map{|a|a[:name].to_s}).to match_array ['a_r_blog', 'a_r_categories', 'a_r_comments']
58
+ end
59
+
60
+ it "list associations types in supported [:belongs_to, :has_and_belongs_to_many, :has_many, :has_one]" do
61
+ expect((@post.associations + @blog.associations + @user.associations).map{|a|a[:type]}.uniq.map(&:to_s)).to match_array ['belongs_to', 'has_and_belongs_to_many', 'has_many', 'has_one']
62
+ end
63
+
64
+ it "has correct parameter of belongs_to association" do
65
+ param = @post.associations.select{|a| a[:name] == :a_r_blog}.first
66
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
67
+ :name => :a_r_blog,
68
+ :pretty_name => "A r blog",
69
+ :type => :belongs_to,
70
+ :foreign_key => :a_r_blog_id,
71
+ :foreign_type => nil,
72
+ :as => nil,
73
+ :polymorphic => false,
74
+ :inverse_of => nil,
75
+ :read_only => nil,
76
+ :nested_form => nil,
77
+ })
78
+ expect(param[:primary_key_proc].call).to eq('id')
79
+ expect(param[:model_proc].call).to eq(ARBlog)
80
+ end
81
+
82
+ it "has correct parameter of has_many association" do
83
+ param = @blog.associations.select{|a| a[:name] == :a_r_posts}.first
84
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
85
+ :name => :a_r_posts,
86
+ :pretty_name => "A r posts",
87
+ :type => :has_many,
88
+ :foreign_key => :ar_blog_id,
89
+ :foreign_type => nil,
90
+ :as => nil,
91
+ :polymorphic => false,
92
+ :inverse_of => nil,
93
+ :read_only => nil,
94
+ :nested_form => nil,
95
+ })
96
+ expect(param[:primary_key_proc].call).to eq('id')
97
+ expect(param[:model_proc].call).to eq(ARPost)
98
+ end
99
+
100
+ it "has correct parameter of has_and_belongs_to_many association" do
101
+ param = @post.associations.select{|a| a[:name] == :a_r_categories}.first
102
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
103
+ :name => :a_r_categories,
104
+ :pretty_name => "A r categories",
105
+ :type => :has_and_belongs_to_many,
106
+ :foreign_key => :ar_post_id,
107
+ :foreign_type => nil,
108
+ :as => nil,
109
+ :polymorphic => false,
110
+ :inverse_of => nil,
111
+ :read_only => nil,
112
+ :nested_form => nil
113
+ })
114
+ expect(param[:primary_key_proc].call).to eq('id')
115
+ expect(param[:model_proc].call).to eq(ARCategory)
116
+ end
117
+
118
+ it "has correct parameter of polymorphic belongs_to association" do
119
+ RailsAdmin::Config.stub!(:models_pool).and_return(["ARBlog", "ARPost", "ARCategory", "ARUser", "ARProfile", "ARComment"])
120
+ param = @comment.associations.select{|a| a[:name] == :commentable}.first
121
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
122
+ :name => :commentable,
123
+ :pretty_name => "Commentable",
124
+ :type => :belongs_to,
125
+ :foreign_key => :commentable_id,
126
+ :foreign_type => :commentable_type,
127
+ :as => nil,
128
+ :polymorphic => true,
129
+ :inverse_of => nil,
130
+ :read_only => nil,
131
+ :nested_form => nil
132
+ })
133
+ # Should not be called for polymorphic relations.
134
+ # TODO: Handle this case
135
+ # expect(param[:primary_key_proc].call).to eq('id')
136
+ expect(param[:model_proc].call).to eq([ARBlog, ARPost])
137
+ end
138
+
139
+ it "has correct parameter of polymorphic inverse has_many association" do
140
+ param = @blog.associations.select{|a| a[:name] == :a_r_comments}.first
141
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
142
+ :name => :a_r_comments,
143
+ :pretty_name => "A r comments",
144
+ :type => :has_many,
145
+ :foreign_key => :commentable_id,
146
+ :foreign_type => nil,
147
+ :as => :commentable,
148
+ :polymorphic => false,
149
+ :inverse_of => nil,
150
+ :read_only => nil,
151
+ :nested_form => nil
152
+ })
153
+ expect(param[:primary_key_proc].call).to eq('id')
154
+ expect(param[:model_proc].call).to eq(ARComment)
155
+ end
156
+
157
+
158
+ it 'has correct opposite model lookup for polymorphic associations' do
159
+ RailsAdmin::Config.stub!(:models_pool).and_return(["ARBlog", "ARPost", "ARCategory", "ARUser", "ARProfile", "ARComment"])
160
+ expect(@category.associations.find{|a| a[:name] == :librarian}[:model_proc].call).to eq [ARUser]
161
+ expect(@blog.associations.find{|a| a[:name] == :librarian}[:model_proc].call).to eq [ARProfile]
162
+ end
163
+ end
164
+
165
+ describe "#properties" do
166
+ it "returns parameters of string-type field" do
167
+ expect(RailsAdmin::AbstractModel.new('Player').properties.select{|f| f[:name] == :name}).to eq([{:name => :name, :pretty_name => "Name", :type => :string, :length => 100, :nullable? => false, :serial? => false}])
168
+ end
169
+
170
+ it "maps serialized attribute to :serialized field type" do
171
+ expect(RailsAdmin::AbstractModel.new('User').properties.find{|f| f[:name] == :roles}).to eq({:name => :roles, :pretty_name => "Roles", :length => 255, :nullable? => true, :serial? => false, :type => :serialized})
172
+ end
173
+ end
174
+
175
+ describe "data access method" do
176
+ before do
177
+ @players = FactoryGirl.create_list(:player, 3)
178
+ @abstract_model = RailsAdmin::AbstractModel.new('Player')
179
+ end
180
+
181
+ it "#new returns instance of AbstractObject" do
182
+ expect(@abstract_model.new.object).to be_instance_of(Player)
183
+ end
184
+
185
+ it "#get returns instance of AbstractObject" do
186
+ expect(@abstract_model.get(@players.first.id).object).to eq(@players.first)
187
+ end
188
+
189
+ it "#get returns nil when id does not exist" do
190
+ expect(@abstract_model.get('abc')).to be_nil
191
+ end
192
+
193
+ it "#first returns a player" do
194
+ expect(@players).to include @abstract_model.first
195
+ end
196
+
197
+ it "#count returns count of items" do
198
+ expect(@abstract_model.count).to eq(@players.count)
199
+ end
200
+
201
+ it "#destroy destroys multiple items" do
202
+ @abstract_model.destroy(@players[0..1])
203
+ expect(Player.all).to eq(@players[2..2])
204
+ end
205
+
206
+ it "#where returns filtered results" do
207
+ expect(@abstract_model.where(:name => @players.first.name)).to eq([@players.first])
208
+ end
209
+
210
+ describe "#all" do
211
+ it "works without options" do
212
+ expect(@abstract_model.all).to match_array @players
213
+ end
214
+
215
+ it "supports eager loading" do
216
+ expect(@abstract_model.all(:include => :team).includes_values).to eq([:team])
217
+ end
218
+
219
+ it "supports limiting" do
220
+ expect(@abstract_model.all(:limit => 2)).to have(2).items
221
+ end
222
+
223
+ it "supports retrieval by bulk_ids" do
224
+ expect(@abstract_model.all(:bulk_ids => @players[0..1].map(&:id))).to match_array @players[0..1]
225
+ end
226
+
227
+ it "supports pagination" do
228
+ expect(@abstract_model.all(:sort => "id", :page => 2, :per => 1)).to eq(@players[1..1])
229
+ expect(@abstract_model.all(:sort => "id", :page => 1, :per => 2)).to eq(@players[1..2].reverse)
230
+ end
231
+
232
+ it "supports ordering" do
233
+ expect(@abstract_model.all(:sort => "id", :sort_reverse => true)).to eq(@players.sort)
234
+ end
235
+
236
+ it "supports querying" do
237
+ expect(@abstract_model.all(:query => @players[1].name)).to eq(@players[1..1])
238
+ end
239
+
240
+ it "supports filtering" do
241
+ expect(@abstract_model.all(:filters => {"name" => {"0000" => {:o => "is", :v => @players[1].name}}})).to eq(@players[1..1])
242
+ end
243
+ end
244
+ end
245
+
246
+ describe "#query_conditions" do
247
+ before do
248
+ @abstract_model = RailsAdmin::AbstractModel.new('Team')
249
+ @teams = [{}, {:name => 'somewhere foos'}, {:manager => 'foo junior'}].
250
+ map{|h| FactoryGirl.create :team, h}
251
+ end
252
+
253
+ it "makes conrrect query" do
254
+ expect(@abstract_model.all(:query => "foo")).to match_array @teams[1..2]
255
+ end
256
+ end
257
+
258
+ describe "#filter_conditions" do
259
+ before do
260
+ @abstract_model = RailsAdmin::AbstractModel.new('Team')
261
+ @division = FactoryGirl.create :division, :name => 'bar division'
262
+ @teams = [{}, {:division => @division}, {:name => 'somewhere foos', :division => @division}, {:name => 'nowhere foos'}].
263
+ map{|h| FactoryGirl.create :team, h}
264
+ end
265
+
266
+ it "makes conrrect query" do
267
+ expect(@abstract_model.all(
268
+ :filters => {"name" => {"0000" => {:o => "like", :v => "foo"}},
269
+ "division" => {"0001" => {:o => "like", :v => "bar"}}},
270
+ :include => :division
271
+ )).to eq([@teams[2]])
272
+ end
273
+ end
274
+
275
+ describe "#build_statement" do
276
+ before do
277
+ @abstract_model = RailsAdmin::AbstractModel.new('FieldTest')
278
+ end
279
+
280
+ it "ignores '_discard' operator or value" do
281
+ [["_discard", ""], ["", "_discard"]].each do |value, operator|
282
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to be_nil
283
+ end
284
+ end
285
+
286
+ it "supports '_blank' operator" do
287
+ [["_blank", ""], ["", "_blank"]].each do |value, operator|
288
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name IS NULL OR name = '')"])
289
+ end
290
+ end
291
+
292
+ it "supports '_present' operator" do
293
+ [["_present", ""], ["", "_present"]].each do |value, operator|
294
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name IS NOT NULL AND name != '')"])
295
+ end
296
+ end
297
+
298
+ it "supports '_null' operator" do
299
+ [["_null", ""], ["", "_null"]].each do |value, operator|
300
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name IS NULL)"])
301
+ end
302
+ end
303
+
304
+ it "supports '_not_null' operator" do
305
+ [["_not_null", ""], ["", "_not_null"]].each do |value, operator|
306
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name IS NOT NULL)"])
307
+ end
308
+ end
309
+
310
+ it "supports '_empty' operator" do
311
+ [["_empty", ""], ["", "_empty"]].each do |value, operator|
312
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name = '')"])
313
+ end
314
+ end
315
+
316
+ it "supports '_not_empty' operator" do
317
+ [["_not_empty", ""], ["", "_not_empty"]].each do |value, operator|
318
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name != '')"])
319
+ end
320
+ end
321
+
322
+ it "supports boolean type query" do
323
+ ['false', 'f', '0'].each do |value|
324
+ expect(@abstract_model.send(:build_statement, :field, :boolean, value, nil)).to eq(["(field IS NULL OR field = ?)", false])
325
+ end
326
+ ['true', 't', '1'].each do |value|
327
+ expect(@abstract_model.send(:build_statement, :field, :boolean, value, nil)).to eq(["(field = ?)", true])
328
+ end
329
+ expect(@abstract_model.send(:build_statement, :field, :boolean, 'word', nil)).to be_nil
330
+ end
331
+
332
+ it "supports integer type query" do
333
+ expect(@abstract_model.send(:build_statement, :field, :integer, "1" , nil)).to eq(["(field = ?)", 1])
334
+ expect(@abstract_model.send(:build_statement, :field, :integer, 'word', nil)).to be_nil
335
+ expect(@abstract_model.send(:build_statement, :field, :integer, "1" , 'default')).to eq(["(field = ?)", 1])
336
+ expect(@abstract_model.send(:build_statement, :field, :integer, 'word', 'default')).to be_nil
337
+ expect(@abstract_model.send(:build_statement, :field, :integer, "1" , 'between')).to eq(["(field = ?)", 1])
338
+ expect(@abstract_model.send(:build_statement, :field, :integer, 'word', 'between')).to be_nil
339
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['6', '' , '' ], 'default')).to eq(["(field = ?)", 6])
340
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['7', '10', '' ], 'default')).to eq(["(field = ?)", 7])
341
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['8', '' , '20'], 'default')).to eq(["(field = ?)", 8])
342
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['9', '10', '20'], 'default')).to eq(["(field = ?)", 9])
343
+ end
344
+
345
+ it "supports integer type range query" do
346
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', '', ''], 'between')).to be_nil
347
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['2', '', ''], 'between')).to be_nil
348
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', '3', ''], 'between')).to eq(["(field >= ?)", 3])
349
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', '', '5'], 'between')).to eq(["(field <= ?)", 5])
350
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['' , '10', '20'], 'between')).to eq(["(field BETWEEN ? AND ?)", 10, 20])
351
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['15', '10', '20'], 'between')).to eq(["(field BETWEEN ? AND ?)", 10, 20])
352
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', 'word1', '' ], 'between')).to be_nil
353
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', '' , 'word2'], 'between')).to be_nil
354
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', 'word3', 'word4'], 'between')).to be_nil
355
+ end
356
+
357
+ it "supports decimal type query" do
358
+ expect(@abstract_model.send(:build_statement, :field, :decimal, "1.1", nil)).to eq(["(field = ?)", 1.1])
359
+ expect(@abstract_model.send(:build_statement, :field, :decimal, 'word', nil)).to be_nil
360
+ end
361
+
362
+ it "supports string type query" do
363
+ expect(@abstract_model.send(:build_statement, :field, :string, "", nil)).to be_nil
364
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "was")).to be_nil
365
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "default")).to eq(["(LOWER(field) #{@like} ?)", "%foo%"])
366
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "like")).to eq(["(LOWER(field) #{@like} ?)", "%foo%"])
367
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "starts_with")).to eq(["(LOWER(field) #{@like} ?)", "foo%"])
368
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "ends_with")).to eq(["(LOWER(field) #{@like} ?)", "%foo"])
369
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "is")).to eq(["(LOWER(field) #{@like} ?)", "foo"])
370
+ end
371
+
372
+ it "performs case-insensitive searches" do
373
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "default")).to eq(["(LOWER(field) #{@like} ?)", "%foo%"])
374
+ expect(@abstract_model.send(:build_statement, :field, :string, "FOO", "default")).to eq(["(LOWER(field) #{@like} ?)", "%foo%"])
375
+ end
376
+
377
+ it "supports date type query" do
378
+ expect(@abstract_model.send(:filter_conditions, { "date_field" => { "1" => { :v => ["", "01/02/2012", "01/03/2012"], :o => 'between' } } })).to eq(["((field_tests.date_field BETWEEN ? AND ?))", Date.new(2012,1,2), Date.new(2012,1,3)])
379
+ expect(@abstract_model.send(:filter_conditions, { "date_field" => { "1" => { :v => ["", "01/03/2012", ""], :o => 'between' } } } )).to eq(["((field_tests.date_field >= ?))", Date.new(2012,1,3)])
380
+ expect(@abstract_model.send(:filter_conditions, { "date_field" => { "1" => { :v => ["", "", "01/02/2012"], :o => 'between' } } } )).to eq(["((field_tests.date_field <= ?))", Date.new(2012,1,2)])
381
+ expect(@abstract_model.send(:filter_conditions, { "date_field" => { "1" => { :v => ["01/02/2012"], :o => 'default' } } } )).to eq(["((field_tests.date_field BETWEEN ? AND ?))", Date.new(2012,1,2), Date.new(2012,1,2)])
382
+ end
383
+
384
+ it "supports datetime type query" do
385
+ expect(@abstract_model.send(:filter_conditions, { "datetime_field" => { "1" => { :v => ["", "01/02/2012", "01/03/2012"], :o => 'between' } } } )).to eq(["((field_tests.datetime_field BETWEEN ? AND ?))", Time.local(2012,1,2), Time.local(2012,1,3).end_of_day])
386
+ expect(@abstract_model.send(:filter_conditions, { "datetime_field" => { "1" => { :v => ["", "01/03/2012", ""], :o => 'between' } } } )).to eq(["((field_tests.datetime_field >= ?))", Time.local(2012,1,3)])
387
+ expect(@abstract_model.send(:filter_conditions, { "datetime_field" => { "1" => { :v => ["", "", "01/02/2012"], :o => 'between' } } } )).to eq(["((field_tests.datetime_field <= ?))", Time.local(2012,1,2).end_of_day])
388
+ expect(@abstract_model.send(:filter_conditions, { "datetime_field" => { "1" => { :v => ["01/02/2012"], :o => 'default' } } } )).to eq(["((field_tests.datetime_field BETWEEN ? AND ?))", Time.local(2012,1,2), Time.local(2012,1,2).end_of_day])
389
+ end
390
+
391
+ it "supports enum type query" do
392
+ expect(@abstract_model.send(:build_statement, :field, :enum, "1", nil)).to eq(["(field IN (?))", ["1"]])
393
+ end
394
+ end
395
+
396
+ describe "model attribute method" do
397
+ before do
398
+ @abstract_model = RailsAdmin::AbstractModel.new('Player')
399
+ end
400
+
401
+ it "#scoped returns relation object" do
402
+ expect(@abstract_model.scoped).to be_instance_of(ActiveRecord::Relation)
403
+ end
404
+
405
+ it "#table_name works" do
406
+ expect(@abstract_model.table_name).to eq('players')
407
+ end
408
+ end
409
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'rails_admin/adapters/mongoid/abstract_object'
3
+
4
+ describe "RailsAdmin::Adapters::Mongoid::AbstractObject", :mongoid => true do
5
+ before(:each) do
6
+ @players = FactoryGirl.create_list :player, 3
7
+ @team = RailsAdmin::Adapters::Mongoid::AbstractObject.new FactoryGirl.create :team
8
+ end
9
+
10
+ describe "references_many association" do
11
+ it "supports retrieval of ids through foo_ids" do
12
+ expect(@team.player_ids).to eq([])
13
+ player = FactoryGirl.create :player, :team => @team
14
+ expect(@team.player_ids).to eq([player.id])
15
+ end
16
+
17
+ it "supports assignment of items through foo_ids=" do
18
+ expect(@team.players).to eq([])
19
+ @team.player_ids = @players.map(&:id)
20
+ @team.reload
21
+ expect(@team.players.map(&:id)).to match_array @players.map(&:id)
22
+ end
23
+
24
+ it "skips invalid id on assignment through foo_ids=" do
25
+ @team.player_ids = @players.map{|item| item.id.to_s }.unshift('4f431021dcf2310db7000006')
26
+ @team.reload
27
+ @players.each &:reload
28
+ expect(@team.players.map(&:id)).to match_array @players.map(&:id)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,776 @@
1
+ require 'spec_helper'
2
+ require 'timecop'
3
+
4
+ describe "RailsAdmin::Adapters::Mongoid", :mongoid => true do
5
+ describe "#associations" do
6
+ before :all do
7
+ RailsAdmin::AbstractModel.reset_polymorphic_parents
8
+
9
+ class MongoBlog
10
+ include Mongoid::Document
11
+ has_many :mongo_posts
12
+ has_many :mongo_comments, :as => :commentable
13
+ belongs_to :librarian, :polymorphic => true
14
+ field :mongo_blog_id
15
+ end
16
+
17
+ class MongoPost
18
+ include Mongoid::Document
19
+ belongs_to :mongo_blog
20
+ has_and_belongs_to_many :mongo_categories
21
+ has_many :mongo_comments, :as => :commentable
22
+ embeds_one :mongo_note
23
+ accepts_nested_attributes_for :mongo_note
24
+ end
25
+
26
+ class MongoCategory
27
+ include Mongoid::Document
28
+ has_and_belongs_to_many :mongo_posts
29
+ belongs_to :librarian, :polymorphic => true
30
+ end
31
+
32
+ class MongoUser
33
+ include Mongoid::Document
34
+ has_one :mongo_profile
35
+ has_many :mongo_categories, :as => :librarian
36
+
37
+ embeds_many :mongo_notes
38
+ accepts_nested_attributes_for :mongo_notes
39
+ field :name, :type => String
40
+ field :message, :type => String
41
+ field :short_text, :type => String
42
+
43
+ validates :short_text, :length => {:maximum => 255}
44
+ end
45
+
46
+ class MongoProfile
47
+ include Mongoid::Document
48
+ belongs_to :mongo_user
49
+ has_many :mongo_blogs, :as => :librarian
50
+ end
51
+
52
+ class MongoComment
53
+ include Mongoid::Document
54
+ belongs_to :commentable, :polymorphic => true
55
+ end
56
+
57
+ class MongoNote
58
+ include Mongoid::Document
59
+ embedded_in :mongo_post
60
+ embedded_in :mongo_user
61
+ end
62
+
63
+ @blog = RailsAdmin::AbstractModel.new MongoBlog
64
+ @post = RailsAdmin::AbstractModel.new MongoPost
65
+ @category = RailsAdmin::AbstractModel.new MongoCategory
66
+ @user = RailsAdmin::AbstractModel.new MongoUser
67
+ @profile = RailsAdmin::AbstractModel.new MongoProfile
68
+ @comment = RailsAdmin::AbstractModel.new MongoComment
69
+ end
70
+
71
+ after :all do
72
+ RailsAdmin::AbstractModel.reset_polymorphic_parents
73
+ end
74
+
75
+ it "lists associations" do
76
+ expect(@post.associations.map{|a| a[:name]}).to match_array [:mongo_blog, :mongo_categories, :mongo_comments, :mongo_note]
77
+ end
78
+
79
+ it "reads correct and know types in [:belongs_to, :has_and_belongs_to_many, :has_many, :has_one]" do
80
+ expect((@post.associations + @blog.associations + @user.associations).map{|a|a[:type].to_s}.uniq).to match_array ['belongs_to', 'has_and_belongs_to_many', 'has_many', 'has_one']
81
+ end
82
+
83
+ it "has correct parameter of belongs_to association" do
84
+ param = @post.associations.find{|a| a[:name] == :mongo_blog}
85
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
86
+ :name => :mongo_blog,
87
+ :pretty_name => "Mongo blog",
88
+ :type => :belongs_to,
89
+ :foreign_key => :mongo_blog_id,
90
+ :foreign_type => nil,
91
+ :foreign_inverse_of => nil,
92
+ :as => nil,
93
+ :polymorphic => false,
94
+ :inverse_of => nil,
95
+ :read_only => nil,
96
+ :nested_form => nil
97
+ })
98
+ expect(param[:primary_key_proc].call).to eq(:_id)
99
+ expect(param[:model_proc].call).to eq(MongoBlog)
100
+ end
101
+
102
+ it "has correct parameter of has_many association" do
103
+ param = @blog.associations.find{|a| a[:name] == :mongo_posts}
104
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
105
+ :name => :mongo_posts,
106
+ :pretty_name => "Mongo posts",
107
+ :type => :has_many,
108
+ :foreign_key => :mongo_blog_id,
109
+ :foreign_type => nil,
110
+ :foreign_inverse_of => nil,
111
+ :as => nil,
112
+ :polymorphic => false,
113
+ :inverse_of => nil,
114
+ :read_only => nil,
115
+ :nested_form => nil
116
+ })
117
+ expect(param[:primary_key_proc].call).to eq(:_id)
118
+ expect(param[:model_proc].call).to eq(MongoPost)
119
+ expect(@post.properties.find{|f| f[:name] == :mongo_blog_id}[:type]).to eq(:bson_object_id)
120
+ end
121
+
122
+ it "does not confuse foreign_key column which belongs to associated model" do
123
+ expect(@blog.properties.find{|f| f[:name] == :mongo_blog_id}[:type]).to eq(:string)
124
+ end
125
+
126
+ it "has correct parameter of has_and_belongs_to_many association" do
127
+ param = @post.associations.find{|a| a[:name] == :mongo_categories}
128
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
129
+ :name => :mongo_categories,
130
+ :pretty_name => "Mongo categories",
131
+ :type => :has_and_belongs_to_many,
132
+ :foreign_key => :mongo_category_ids,
133
+ :foreign_type => nil,
134
+ :foreign_inverse_of => nil,
135
+ :as => nil,
136
+ :polymorphic => false,
137
+ :inverse_of => nil,
138
+ :read_only => nil,
139
+ :nested_form => nil
140
+ })
141
+ expect(param[:primary_key_proc].call).to eq(:_id)
142
+ expect(param[:model_proc].call).to eq(MongoCategory)
143
+ end
144
+
145
+ it "has correct parameter of polymorphic belongs_to association" do
146
+ RailsAdmin::Config.stub!(:models_pool).and_return(["MongoBlog", "MongoPost", "MongoCategory", "MongoUser", "MongoProfile", "MongoComment"])
147
+ param = @comment.associations.find{|a| a[:name] == :commentable}
148
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
149
+ :name => :commentable,
150
+ :pretty_name => "Commentable",
151
+ :type => :belongs_to,
152
+ :foreign_key => :commentable_id,
153
+ :foreign_type => :commentable_type,
154
+ :foreign_inverse_of => (Mongoid::VERSION >= '3.0.0' ? :commentable_field : nil),
155
+ :as => nil,
156
+ :polymorphic => true,
157
+ :inverse_of => nil,
158
+ :read_only => nil,
159
+ :nested_form => nil
160
+ })
161
+ expect(param[:primary_key_proc].call).to eq(:_id)
162
+ expect(param[:model_proc].call).to eq([MongoBlog, MongoPost])
163
+ end
164
+
165
+ it "has correct parameter of polymorphic inverse has_many association" do
166
+ RailsAdmin::Config.stub!(:models_pool).and_return(["MongoBlog", "MongoPost", "MongoCategory", "MongoUser", "MongoProfile", "MongoComment"])
167
+ param = @blog.associations.find{|a| a[:name] == :mongo_comments}
168
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
169
+ :name => :mongo_comments,
170
+ :pretty_name => "Mongo comments",
171
+ :type => :has_many,
172
+ :foreign_key => :commentable_id,
173
+ :foreign_type => nil,
174
+ :foreign_inverse_of => nil,
175
+ :as => :commentable,
176
+ :polymorphic => false,
177
+ :inverse_of => nil,
178
+ :read_only => nil,
179
+ :nested_form => nil
180
+ })
181
+ expect(param[:primary_key_proc].call).to eq(:_id)
182
+ expect(param[:model_proc].call).to eq(MongoComment)
183
+ end
184
+
185
+ it 'has correct opposite model lookup for polymorphic associations' do
186
+ RailsAdmin::Config.stub!(:models_pool).and_return(["MongoBlog", "MongoPost", "MongoCategory", "MongoUser", "MongoProfile", "MongoComment"])
187
+ expect(@category.associations.find{|a| a[:name] == :librarian}[:model_proc].call).to eq [MongoUser]
188
+ expect(@blog.associations.find{|a| a[:name] == :librarian}[:model_proc].call).to eq [MongoProfile]
189
+ end
190
+
191
+ it "has correct parameter of embeds_one association" do
192
+ param = @post.associations.find{|a| a[:name] == :mongo_note}
193
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
194
+ :name => :mongo_note,
195
+ :pretty_name => "Mongo note",
196
+ :type => :has_one,
197
+ :foreign_key => nil,
198
+ :foreign_type => nil,
199
+ :foreign_inverse_of => nil,
200
+ :as => nil,
201
+ :polymorphic => false,
202
+ :inverse_of => nil,
203
+ :read_only => nil,
204
+ :nested_form => {:allow_destroy => false, :update_only => false}
205
+ })
206
+ expect(param[:primary_key_proc].call).to eq(:_id)
207
+ expect(param[:model_proc].call).to eq(MongoNote)
208
+ end
209
+
210
+ it "has correct parameter of embeds_many association" do
211
+ param = @user.associations.find{|a| a[:name] == :mongo_notes}
212
+ expect(param.reject{|k, v| [:primary_key_proc, :model_proc].include? k }).to eq({
213
+ :name => :mongo_notes,
214
+ :pretty_name => "Mongo notes",
215
+ :type => :has_many,
216
+ :foreign_key => nil,
217
+ :foreign_type => nil,
218
+ :foreign_inverse_of => nil,
219
+ :as => nil,
220
+ :polymorphic => false,
221
+ :inverse_of => nil,
222
+ :read_only => nil,
223
+ :nested_form => {:allow_destroy => false, :update_only => false}
224
+ })
225
+ expect(param[:primary_key_proc].call).to eq(:_id)
226
+ expect(param[:model_proc].call).to eq(MongoNote)
227
+ end
228
+
229
+ it "raises error when embeds_* is used without accepts_nested_attributes_for" do
230
+ class MongoEmbedsOne
231
+ include Mongoid::Document
232
+ embeds_one :mongo_embedded
233
+ end
234
+
235
+ class MongoEmbedsMany
236
+ include Mongoid::Document
237
+ embeds_many :mongo_embeddeds
238
+ end
239
+
240
+ class MongoEmbedded
241
+ include Mongoid::Document
242
+ embedded_in :mongo_embeds_one
243
+ embedded_in :mongo_embeds_many
244
+ end
245
+
246
+ expect(lambda{ RailsAdmin::AbstractModel.new(MongoEmbedsOne).associations }).to raise_error(RuntimeError,
247
+ "Embbeded association without accepts_nested_attributes_for can't be handled by RailsAdmin,\nbecause embedded model doesn't have top-level access.\nPlease add `accepts_nested_attributes_for :mongo_embedded' line to `MongoEmbedsOne' model.\n"
248
+ )
249
+ expect(lambda{ RailsAdmin::AbstractModel.new(MongoEmbedsMany).associations }).to raise_error(RuntimeError,
250
+ "Embbeded association without accepts_nested_attributes_for can't be handled by RailsAdmin,\nbecause embedded model doesn't have top-level access.\nPlease add `accepts_nested_attributes_for :mongo_embeddeds' line to `MongoEmbedsMany' model.\n"
251
+ )
252
+ end
253
+
254
+ it "works with inherited embeds_many model" do
255
+ class MongoEmbedsParent
256
+ include Mongoid::Document
257
+ embeds_many :mongo_embeddeds
258
+ accepts_nested_attributes_for :mongo_embeddeds
259
+ end
260
+
261
+ class MongoEmbedded
262
+ include Mongoid::Document
263
+ embedded_in :mongo_embeds_many
264
+ end
265
+
266
+ class MongoEmbedsChild < MongoEmbedsParent; end
267
+
268
+ expect(lambda{ RailsAdmin::AbstractModel.new(MongoEmbedsChild).associations }).not_to raise_error
269
+ end
270
+ end
271
+
272
+ describe "#properties" do
273
+ before :all do
274
+ @abstract_model = RailsAdmin::AbstractModel.new(FieldTest)
275
+ end
276
+
277
+ it "maps Mongoid column types to RA types" do
278
+ expect(@abstract_model.properties.select{|p| %w(_id _type array_field big_decimal_field
279
+ boolean_field bson_object_id_field date_field datetime_field time_with_zone_field default_field float_field
280
+ hash_field integer_field name object_field range_field short_text string_field subject
281
+ symbol_field text_field time_field title).
282
+ include? p[:name].to_s}).to match_array [
283
+ { :name => :_id,
284
+ :pretty_name => "Id",
285
+ :nullable? => true,
286
+ :serial? => true,
287
+ :type => :bson_object_id,
288
+ :length => nil },
289
+ { :name => :_type,
290
+ :pretty_name => "Type",
291
+ :nullable? => true,
292
+ :serial? => false,
293
+ :type => :text,
294
+ :length => nil },
295
+ { :name => :array_field,
296
+ :pretty_name => "Array field",
297
+ :nullable? => true,
298
+ :serial? => false,
299
+ :type => :serialized,
300
+ :length => nil },
301
+ { :name => :big_decimal_field,
302
+ :pretty_name => "Big decimal field",
303
+ :nullable? => true,
304
+ :serial? => false,
305
+ :type => :decimal,
306
+ :length => nil },
307
+ { :name => :boolean_field,
308
+ :pretty_name => "Boolean field",
309
+ :nullable? => true,
310
+ :serial? => false,
311
+ :type => :boolean,
312
+ :length => nil },
313
+ { :name => :bson_object_id_field,
314
+ :pretty_name => "Bson object id field",
315
+ :nullable? => true,
316
+ :serial? => false,
317
+ :type => :bson_object_id,
318
+ :length => nil },
319
+ { :name => :date_field,
320
+ :pretty_name => "Date field",
321
+ :nullable? => true,
322
+ :serial? => false,
323
+ :type => :date,
324
+ :length => nil },
325
+ { :name => :datetime_field,
326
+ :pretty_name => "Datetime field",
327
+ :nullable? => true,
328
+ :serial? => false,
329
+ :type => :datetime,
330
+ :length => nil },
331
+ { :name => :time_with_zone_field,
332
+ :pretty_name => "Time with zone field",
333
+ :nullable? => true,
334
+ :serial? => false,
335
+ :type => :datetime,
336
+ :length => nil },
337
+ { :name => :default_field,
338
+ :pretty_name => "Default field",
339
+ :nullable? => true,
340
+ :serial? => false,
341
+ :type => :string,
342
+ :length => 255 },
343
+ { :name => :float_field,
344
+ :pretty_name => "Float field",
345
+ :nullable? => true,
346
+ :serial? => false,
347
+ :type => :float,
348
+ :length => nil },
349
+ { :name => :hash_field,
350
+ :pretty_name => "Hash field",
351
+ :nullable? => true,
352
+ :serial? => false,
353
+ :type => :serialized,
354
+ :length => nil },
355
+ { :name => :integer_field,
356
+ :pretty_name => "Integer field",
357
+ :nullable? => true,
358
+ :serial? => false,
359
+ :type => :integer,
360
+ :length => nil },
361
+ { :name => :name,
362
+ :pretty_name => "Name",
363
+ :nullable? => true,
364
+ :serial? => false,
365
+ :type => :string,
366
+ :length => 255 },
367
+ { :name => :object_field,
368
+ :pretty_name => "Object field",
369
+ :nullable? => true,
370
+ :serial? => false,
371
+ :type => :string,
372
+ :length => 255 },
373
+ { :name => :short_text,
374
+ :pretty_name => "Short text",
375
+ :nullable? => true,
376
+ :serial? => false,
377
+ :type => :string,
378
+ :length => 255 },
379
+ { :name => :string_field,
380
+ :pretty_name => "String field",
381
+ :nullable? => true,
382
+ :serial? => false,
383
+ :type => :text,
384
+ :length => nil },
385
+ { :name => :subject,
386
+ :pretty_name => "Subject",
387
+ :nullable? => true,
388
+ :serial? => false,
389
+ :type => :string,
390
+ :length => 255 },
391
+ { :name => :symbol_field,
392
+ :pretty_name => "Symbol field",
393
+ :nullable? => true,
394
+ :serial? => false,
395
+ :type => :string,
396
+ :length => 255 },
397
+ { :name => :text_field,
398
+ :pretty_name => "Text field",
399
+ :nullable? => true,
400
+ :serial? => false,
401
+ :type => :text,
402
+ :length => nil },
403
+ { :name => :time_field,
404
+ :pretty_name => "Time field",
405
+ :nullable? => true,
406
+ :serial? => false,
407
+ :type => :datetime,
408
+ :length => nil },
409
+ { :name => :title,
410
+ :pretty_name => "Title",
411
+ :nullable? => true,
412
+ :serial? => false,
413
+ :type => :string,
414
+ :length => 255 }
415
+ ]
416
+ end
417
+
418
+ it "detects validation length properly" do
419
+ class LengthValiated
420
+ include Mongoid::Document
421
+ field :text, :type => String
422
+ validates :text, :length => {:maximum => 50}
423
+ end
424
+ expect(RailsAdmin::AbstractModel.new('LengthValiated').send(:length_validation_lookup, :text)).to eq(50)
425
+ end
426
+
427
+ it "does not cause problem with custom validators" do
428
+ class MyCustomValidator < ActiveModel::Validator
429
+ def validate(r); end
430
+ end
431
+ class CustomValiated
432
+ include Mongoid::Document
433
+ field :text, :type => String
434
+ validates_with MyCustomValidator
435
+ end
436
+ expect(lambda{ RailsAdmin::AbstractModel.new('CustomValiated').send(:length_validation_lookup, :text) }).not_to raise_error
437
+ end
438
+ end
439
+
440
+ describe "data access method" do
441
+ before do
442
+ @players = FactoryGirl.create_list(:player, 3)
443
+ @abstract_model = RailsAdmin::AbstractModel.new('Player')
444
+ end
445
+
446
+ it "#new returns instance of AbstractObject" do
447
+ expect(@abstract_model.new.object).to be_instance_of(Player)
448
+ end
449
+
450
+ it "#get returns instance of AbstractObject" do
451
+ expect(@abstract_model.get(@players.first.id.to_s).object).to eq(@players.first)
452
+ end
453
+
454
+ it "#get returns nil when id does not exist" do
455
+ expect(@abstract_model.get('4f4f0824dcf2315093000000')).to be_nil
456
+ end
457
+
458
+ it "#first returns a player" do
459
+ expect(@players).to include @abstract_model.first
460
+ end
461
+
462
+ it "#count returns count of items" do
463
+ expect(@abstract_model.count).to eq(@players.count)
464
+ end
465
+
466
+ it "#destroy destroys multiple items" do
467
+ @abstract_model.destroy(@players[0..1])
468
+ expect(Player.all).to eq(@players[2..2])
469
+ end
470
+
471
+ it "#where returns filtered results" do
472
+ expect(@abstract_model.where(:name => @players.first.name).to_a).to eq([@players.first])
473
+ end
474
+
475
+ describe "#all" do
476
+ it "works without options" do
477
+ expect(@abstract_model.all.to_a).to match_array @players
478
+ end
479
+
480
+ it "supports eager loading" do
481
+ expect(@abstract_model.all(:include => :team).inclusions.map{|i| i.class_name}).to eq(["Team"])
482
+ end
483
+
484
+ it "supports limiting" do
485
+ expect(@abstract_model.all(:limit => 2).to_a).to have(2).items
486
+ end
487
+
488
+ it "supports retrieval by bulk_ids" do
489
+ expect(@abstract_model.all(:bulk_ids => @players[0..1].map{|player| player.id.to_s }).to_a).to match_array @players[0..1]
490
+ end
491
+
492
+ it "supports pagination" do
493
+ expect(@abstract_model.all(:sort => 'players._id', :page => 2, :per => 1).to_a).to eq(@players[1..1])
494
+ # To prevent RSpec matcher to call Mongoid::Criteria#== method,
495
+ # (we want to test equality of query result, not of Mongoid criteria)
496
+ # to_a is added to invoke Mongoid query
497
+ end
498
+
499
+ it "supports ordering" do
500
+ expect(@abstract_model.all(:sort => 'players._id', :sort_reverse => true).to_a).to eq(@players.sort)
501
+ expect(@abstract_model.all(:sort => 'players._id', :sort_reverse => false).to_a).to eq(@players.sort.reverse)
502
+ end
503
+
504
+ it "supports querying" do
505
+ expect(@abstract_model.all(:query => @players[1].name)).to eq(@players[1..1])
506
+ end
507
+
508
+ it "supports filtering" do
509
+ expect(@abstract_model.all(:filters => {"name" => {"0000" => {:o => "is", :v => @players[1].name}}})).to eq(@players[1..1])
510
+ end
511
+
512
+ it "ignores non-existent field name on filtering" do
513
+ expect(lambda{ @abstract_model.all(:filters => {"dummy" => {"0000" => {:o => "is", :v => @players[1].name}}}) }).not_to raise_error
514
+ end
515
+ end
516
+ end
517
+
518
+ describe "searching on association" do
519
+ describe "whose type is belongs_to" do
520
+ before do
521
+ RailsAdmin.config Player do
522
+ field :team do
523
+ queryable true
524
+ end
525
+ end
526
+ @players = FactoryGirl.create_list(:player, 3)
527
+ @team = FactoryGirl.create :team, :name => 'foobar'
528
+ @team.players << @players[1]
529
+ @abstract_model = RailsAdmin::AbstractModel.new('Player')
530
+ end
531
+
532
+ it "supports querying" do
533
+ expect(@abstract_model.all(:query => 'foobar').to_a).to eq(@players[1..1])
534
+ end
535
+
536
+ it "supports filtering" do
537
+ expect(@abstract_model.all(:filters => {"team" => {"0000" => {:o => "is", :v => 'foobar'}}}).to_a).to eq(@players[1..1])
538
+ end
539
+ end
540
+
541
+ describe "whose type is has_many" do
542
+ before do
543
+ RailsAdmin.config Team do
544
+ field :players do
545
+ queryable true
546
+ searchable :all
547
+ end
548
+ end
549
+ @teams = FactoryGirl.create_list(:team, 3)
550
+ @players = [{:team => @teams[1]},
551
+ {:team => @teams[1], :name => 'foobar'},
552
+ {:team => @teams[2]}].map{|h| FactoryGirl.create :player, h}
553
+ @abstract_model = RailsAdmin::AbstractModel.new('Team')
554
+ end
555
+
556
+ it "supports querying" do
557
+ expect(@abstract_model.all(:query => 'foobar').to_a).to eq(@teams[1..1])
558
+ end
559
+
560
+ it "supports filtering" do
561
+ expect(@abstract_model.all(:filters => {"players" => {"0000" => {:o => "is", :v => 'foobar'}}}).to_a).to eq(@teams[1..1])
562
+ end
563
+ end
564
+
565
+ describe "whose type is has_and_belongs_to_many" do
566
+ before do
567
+ RailsAdmin.config Team do
568
+ field :fans do
569
+ queryable true
570
+ searchable :all
571
+ end
572
+ end
573
+ @teams = FactoryGirl.create_list(:team, 3)
574
+ @fans = [{}, {:name => 'foobar'}, {}].map{|h| FactoryGirl.create :fan, h}
575
+ @teams[1].fans = [@fans[0], @fans[1]]
576
+ @teams[2].fans << @fans[2]
577
+ @abstract_model = RailsAdmin::AbstractModel.new('Team')
578
+ end
579
+
580
+ it "supports querying" do
581
+ expect(@abstract_model.all(:query => 'foobar').to_a).to eq(@teams[1..1])
582
+ end
583
+
584
+ it "supports filtering" do
585
+ expect(@abstract_model.all(:filters => {"fans" => {"0000" => {:o => "is", :v => 'foobar'}}}).to_a).to eq(@teams[1..1])
586
+ end
587
+ end
588
+
589
+ describe "whose type is embedded has_many" do
590
+ before do
591
+ RailsAdmin.config FieldTest do
592
+ field :embeds do
593
+ queryable true
594
+ searchable :all
595
+ end
596
+ end
597
+ @field_tests = FactoryGirl.create_list(:field_test, 3)
598
+ @field_tests[0].embeds.create :name => 'foo'
599
+ @field_tests[1].embeds.create :name => 'bar'
600
+ @abstract_model = RailsAdmin::AbstractModel.new('FieldTest')
601
+ end
602
+
603
+ it "supports querying" do
604
+ expect(@abstract_model.all(:query => 'bar').to_a).to eq(@field_tests[1..1])
605
+ end
606
+
607
+ it "supports filtering" do
608
+ expect(@abstract_model.all(:filters => {"embeds" => {"0000" => {:o => "is", :v => 'bar'}}}).to_a).to eq(@field_tests[1..1])
609
+ end
610
+ end
611
+ end
612
+
613
+ describe "#query_conditions" do
614
+ before do
615
+ @abstract_model = RailsAdmin::AbstractModel.new('Player')
616
+ @players = [{}, {:name => 'Many foos'}, {:position => 'foo shortage'}].
617
+ map{|h| FactoryGirl.create :player, h}
618
+ end
619
+
620
+ it "makes conrrect query" do
621
+ expect(@abstract_model.all(:query => "foo").to_a).to match_array @players[1..2]
622
+ end
623
+ end
624
+
625
+ describe "#filter_conditions" do
626
+ before do
627
+ @abstract_model = RailsAdmin::AbstractModel.new('Player')
628
+ @team = FactoryGirl.create :team, :name => 'king of bar'
629
+ @players = [{}, {:team => @team}, {:name => 'Many foos', :team => @team}, {:name => 'Great foo'}].
630
+ map{|h| FactoryGirl.create :player, h}
631
+ end
632
+
633
+ it "makes conrrect query" do
634
+ expect(@abstract_model.all(:filters =>
635
+ {"name" => {"0000" => {:o => "like", :v => "foo"}},
636
+ "team" => {"0001" => {:o => "like", :v => "bar"}}}
637
+ )).to eq([@players[2]])
638
+ end
639
+ end
640
+
641
+ describe "#build_statement" do
642
+ before do
643
+ @abstract_model = RailsAdmin::AbstractModel.new('FieldTest')
644
+ end
645
+
646
+ it "ignores '_discard' operator or value" do
647
+ [["_discard", ""], ["", "_discard"]].each do |value, operator|
648
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to be_nil
649
+ end
650
+ end
651
+
652
+ it "supports '_blank' operator" do
653
+ [["_blank", ""], ["", "_blank"]].each do |value, operator|
654
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq({:name => {"$in" => [nil, ""]}})
655
+ end
656
+ end
657
+
658
+ it "supports '_present' operator" do
659
+ [["_present", ""], ["", "_present"]].each do |value, operator|
660
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq({:name => {"$nin" => [nil, ""]}})
661
+ end
662
+ end
663
+
664
+ it "supports '_null' operator" do
665
+ [["_null", ""], ["", "_null"]].each do |value, operator|
666
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq({:name => nil})
667
+ end
668
+ end
669
+
670
+ it "supports '_not_null' operator" do
671
+ [["_not_null", ""], ["", "_not_null"]].each do |value, operator|
672
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq({:name => {"$ne" => nil}})
673
+ end
674
+ end
675
+
676
+ it "supports '_empty' operator" do
677
+ [["_empty", ""], ["", "_empty"]].each do |value, operator|
678
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq({:name => ""})
679
+ end
680
+ end
681
+
682
+ it "supports '_not_empty' operator" do
683
+ [["_not_empty", ""], ["", "_not_empty"]].each do |value, operator|
684
+ expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq({:name => {"$ne" => ""}})
685
+ end
686
+ end
687
+
688
+ it "supports boolean type query" do
689
+ ['false', 'f', '0'].each do |value|
690
+ expect(@abstract_model.send(:build_statement, :field, :boolean, value, nil)).to eq({:field => false})
691
+ end
692
+ ['true', 't', '1'].each do |value|
693
+ expect(@abstract_model.send(:build_statement, :field, :boolean, value, nil)).to eq({:field => true})
694
+ end
695
+ expect(@abstract_model.send(:build_statement, :field, :boolean, 'word', nil)).to be_nil
696
+ end
697
+
698
+ it "supports integer type query" do
699
+ expect(@abstract_model.send(:build_statement, :field, :integer, "1", nil)).to eq({:field => 1})
700
+ expect(@abstract_model.send(:build_statement, :field, :integer, 'word', nil)).to be_nil
701
+ end
702
+
703
+ it "supports integer type range query" do
704
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', '', ''], nil)).to be_nil
705
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['2', '', ''], nil)).to eq({:field => 2})
706
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', '3', ''], nil)).to eq({:field => {"$gte" => 3}})
707
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', '', '5'], nil)).to eq({:field => {"$lte" => 5}})
708
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['' , '10', '20'], nil)).to eq({:field => {"$gte" => 10, "$lte" => 20}})
709
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['15', '10', '20'], nil)).to eq({:field => {"$gte" => 10, "$lte" => 20}})
710
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', 'word1', '' ], nil)).to be_nil
711
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', '' , 'word2'], nil)).to be_nil
712
+ expect(@abstract_model.send(:build_statement, :field, :integer, ['', 'word3', 'word4'], nil)).to be_nil
713
+ end
714
+
715
+ it "supports string type query" do
716
+ expect(@abstract_model.send(:build_statement, :field, :string, "", nil)).to be_nil
717
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "was")).to be_nil
718
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "default")).to eq({:field => /foo/i})
719
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "like")).to eq({:field => /foo/i})
720
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "starts_with")).to eq({:field => /^foo/i})
721
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "ends_with")).to eq({:field => /foo$/i})
722
+ expect(@abstract_model.send(:build_statement, :field, :string, "foo", "is")).to eq({:field => 'foo'})
723
+ end
724
+
725
+ it "supports date type query" do
726
+ expect(@abstract_model.send(:filter_conditions, { "date_field" => { "1" => { :v => ["", "01/02/2012", "01/03/2012"], :o => 'between' } } })).to eq({"$and" => [{"date_field" => {"$gte" => Date.new(2012,1,2), "$lte" => Date.new(2012,1,3)}}]})
727
+ expect(@abstract_model.send(:filter_conditions, { "date_field" => { "1" => { :v => ["", "01/03/2012", ""], :o => 'between' } } } )).to eq({"$and" => [{"date_field" => {"$gte" => Date.new(2012,1,3)}}]})
728
+ expect(@abstract_model.send(:filter_conditions, { "date_field" => { "1" => { :v => ["", "", "01/02/2012"], :o => 'between' } } } )).to eq({"$and" => [{"date_field" => {"$lte" => Date.new(2012,1,2)}}]})
729
+ expect(@abstract_model.send(:filter_conditions, { "date_field" => { "1" => { :v => ["01/02/2012"], :o => 'default' } } } )).to eq({"$and" => [{"date_field" => {"$gte" => Date.new(2012,1,2), "$lte" => Date.new(2012,1,2)}}]})
730
+ end
731
+
732
+ it "supports datetime type query" do
733
+ expect(@abstract_model.send(:filter_conditions, { "datetime_field" => { "1" => { :v => ["", "01/02/2012", "01/03/2012"], :o => 'between' } } } )).to eq({"$and" => [{"datetime_field" => {"$gte" => Time.local(2012,1,2), "$lte" => Time.local(2012,1,3).end_of_day}}]})
734
+ expect(@abstract_model.send(:filter_conditions, { "datetime_field" => { "1" => { :v => ["", "01/03/2012", ""], :o => 'between' } } } )).to eq({"$and" => [{"datetime_field" => {"$gte" => Time.local(2012,1,3)}}]})
735
+ expect(@abstract_model.send(:filter_conditions, { "datetime_field" => { "1" => { :v => ["", "", "01/02/2012"], :o => 'between' } } } )).to eq({"$and" => [{"datetime_field" => {"$lte" => Time.local(2012,1,2).end_of_day}}]})
736
+ expect(@abstract_model.send(:filter_conditions, { "datetime_field" => { "1" => { :v => ["01/02/2012"], :o => 'default' } } } )).to eq({"$and" => [{"datetime_field" => {"$gte" => Time.local(2012,1,2), "$lte" => Time.local(2012,1,2).end_of_day}}]})
737
+ end
738
+
739
+ it "supports enum type query" do
740
+ expect(@abstract_model.send(:build_statement, :field, :enum, "1", nil)).to eq({:field => {"$in" => ["1"]}})
741
+ end
742
+ end
743
+
744
+ describe "model attribute method" do
745
+ before do
746
+ @abstract_model = RailsAdmin::AbstractModel.new('Player')
747
+ end
748
+
749
+ it "#scoped returns relation object" do
750
+ expect(@abstract_model.scoped).to be_instance_of(Mongoid::Criteria)
751
+ end
752
+
753
+ it "#table_name works" do
754
+ expect(@abstract_model.table_name).to eq('players')
755
+ end
756
+ end
757
+
758
+ describe "serialization" do
759
+ before do
760
+ @abstract_model = RailsAdmin::AbstractModel.new('FieldTest')
761
+ @controller = RailsAdmin::MainController.new
762
+ end
763
+
764
+ it "accepts array value" do
765
+ params = HashWithIndifferentAccess.new({:array_field => '[1, 3]'})
766
+ @controller.send(:sanitize_params_for!, 'create', @abstract_model.config, params)
767
+ expect(params[:array_field]).to eq([1, 3])
768
+ end
769
+
770
+ it "accepts hash value" do
771
+ params = HashWithIndifferentAccess.new({:hash_field => '{a: 1, b: 3}'})
772
+ @controller.send(:sanitize_params_for!, 'create', @abstract_model.config, params)
773
+ expect(params[:hash_field]).to eq({"a" => 1, "b" => 3})
774
+ end
775
+ end
776
+ end