spiderfw 0.5.19 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/VERSION +1 -1
- data/apps/core/auth/lib/rbac.rb +7 -2
- data/apps/core/auth/models/mixins/rbac_provider.rb +66 -4
- data/apps/core/components/assets.rb +63 -33
- data/apps/core/components/public/js/jquery/{jquery-1.4.3.js → jquery-1.5.2.js} +2617 -1126
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/overlay/overlay.apple.js +155 -0
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/overlay/overlay.js +293 -0
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/scrollable/scrollable.js +335 -0
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/tabs/tabs.css +59 -0
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/tabs/tabs.js +283 -0
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/toolbox/toolbox.expose.js +224 -0
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/tooltip/tooltip.dynamic.js +150 -0
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/tooltip/tooltip.js +343 -0
- data/apps/core/components/public/js/jquery/jquery-tools-1.2.5/tooltip/tooltip.slide.js +78 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/button_bg.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/datepicker.gif +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/icon_sprite.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/progress_bar.gif +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/slider_h_bg.gif +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/slider_handles.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/slider_v_bg.gif +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/tab_bg.gif +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/the_gradient.gif +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-anim_basic_16x16.gif +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-icons_222222_256x240.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-icons_228ef1_256x240.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-icons_ef8c08_256x240.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-icons_ffd27a_256x240.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/images/ui-icons_ffffff_256x240.png +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4 → jquery-ui-1.8.11}/css/Aristo/jquery-ui.custom.css +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-af.js +0 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-ar-DZ.js +23 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-ar.js +7 -8
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-az.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-bg.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-bs.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-ca.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-cs.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-da.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-de.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-el.js +0 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-en-AU.js +23 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-en-GB.js +0 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-en-NZ.js +23 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-eo.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-es.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-et.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-eu.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-fa.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-fi.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-fo.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-fr-CH.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-fr.js +12 -10
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-gl.js +23 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-he.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-hr.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-hu.js +1 -1
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-hy.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-id.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-is.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-it.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-ja.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-ko.js +0 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-kz.js +23 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-lt.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-lv.js +0 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-ml.js +23 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-ms.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-nl.js +0 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-no.js +23 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-pl.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-pt-BR.js +0 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-pt.js +22 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-rm.js +21 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-ro.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-ru.js +1 -1
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-sk.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-sl.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-sq.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-sr-SR.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-sr.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-sv.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-ta.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-th.js +1 -1
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/i18n/jquery.ui.datepicker-tj.js +23 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-tr.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-uk.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-vi.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-zh-CN.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-zh-HK.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/i18n/jquery.ui.datepicker-zh-TW.js +0 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.blind.js +3 -3
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.bounce.js +3 -3
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.clip.js +3 -3
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.core.js +48 -15
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.drop.js +3 -3
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.explode.js +2 -2
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.11/ui/jquery.effects.fade.js +32 -0
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.fold.js +3 -3
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.highlight.js +2 -2
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.pulsate.js +2 -2
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.scale.js +4 -4
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.shake.js +3 -3
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.slide.js +4 -4
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.effects.transfer.js +2 -2
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.accordion.js +33 -20
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.autocomplete.js +104 -42
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.button.js +35 -13
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.core.js +111 -84
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.datepicker.js +87 -46
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.dialog.js +105 -75
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.draggable.js +17 -15
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.droppable.js +5 -5
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.mouse.js +16 -11
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.position.js +51 -32
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.progressbar.js +24 -10
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.resizable.js +7 -7
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.selectable.js +3 -3
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.slider.js +9 -7
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.sortable.js +22 -20
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.tabs.js +15 -14
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → jquery-ui-1.8.11}/ui/jquery.ui.widget.js +50 -25
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → plugins/bsmselect}/GPL-LICENSE.txt +1 -1
- data/apps/core/components/public/js/jquery/{jquery-ui-1.8.4/development-bundle → plugins/bsmselect}/MIT-LICENSE.txt +3 -7
- data/apps/core/components/public/js/jquery/plugins/bsmselect/README.md +185 -0
- data/apps/core/components/public/js/jquery/plugins/bsmselect/css/jquery.bsmselect.css +64 -0
- data/apps/core/components/public/js/jquery/plugins/bsmselect/js/jquery.bsmselect.compatibility.js +60 -0
- data/apps/core/components/public/js/jquery/plugins/bsmselect/js/jquery.bsmselect.js +381 -0
- data/apps/core/components/public/js/jquery/plugins/bsmselect/js/jquery.bsmselect.sortable.js +49 -0
- data/apps/core/components/public/js/plugins/sortable.js +16 -7
- data/apps/core/components/public/js/spider.js +60 -41
- data/apps/core/components/widgets/admin/admin.shtml +1 -1
- data/apps/core/components/widgets/list/list.shtml +2 -2
- data/apps/core/components/widgets/month_calendar/month_calendar.shtml +23 -20
- data/apps/core/components/widgets/switcher/switcher.rb +77 -21
- data/apps/core/components/widgets/switcher/templates/default.shtml +8 -0
- data/apps/core/components/widgets/switcher/templates/table.shtml +15 -0
- data/apps/core/components/widgets/table/table.rb +4 -1
- data/apps/core/components/widgets/table/table.shtml +10 -8
- data/apps/core/forms/public/css/form.css +9 -1
- data/apps/core/forms/public/date_time.js +14 -2
- data/apps/core/forms/public/input.js +1 -1
- data/apps/core/forms/public/select.js +4 -3
- data/apps/core/forms/tags/element_row.erb +11 -2
- data/apps/core/forms/widgets/inputs/date_time/date_time.rb +9 -0
- data/apps/core/forms/widgets/inputs/date_time/date_time.shtml +1 -1
- data/apps/core/forms/widgets/inputs/html_area/html_area.shtml +2 -2
- data/apps/core/forms/widgets/inputs/input/input.rb +0 -3
- data/apps/core/forms/widgets/inputs/select/select.shtml +2 -2
- data/apps/messenger/backends/email/sendmail.rb +20 -0
- data/apps/messenger/backends/email/smtp.rb +12 -14
- data/apps/messenger/backends/email/test.rb +20 -0
- data/apps/messenger/config/options.rb +9 -9
- data/apps/messenger/config/test.config.yml +2 -0
- data/apps/messenger/controllers/mixins/messenger_helper.rb +41 -15
- data/apps/messenger/lib/email_backend.rb +10 -0
- data/apps/messenger/messenger.rb +45 -26
- data/apps/messenger/test/features/attachments.feature +26 -0
- data/apps/messenger/test/features/messenger_helper.feature +31 -0
- data/apps/messenger/test/features/sending_email.feature +10 -0
- data/apps/messenger/test/features/step_definitions/common_steps.rb +11 -0
- data/apps/messenger/test/features/step_definitions/email_steps.rb +98 -0
- data/apps/messenger/test/features/support/env.rb +11 -0
- data/apps/messenger/test/files/test_file1.txt +1 -0
- data/apps/messenger/test/lib/controllers/mail_test_controller.rb +34 -0
- data/apps/messenger/test/templates/email/multipart.html.erb +1 -0
- data/apps/messenger/test/templates/email/multipart.txt.erb +1 -0
- data/apps/messenger/test/templates/email/simple.erb +1 -0
- data/apps/messenger/test/templates/email/vars.erb +1 -0
- data/lib/spiderfw/cmd/cmd.rb +4 -0
- data/lib/spiderfw/cmd/commands/webserver.rb +12 -59
- data/lib/spiderfw/config/configuration.rb +4 -0
- data/lib/spiderfw/config/options/spider.rb +25 -8
- data/lib/spiderfw/controller/controller.rb +10 -4
- data/lib/spiderfw/controller/first_responder.rb +6 -20
- data/lib/spiderfw/controller/http_controller.rb +2 -1
- data/lib/spiderfw/controller/mixins/http_mixin.rb +12 -1
- data/lib/spiderfw/controller/mixins/visual.rb +3 -16
- data/lib/spiderfw/env.rb +1 -1
- data/lib/spiderfw/http/server.rb +178 -2
- data/lib/spiderfw/model/base_model.rb +142 -111
- data/lib/spiderfw/model/data_type.rb +15 -0
- data/lib/spiderfw/model/datatypes/decimal.rb +8 -0
- data/lib/spiderfw/model/datatypes/pk.rb +29 -0
- data/lib/spiderfw/model/datatypes.rb +1 -0
- data/lib/spiderfw/model/element.rb +5 -1
- data/lib/spiderfw/model/extended_models/managed.rb +1 -1
- data/lib/spiderfw/model/junction.rb +23 -0
- data/lib/spiderfw/model/mappers/db_mapper.rb +96 -80
- data/lib/spiderfw/model/mappers/document_mapper.rb +315 -0
- data/lib/spiderfw/model/mappers/mapper.rb +164 -75
- data/lib/spiderfw/model/mixins/list.rb +1 -0
- data/lib/spiderfw/model/mixins/versioned.rb +63 -27
- data/lib/spiderfw/model/model.rb +36 -9
- data/lib/spiderfw/model/query_funcs.rb +3 -0
- data/lib/spiderfw/model/query_set.rb +21 -1
- data/lib/spiderfw/model/storage/base_storage.rb +259 -6
- data/lib/spiderfw/model/storage/{db/db_connection_pool.rb → connection_pool.rb} +25 -21
- data/lib/spiderfw/model/storage/db/adapters/mysql.rb +25 -5
- data/lib/spiderfw/model/storage/db/adapters/oracle.rb +1 -1
- data/lib/spiderfw/model/storage/db/connectors/jdbc_oracle.rb +2 -2
- data/lib/spiderfw/model/storage/db/connectors/oci8.rb +3 -4
- data/lib/spiderfw/model/storage/db/db_storage.rb +18 -219
- data/lib/spiderfw/model/storage/document/adapters/mongodb.rb +307 -0
- data/lib/spiderfw/model/storage/document/document.rb +7 -0
- data/lib/spiderfw/model/storage/document/document_storage.rb +34 -0
- data/lib/spiderfw/model/storage.rb +23 -11
- data/lib/spiderfw/model/unit_of_work.rb +45 -22
- data/lib/spiderfw/spider.rb +660 -0
- data/lib/spiderfw/templates/blocks/html.rb +4 -2
- data/lib/spiderfw/templates/blocks/run.rb +1 -1
- data/lib/spiderfw/templates/blocks/tag_if.rb +1 -1
- data/lib/spiderfw/templates/blocks/widget.rb +1 -1
- data/lib/spiderfw/templates/layout.rb +29 -5
- data/lib/spiderfw/templates/template.rb +72 -7
- data/lib/spiderfw/templates/template_blocks.rb +1 -1
- data/lib/spiderfw/test/capybara.rb +7 -0
- data/lib/spiderfw/test/cucumber.rb +12 -0
- data/lib/spiderfw/test/page_object.rb +29 -0
- data/lib/spiderfw/test/spec.rb +20 -0
- data/lib/spiderfw/test/stubs/mapper_stub.rb +18 -0
- data/lib/spiderfw/test/stubs/storage_stub.rb +23 -0
- data/lib/spiderfw/test/unit.rb +23 -0
- data/lib/spiderfw/test.rb +89 -0
- data/lib/spiderfw/utils/json.rb +6 -0
- data/lib/spiderfw/utils/logger.rb +17 -4
- data/lib/spiderfw/utils/loggers/apache_commons_logger.rb +61 -0
- data/lib/spiderfw/utils/monkey/date_time.rb +2 -2
- data/lib/spiderfw/utils/monkey/module.rb +3 -1
- data/lib/spiderfw/utils/profiling.rb +2 -2
- data/lib/spiderfw/widget/widget.rb +31 -13
- data/lib/spiderfw.rb +1 -597
- data/spider.gemspec +9 -10
- metadata +193 -132
- data/apps/admin/_init.rb +0 -9
- data/apps/admin/controllers/admin_controller.rb +0 -12
- data/apps/admin/widgets/dashboard_widget/dashboard_widget.rb +0 -8
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.4/development-bundle/AUTHORS.txt +0 -30
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.4/development-bundle/ui/i18n/jquery-ui-i18n.js +0 -1176
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.4/development-bundle/ui/i18n/jquery.ui.datepicker-no.js +0 -23
- data/apps/core/components/public/js/jquery/jquery-ui-1.8.4/development-bundle/version.txt +0 -1
- data/apps/core/components/public/js/jquery/plugins/asmselect/jquery.asmselect.css +0 -64
- data/apps/core/components/public/js/jquery/plugins/asmselect/jquery.asmselect.js +0 -407
- data/apps/core/components/widgets/switcher/switcher.shtml +0 -17
- data/apps/master/po/master.pot +0 -400
@@ -126,8 +126,6 @@ module Spider; module Model; module Storage; module Db; module Connectors
|
|
126
126
|
case type.name
|
127
127
|
when 'Spider::DataTypes::Decimal', 'BigDecimal'
|
128
128
|
java_bigdecimal(value)
|
129
|
-
when 'Spider::DataTypes::Bool'
|
130
|
-
value ? 1 : 0
|
131
129
|
when 'Date', 'DateTime'
|
132
130
|
java_date(value)
|
133
131
|
when 'Time'
|
@@ -185,6 +183,8 @@ module Spider; module Model; module Storage; module Db; module Connectors
|
|
185
183
|
method = case type
|
186
184
|
when :INTEGER, :SMALLINT, :TINYING, :BIGINTEGER, :NUMBER, :NUMERIC
|
187
185
|
:getInt
|
186
|
+
when :LONG
|
187
|
+
:getLong
|
188
188
|
when :FLOAT, :REAL
|
189
189
|
:getFloat
|
190
190
|
when :DECIMAL
|
@@ -66,9 +66,8 @@ module Spider; module Model; module Storage; module Db; module Connectors
|
|
66
66
|
|
67
67
|
def prepare_value(type, value)
|
68
68
|
value = super
|
69
|
-
if
|
70
|
-
|
71
|
-
end
|
69
|
+
type = type.primary_keys[0].type if type < Spider::Model::BaseModel
|
70
|
+
type = Fixnum if type == Spider::DataTypes::PK
|
72
71
|
return Oracle::OracleNilValue.new(Spider::Model.ruby_type(type)) if (value == nil)
|
73
72
|
case type.name
|
74
73
|
when 'Spider::DataTypes::Binary'
|
@@ -84,7 +83,7 @@ module Spider; module Model; module Storage; module Db; module Connectors
|
|
84
83
|
debug_vars = bind_vars.map{|var| var = var.to_s; var && var.length > 50 ? var[0..50]+"...(#{var.length-50} chars more)" : var}
|
85
84
|
end
|
86
85
|
curr[:last_executed] = [sql, bind_vars]
|
87
|
-
if
|
86
|
+
if Spider.conf.get('storage.db.replace_debug_vars')
|
88
87
|
debug("oci8 #{connection} executing: "+sql.gsub(/:(\d+)/){
|
89
88
|
i = $1.to_i
|
90
89
|
v = bind_vars[i-1]
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spiderfw/model/storage/base_storage'
|
2
2
|
require 'spiderfw/model/mappers/db_mapper'
|
3
|
-
require 'spiderfw/model/storage/db/db_connection_pool'
|
4
3
|
require 'iconv'
|
5
4
|
|
6
5
|
module Spider; module Model; module Storage; module Db
|
@@ -31,60 +30,19 @@ module Spider; module Model; module Storage; module Db
|
|
31
30
|
attr_reader :type_synonyms
|
32
31
|
# Type conversions which do not lose data. See also #safe_schema_conversion?
|
33
32
|
attr_reader :safe_conversions
|
34
|
-
# An Hash of DB capabilities. The default is
|
35
|
-
# {:autoincrement => false, :sequences => true, :transactions => true}
|
36
|
-
# (The BaseStorage class provides file sequences in case the subclass does not support them.)
|
37
|
-
attr_reader :capabilities
|
38
33
|
|
39
|
-
|
40
|
-
def
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
def max_connections
|
45
|
-
nil
|
46
|
-
end
|
47
|
-
|
48
|
-
def connection_pools
|
49
|
-
@pools ||= {}
|
50
|
-
end
|
51
|
-
|
52
|
-
def get_connection(*args)
|
53
|
-
@pools ||= {}
|
54
|
-
@pools[args] ||= DbConnectionPool.new(args, self)
|
55
|
-
@pools[args].get_connection
|
56
|
-
end
|
57
|
-
|
58
|
-
# Frees a connection, relasing it to the pool
|
59
|
-
def release_connection(conn, conn_params)
|
60
|
-
return unless conn
|
61
|
-
return unless @pools && @pools[conn_params]
|
62
|
-
@pools[conn_params].release(conn)
|
63
|
-
end
|
64
|
-
|
65
|
-
# Removes a connection from the pool.
|
66
|
-
def remove_connection(conn, conn_params)
|
67
|
-
return unless conn
|
68
|
-
return unless @pools && @pools[conn_params]
|
69
|
-
@pools[conn_params].remove(conn)
|
34
|
+
|
35
|
+
def storage_type
|
36
|
+
:db
|
70
37
|
end
|
71
38
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def connection_alive?(conn)
|
78
|
-
raise "Virtual"
|
39
|
+
def inherited(subclass)
|
40
|
+
subclass.instance_variable_set("@reserved_keywords", @reserved_keywords)
|
41
|
+
subclass.instance_variable_set("@type_synonyms", @type_synonyms)
|
42
|
+
subclass.instance_variable_set("@safe_conversions", @safe_conversions)
|
43
|
+
super
|
79
44
|
end
|
80
|
-
|
81
|
-
def inherited(subclass)
|
82
|
-
subclass.instance_variable_set("@reserved_keywords", @reserved_keywords)
|
83
|
-
subclass.instance_variable_set("@type_synonyms", @type_synonyms)
|
84
|
-
subclass.instance_variable_set("@safe_conversions", @safe_conversions)
|
85
|
-
subclass.instance_variable_set("@capabilities", @capabilities)
|
86
|
-
end
|
87
|
-
|
45
|
+
|
88
46
|
end
|
89
47
|
|
90
48
|
def query_start
|
@@ -100,70 +58,11 @@ module Spider; module Model; module Storage; module Db
|
|
100
58
|
Spider.logger.info("Db query (#{@instance_name}) done in #{diff}ms")
|
101
59
|
end
|
102
60
|
|
103
|
-
def curr
|
104
|
-
Thread.current[:db_storages] ||= {}
|
105
|
-
Thread.current[:db_storages][@connection_params] ||= {
|
106
|
-
:transaction_nesting => 0, :savepoints => []
|
107
|
-
}
|
108
|
-
end
|
109
|
-
|
110
|
-
def connection_pool
|
111
|
-
self.class.connection_pools[@connection_params]
|
112
|
-
end
|
113
|
-
|
114
61
|
# The constructor takes the connection URL, which will be parsed into connection params.
|
115
62
|
def initialize(url)
|
116
63
|
super
|
117
64
|
end
|
118
65
|
|
119
|
-
# Instantiates a new connection with current connection params.
|
120
|
-
def connect
|
121
|
-
return self.class.get_connection(*@connection_params)
|
122
|
-
#Spider::Logger.debug("#{self.class.name} in thread #{Thread.current} acquired connection #{@conn}")
|
123
|
-
end
|
124
|
-
|
125
|
-
# True if currently connected.
|
126
|
-
def connected?
|
127
|
-
curr[:conn] != nil
|
128
|
-
end
|
129
|
-
|
130
|
-
|
131
|
-
# Returns the current connection, or creates a new one.
|
132
|
-
# If a block is given, will release the connection after yielding.
|
133
|
-
def connection
|
134
|
-
# is_connected = connected?
|
135
|
-
# Spider.logger.debug("#{self} already connected with conn #{@conn}") if is_connected
|
136
|
-
# connect unless is_connected
|
137
|
-
curr[:conn] = connect
|
138
|
-
if block_given?
|
139
|
-
yield curr[:conn]
|
140
|
-
release # unless is_connected
|
141
|
-
return true
|
142
|
-
else
|
143
|
-
#debugger unless @conn
|
144
|
-
return curr[:conn]
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def self.connection_attributes
|
149
|
-
@connection_attributes ||= {}
|
150
|
-
end
|
151
|
-
|
152
|
-
def connection_attributes
|
153
|
-
self.class.connection_attributes[connection] ||= {}
|
154
|
-
end
|
155
|
-
|
156
|
-
# Releases the current connection to the pool.
|
157
|
-
def release
|
158
|
-
# The subclass should check if the connection is alive, and if it is not call remove_connection instead
|
159
|
-
c = curr[:conn]
|
160
|
-
#Spider.logger.debug("#{self} in thread #{Thread.current} releasing #{curr[:conn]}")
|
161
|
-
curr[:conn] = nil
|
162
|
-
self.class.release_connection(c, @connection_params)
|
163
|
-
#Spider.logger.debug("#{self} in thread #{Thread.current} released #{curr[:conn]}")
|
164
|
-
return nil
|
165
|
-
#@conn = nil
|
166
|
-
end
|
167
66
|
|
168
67
|
# Returns the default mapper for the storage.
|
169
68
|
# If the storage subclass contains a MapperExtension module, it will be mixed-in with the mapper.
|
@@ -175,106 +74,6 @@ module Spider; module Model; module Storage; module Db
|
|
175
74
|
return mapper
|
176
75
|
end
|
177
76
|
|
178
|
-
# True if given named capability is supported by the DB.
|
179
|
-
def supports?(capability)
|
180
|
-
self.class.capabilities[capability]
|
181
|
-
end
|
182
|
-
|
183
|
-
def supports_transactions?
|
184
|
-
return self.class.capabilities[:transactions]
|
185
|
-
end
|
186
|
-
|
187
|
-
def transactions_enabled?
|
188
|
-
@configuration['enable_transactions'] && supports_transactions?
|
189
|
-
end
|
190
|
-
|
191
|
-
def start_transaction
|
192
|
-
return unless transactions_enabled?
|
193
|
-
return savepoint("point#{curr[:savepoints].length}") if in_transaction?
|
194
|
-
curr[:transaction_nesting] += 1
|
195
|
-
Spider.logger.debug("#{self.class.name} starting transaction for connection #{connection.object_id}")
|
196
|
-
do_start_transaction
|
197
|
-
return true
|
198
|
-
end
|
199
|
-
|
200
|
-
# May be implemented by subclasses.
|
201
|
-
def do_start_transaction
|
202
|
-
raise StorageException, "The current storage does not support transactions"
|
203
|
-
end
|
204
|
-
|
205
|
-
def in_transaction
|
206
|
-
if in_transaction?
|
207
|
-
curr[:transaction_nesting] += 1
|
208
|
-
return true
|
209
|
-
else
|
210
|
-
start_transaction
|
211
|
-
return false
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def in_transaction?
|
216
|
-
return false
|
217
|
-
end
|
218
|
-
|
219
|
-
def commit
|
220
|
-
return false unless transactions_enabled?
|
221
|
-
raise StorageException, "Commit without a transaction" unless in_transaction?
|
222
|
-
return curr[:savepoints].pop unless curr[:savepoints].empty?
|
223
|
-
commit!
|
224
|
-
end
|
225
|
-
|
226
|
-
def commit_or_continue
|
227
|
-
return false unless transactions_enabled?
|
228
|
-
raise StorageException, "Commit without a transaction" unless in_transaction?
|
229
|
-
if curr[:transaction_nesting] == 1
|
230
|
-
commit
|
231
|
-
return true
|
232
|
-
else
|
233
|
-
curr[:transaction_nesting] -= 1
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
def commit!
|
238
|
-
Spider.logger.debug("#{self.class.name} commit connection #{curr[:conn].object_id}")
|
239
|
-
curr[:transaction_nesting] = 0
|
240
|
-
do_commit
|
241
|
-
release
|
242
|
-
end
|
243
|
-
|
244
|
-
def do_commit
|
245
|
-
raise StorageException, "The current storage does not support transactions"
|
246
|
-
end
|
247
|
-
|
248
|
-
def rollback
|
249
|
-
raise "Can't rollback in a nested transaction" if curr[:transaction_nesting] > 1
|
250
|
-
return rollback_savepoint(curr[:savepoints].last) unless curr[:savepoints].empty?
|
251
|
-
rollback!
|
252
|
-
end
|
253
|
-
|
254
|
-
def rollback!
|
255
|
-
curr[:transaction_nesting] = 0
|
256
|
-
Spider.logger.debug("#{self.class.name} rollback")
|
257
|
-
do_rollback
|
258
|
-
curr[:savepoints] = []
|
259
|
-
release
|
260
|
-
end
|
261
|
-
|
262
|
-
def do_rollback
|
263
|
-
raise StorageException, "The current storage does not support transactions"
|
264
|
-
end
|
265
|
-
|
266
|
-
def savepoint(name)
|
267
|
-
curr[:savepoints] << name
|
268
|
-
end
|
269
|
-
|
270
|
-
def rollback_savepoint(name=nil)
|
271
|
-
if name
|
272
|
-
curr[:savepoints] = curr[:savepoints][0,(curr[:savepoints].index(name))]
|
273
|
-
name
|
274
|
-
else
|
275
|
-
curr[:savepoints].pop
|
276
|
-
end
|
277
|
-
end
|
278
77
|
|
279
78
|
def lock(table, mode=:exclusive)
|
280
79
|
lockmode = case(mode)
|
@@ -340,6 +139,9 @@ module Spider; module Model; module Storage; module Db
|
|
340
139
|
def column_attributes(type, attributes)
|
341
140
|
db_attributes = {}
|
342
141
|
case type.name
|
142
|
+
when 'Spider::DataTypes::PK'
|
143
|
+
db_attributes[:autoincrement] = true if supports?(:autoincrement)
|
144
|
+
db_attributes[:length] = 11
|
343
145
|
when 'String', 'Spider::DataTypes::Text'
|
344
146
|
db_attributes[:length] = attributes[:length] if (attributes[:length])
|
345
147
|
when 'Float'
|
@@ -379,6 +181,8 @@ module Spider; module Model; module Storage; module Db
|
|
379
181
|
return "SUBSTR(#{fields.join(', ')}, #{arguments})"
|
380
182
|
when :subtract
|
381
183
|
return "(#{fields[0]} - #{fields[1]})"
|
184
|
+
when :rownum
|
185
|
+
return "ROWNUM()"
|
382
186
|
end
|
383
187
|
raise NotImplementedError, "#{self.class} does not support function #{func.func_name}"
|
384
188
|
end
|
@@ -387,15 +191,6 @@ module Spider; module Model; module Storage; module Db
|
|
387
191
|
# Preparing values #
|
388
192
|
##################################################################
|
389
193
|
|
390
|
-
# Prepares a value for saving.
|
391
|
-
def value_for_save(type, value, save_mode)
|
392
|
-
return prepare_value(type, value)
|
393
|
-
end
|
394
|
-
|
395
|
-
# Prepares a value that will be used in a condition.
|
396
|
-
def value_for_condition(type, value)
|
397
|
-
return prepare_value(type, value)
|
398
|
-
end
|
399
194
|
|
400
195
|
# Converts a value loaded from the DB to return it to the mapper.
|
401
196
|
def value_to_mapper(type, value)
|
@@ -669,6 +464,10 @@ module Spider; module Model; module Storage; module Db
|
|
669
464
|
return [sql, bind_vars]
|
670
465
|
end
|
671
466
|
|
467
|
+
def sql_truncate(table)
|
468
|
+
"TRUNCATE #{table}"
|
469
|
+
end
|
470
|
+
|
672
471
|
# Returns an array of SQL statements for a create structured description.
|
673
472
|
def sql_create_table(create)
|
674
473
|
name = create[:table]
|
@@ -0,0 +1,307 @@
|
|
1
|
+
require 'spiderfw/model/storage/document/document_storage'
|
2
|
+
require 'mongo'
|
3
|
+
|
4
|
+
module Spider; module Model; module Storage; module Document
|
5
|
+
|
6
|
+
class Mongodb < DocumentStorage
|
7
|
+
CONDITION_OPS = {
|
8
|
+
'>' => '$gt', '<' => '$lt', '>=' => '$gte', '<=' => '$lte', 'not' => '$e', '<>' => '$ne'
|
9
|
+
}
|
10
|
+
|
11
|
+
def self.parse_url(url)
|
12
|
+
# doc:mongodb://<username:password>@<host>:<port>/<database>
|
13
|
+
if (url =~ /.+:\/\/(?:(.+):(.+)@)?(.+)?\/(.+)/)
|
14
|
+
user = $1
|
15
|
+
pass = $2
|
16
|
+
location = $3
|
17
|
+
db_name = $4
|
18
|
+
else
|
19
|
+
raise ArgumentError, "Mongodb url '#{url}' is invalid"
|
20
|
+
end
|
21
|
+
location =~ /(.+)(?::(\d+))/
|
22
|
+
host = $1
|
23
|
+
port = $2
|
24
|
+
return [host, user, pass, db_name, port]
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_url(url)
|
28
|
+
@host, @user, @pass, @db_name, @port = self.class.parse_url(url)
|
29
|
+
@connection_params = [@host, @user, @pass, @db_name, @port]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.new_connection(host=nil, user=nil, passwd=nil, db=nil, port=nil)
|
33
|
+
conn = ::Mongo::Connection.new(host, port)
|
34
|
+
conn.authenticate(user, passwd) if user
|
35
|
+
return conn
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.disconnect(conn)
|
39
|
+
conn.close
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.connection_alive?(conn)
|
43
|
+
conn.connected?
|
44
|
+
end
|
45
|
+
|
46
|
+
def connect
|
47
|
+
conn = super
|
48
|
+
curr[:db] = conn.db(@connection_params[3])
|
49
|
+
conn
|
50
|
+
end
|
51
|
+
|
52
|
+
def release
|
53
|
+
curr[:db] = nil
|
54
|
+
super
|
55
|
+
end
|
56
|
+
|
57
|
+
def db
|
58
|
+
connection
|
59
|
+
curr[:db]
|
60
|
+
end
|
61
|
+
|
62
|
+
def collection(coll)
|
63
|
+
db.collection(coll)
|
64
|
+
end
|
65
|
+
|
66
|
+
def insert(collection, doc)
|
67
|
+
Spider.logger.debug("Mongodb insert #{collection}:")
|
68
|
+
Spider.logger.debug(doc)
|
69
|
+
begin
|
70
|
+
collection(collection).insert(doc)
|
71
|
+
ensure
|
72
|
+
release
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def update(collection, selector, vals)
|
77
|
+
Spider.logger.debug("Mongodb update #{collection}, #{selector.inspect}:")
|
78
|
+
Spider.logger.debug(vals)
|
79
|
+
begin
|
80
|
+
collection(collection).update(selector, {'$set' => vals})
|
81
|
+
ensure
|
82
|
+
release
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete(collection, doc)
|
87
|
+
begin
|
88
|
+
collection(collection).remove({"_id" => doc["_id"]}, doc)
|
89
|
+
ensure
|
90
|
+
release
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def prepare_value(type, value)
|
95
|
+
return value if value.nil?
|
96
|
+
case type.name
|
97
|
+
when 'Time'
|
98
|
+
value = value.utc
|
99
|
+
when 'DateTime'
|
100
|
+
value = value.to_local_time.utc.to_time
|
101
|
+
when 'Date'
|
102
|
+
value = value.to_gm_time.utc
|
103
|
+
when 'BigDecimal'
|
104
|
+
# FIXME: should multiply on value.attributes[:scale] and store an integer, converting it back on load
|
105
|
+
value = value.to_f
|
106
|
+
end
|
107
|
+
value
|
108
|
+
end
|
109
|
+
|
110
|
+
def value_to_mapper(type, value)
|
111
|
+
if value.class == Time
|
112
|
+
if type.name == 'Date'
|
113
|
+
value = value.to_date
|
114
|
+
elsif type.name == 'DateTime'
|
115
|
+
value = value.to_datetime
|
116
|
+
end
|
117
|
+
return value
|
118
|
+
elsif type.name == 'Fixnum'
|
119
|
+
return value.to_i
|
120
|
+
end
|
121
|
+
return super
|
122
|
+
end
|
123
|
+
|
124
|
+
def find(collection, condition, request, options)
|
125
|
+
options[:fields] = request
|
126
|
+
Spider.logger.debug("Mongodb find #{collection}, #{condition.inspect}")
|
127
|
+
begin
|
128
|
+
res = collection(collection).find(condition, options).to_a
|
129
|
+
ensure
|
130
|
+
release
|
131
|
+
end
|
132
|
+
res = res.map{ |row| keys_to_symbols(row) }
|
133
|
+
res.extend(StorageResult)
|
134
|
+
res.total_rows = res.length # FIXME
|
135
|
+
res
|
136
|
+
end
|
137
|
+
|
138
|
+
def keys_to_symbols(h)
|
139
|
+
sh = {}
|
140
|
+
h.each do |k, v|
|
141
|
+
v = if v.is_a?(Hash)
|
142
|
+
keys_to_symbols(v)
|
143
|
+
elsif v.is_a?(Array)
|
144
|
+
v.map{ |row| keys_to_symbols(row) }
|
145
|
+
else
|
146
|
+
v
|
147
|
+
end
|
148
|
+
#name = k == "_id" ? :id : k.to_sym
|
149
|
+
name = k.to_sym
|
150
|
+
sh[name] = v
|
151
|
+
end
|
152
|
+
sh
|
153
|
+
end
|
154
|
+
|
155
|
+
def drop_db!
|
156
|
+
conn = connection
|
157
|
+
begin
|
158
|
+
conn.drop_database(@db_name)
|
159
|
+
ensure
|
160
|
+
release
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def generate_pk
|
165
|
+
::BSON::ObjectId.new
|
166
|
+
end
|
167
|
+
|
168
|
+
# Mapper extension
|
169
|
+
|
170
|
+
module MapperExtension
|
171
|
+
|
172
|
+
def prepare_condition(condition)
|
173
|
+
cond_hash = {}
|
174
|
+
pks = []
|
175
|
+
condition.each_with_comparison do |k, v, comp|
|
176
|
+
element = model.elements[k.to_sym]
|
177
|
+
name = nil
|
178
|
+
if element.primary_key?
|
179
|
+
if @model.primary_keys.length == 1
|
180
|
+
name = '_id'
|
181
|
+
else
|
182
|
+
raise "Mongo conditions for multiple primary keys are not supported yet"
|
183
|
+
end
|
184
|
+
else
|
185
|
+
name = element.name.to_s
|
186
|
+
end
|
187
|
+
#next unless model.mapper.mapped?(element)
|
188
|
+
if element.model?
|
189
|
+
if element.attributes[:embedded]
|
190
|
+
# TODO
|
191
|
+
else
|
192
|
+
pks = []
|
193
|
+
element.model.primary_keys.each do |ek|
|
194
|
+
kv = v[ek.name]
|
195
|
+
raise "Document mapper can't join #{element.name}: condition #{condition}" unless kv
|
196
|
+
pks << element.mapper.map_condition_value(ek.type, kv)
|
197
|
+
end
|
198
|
+
hash_v = element.model.keys_string(pks)
|
199
|
+
hash_v = {Mongodb::CONDITION_OPS[comp] => hash_v} unless comp == '='
|
200
|
+
cond_hash[name] = hash_v
|
201
|
+
end
|
202
|
+
else
|
203
|
+
hash_v = map_condition_value(element.type, v)
|
204
|
+
comp ||= '='
|
205
|
+
if comp != '='
|
206
|
+
if comp == 'like' || comp == 'ilike'
|
207
|
+
options = comp == 'ilike' ? Regexp::IGNORECASE : nil
|
208
|
+
parts = hash_v.split('%')
|
209
|
+
parts << "" if hash_v[-1].chr == '%'
|
210
|
+
re_str = parts.map{ |p| p.blank? ? '' : Regexp.quote(p)}.join('.+')
|
211
|
+
hash_v = Regexp.new(re_str, options)
|
212
|
+
else
|
213
|
+
hash_v = {Mongodb::CONDITION_OPS[comp] => hash_v}
|
214
|
+
end
|
215
|
+
end
|
216
|
+
cond_hash[name] = hash_v
|
217
|
+
end
|
218
|
+
end
|
219
|
+
or_conds = []
|
220
|
+
or_conds << cond_hash if condition.conjunction == :or && condition.subconditions.length > 0
|
221
|
+
condition.subconditions.each do |sub|
|
222
|
+
sub_res = self.prepare_condition(sub)
|
223
|
+
if condition.conjunction == :and
|
224
|
+
cond_hash.merge!(sub_res)
|
225
|
+
elsif condition.conjunction == :or
|
226
|
+
or_conds << sub_res
|
227
|
+
end
|
228
|
+
end
|
229
|
+
unless or_conds.empty?
|
230
|
+
cond_hash = { '$or' => or_conds }
|
231
|
+
end
|
232
|
+
cond_hash
|
233
|
+
end
|
234
|
+
|
235
|
+
def prepare_request(request)
|
236
|
+
h = {}
|
237
|
+
request.each do |k, v|
|
238
|
+
element = @model.elements[k.to_sym]
|
239
|
+
next unless element
|
240
|
+
name = element.primary_key? ? '_id' : element.name.to_s
|
241
|
+
if v.is_a?(Spider::Model::Request)
|
242
|
+
sub = prepare_request(v)
|
243
|
+
sub.each do |sk, sv|
|
244
|
+
h["#{name}.#{sk}"] = sv
|
245
|
+
end
|
246
|
+
else
|
247
|
+
h[name] = 1
|
248
|
+
end
|
249
|
+
end
|
250
|
+
h
|
251
|
+
end
|
252
|
+
|
253
|
+
def fetch(query)
|
254
|
+
condition = prepare_condition(query.condition)
|
255
|
+
request = prepare_request(query.request)
|
256
|
+
options = {}
|
257
|
+
options[:limit] = query.limit if query.limit
|
258
|
+
options[:skip] = query.offset if query.offset
|
259
|
+
if query.order
|
260
|
+
order_array = []
|
261
|
+
query.order.each do |order|
|
262
|
+
order_element, direction = order
|
263
|
+
dir_str = direction == :desc ? 'descending' : 'ascending'
|
264
|
+
order_array << [order_element.to_s, dir_str]
|
265
|
+
end
|
266
|
+
options[:sort] = order_array unless order_array.empty?
|
267
|
+
end
|
268
|
+
res = storage.find(@model.name, condition, request, options)
|
269
|
+
r = res.map{ |row| postprocess_result(row) }
|
270
|
+
r.extend(Storage::StorageResult) # FIXME: avoid doing this twice
|
271
|
+
r.total_rows = res.total_rows
|
272
|
+
r
|
273
|
+
end
|
274
|
+
|
275
|
+
def postprocess_result(h, model=nil)
|
276
|
+
model ||= @model
|
277
|
+
sh = {}
|
278
|
+
h.each do |k, v|
|
279
|
+
if k == :_id
|
280
|
+
pks = model.split_keys_string(v)
|
281
|
+
model.primary_keys.each_with_index do |pk, i|
|
282
|
+
pkval = pks[i]
|
283
|
+
pkval = storage_value_to_mapper(pk.type, pkval)
|
284
|
+
sh[pk.name] = pks[i]
|
285
|
+
end
|
286
|
+
else
|
287
|
+
el = model.elements[k]
|
288
|
+
v = if v.is_a?(Hash)
|
289
|
+
postprocess_result(v, el.model)
|
290
|
+
elsif v.is_a?(Array)
|
291
|
+
v.map{ |row| postprocess_result(row, el.model) }
|
292
|
+
else
|
293
|
+
v
|
294
|
+
end
|
295
|
+
sh[k] = v
|
296
|
+
end
|
297
|
+
end
|
298
|
+
sh
|
299
|
+
end
|
300
|
+
|
301
|
+
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|
306
|
+
|
307
|
+
end; end; end; end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spiderfw/model/storage/base_storage'
|
2
|
+
require 'spiderfw/model/mappers/document_mapper'
|
3
|
+
|
4
|
+
module Spider; module Model; module Storage; module Document
|
5
|
+
|
6
|
+
class DocumentStorage < Storage::BaseStorage
|
7
|
+
|
8
|
+
@capabilities = {
|
9
|
+
:embedding => true,
|
10
|
+
:transactions => false
|
11
|
+
}
|
12
|
+
|
13
|
+
def self.storage_type
|
14
|
+
:document
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the default mapper for the storage.
|
18
|
+
# If the storage subclass contains a MapperExtension module, it will be mixed-in with the mapper.
|
19
|
+
def get_mapper(model)
|
20
|
+
mapper = Spider::Model::Mappers::DocumentMapper.new(model, self)
|
21
|
+
if (self.class.const_defined?(:MapperExtension))
|
22
|
+
mapper.extend(self.class.const_get(:MapperExtension))
|
23
|
+
end
|
24
|
+
return mapper
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate_pk
|
28
|
+
Spider::DataTypes::UUID.auto_value
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end; end; end; end
|