rails_admin-lbgraham 0.4.2

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