localtower 0.5.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +129 -33
- data/app/assets/stylesheets/application.css +68 -0
- data/app/controllers/localtower/pages_controller.rb +30 -30
- data/app/javascript/application.js +46 -0
- data/app/javascript/components/DarkSelect.js +115 -0
- data/app/javascript/components/ModernTooltip.js +26 -0
- data/app/javascript/components/NewMigrationForm.js +687 -0
- data/app/javascript/components/NewModelForm.js +432 -0
- data/app/javascript/components/data/Stores.js +294 -0
- data/app/views/layouts/localtower/application.html.erb +77 -80
- data/app/views/localtower/_migration.html.erb +30 -0
- data/app/views/localtower/pages/_alert_no_models.html.erb +3 -0
- data/app/views/localtower/pages/migrations.html.erb +25 -87
- data/app/views/localtower/pages/new_migration.html.erb +40 -0
- data/app/views/localtower/pages/new_model.html.erb +21 -0
- data/config/routes.rb +5 -5
- data/lib/localtower/engine.rb +5 -2
- data/lib/localtower/generators/migration.rb +219 -161
- data/lib/localtower/generators/model.rb +59 -26
- data/lib/localtower/generators/service_objects/insert_array.rb +25 -0
- data/lib/localtower/generators/service_objects/insert_defaults.rb +85 -43
- data/lib/localtower/generators/service_objects/insert_foreign_keys.rb +35 -0
- data/lib/localtower/generators/service_objects/insert_indexes.rb +103 -0
- data/lib/localtower/generators/service_objects/insert_nullable.rb +25 -0
- data/lib/localtower/status.rb +4 -2
- data/lib/localtower/tools.rb +31 -23
- data/lib/localtower/version.rb +1 -1
- data/lib/localtower.rb +0 -6
- data/public/com/favicon-64.png +0 -0
- data/public/com/twitter-cover-1.png +0 -0
- data/public/com/twitter-cover-2.png +0 -0
- data/public/fonts/Circular/CircularStd-Black.otf +0 -0
- data/public/fonts/Circular/CircularStd-BlackItalic.otf +0 -0
- data/public/fonts/Circular/CircularStd-Bold.otf +0 -0
- data/public/fonts/Circular/CircularStd-BoldItalic.otf +0 -0
- data/public/fonts/Circular/CircularStd-Book.otf +0 -0
- data/public/fonts/Circular/CircularStd-BookItalic.otf +0 -0
- data/public/fonts/Circular/CircularStd-Light Italic.otf +0 -0
- data/public/fonts/Circular/CircularStd-Light.otf +0 -0
- data/public/fonts/Circular/CircularStd-Medium.otf +0 -0
- data/public/fonts/Circular/CircularStd-MediumItalic.otf +0 -0
- data/public/fonts/Circular/Read Me.txt +5 -0
- data/public/fonts/Circular/www.dfonts.org.url +2 -0
- data/public/javascripts/application.js +30830 -0
- data/public/javascripts/application.js.map +7 -0
- data/public/screenshots/v0.1.1/1_schema.png +0 -0
- data/public/screenshots/v0.1.1/2_models_1.png +0 -0
- data/public/screenshots/v0.1.1/2_models_2.png +0 -0
- data/public/screenshots/v0.1.1/3_relations.png +0 -0
- data/public/screenshots/v0.1.1/4_migrations.png +0 -0
- data/public/screenshots/v0.1.6/1_schema.png +0 -0
- data/public/screenshots/v0.1.6/2_models_1.png +0 -0
- data/public/screenshots/v0.1.6/3_relations.png +0 -0
- data/public/screenshots/v0.1.6/4_migrations.png +0 -0
- data/public/screenshots/v0.1.6/5_capture.png +0 -0
- data/public/screenshots/v1.0.0/migrations.png +0 -0
- data/public/screenshots/v1.0.0/models.png +0 -0
- data/public/screenshots/v1.0.0/new_migration.png +0 -0
- data/public/screenshots/v1.0.0/new_model.png +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.44.30.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.44.42.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.44.54.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.48.21.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.48.28.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.48.51.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.49.09.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.50.04.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.50.11.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.50.19.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.51.47.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.51.48.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.52.02.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.52.18.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.52.26.jpg +0 -0
- data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.52.38.jpg +0 -0
- data/public/screenshots/v2.0.0/migrations.png +0 -0
- data/public/screenshots/v2.0.0/new_migration.png +0 -0
- data/public/screenshots/v2.0.0/new_model.png +0 -0
- data/public/stylesheets/application.css +1179 -0
- data/public/vendor/jquery-3.7.1.min.js +2 -0
- data/public/vendor/lucide.min.js +12 -0
- data/public/vendor/monokai-sublime.css +80 -0
- data/public/vendor/rails-ujs.min.js +8 -0
- data/spec/dummy/Gemfile +1 -3
- data/spec/dummy/Gemfile.lock +140 -111
- data/spec/dummy/config/database.yml +4 -6
- data/spec/dummy/config/environments/development.rb +1 -0
- data/spec/dummy/db/migrate/20241118233214_create_users.rb +9 -0
- data/spec/dummy/db/migrate/20241118233233_add_column_titme_for_user.rb +6 -0
- data/spec/dummy/db/schema.rb +4 -8
- data/spec/dummy/lib/tasks/reset.rake +16 -0
- data/spec/dummy/log/development.log +21437 -4475
- data/spec/dummy/log/localtower.log +586 -139
- data/spec/dummy/log/test.log +716 -0
- data/spec/dummy/test/index.html +38 -0
- data/spec/dummy/tmp/cache/sessions/localtower/726/FE1/_session_id%3A2%3A%3A69d6764784f832ea25700ea2f242210f3f8d94b48912b0f09ffc44311f0376eb +0 -0
- data/spec/dummy/tmp/cache/sessions/localtower/77E/121/_session_id%3A2%3A%3A0b3c1fe7154461ba023ba6c81dd1b999348757880b505f4b082faed263a627f9 +1 -0
- data/spec/dummy/tmp/cache/sessions/localtower/7EB/8A1/_session_id%3A2%3A%3Af88237c1d157546a5dcde894fd6c1410162a8eba318748d4ac573ee75e40df16 +0 -0
- data/spec/dummy/tmp/local_secret.txt +1 -0
- data/spec/dummy/tmp/pids/server.pid +1 -0
- data/spec/factories/migration.rb +87 -66
- data/spec/factories/model.rb +54 -20
- data/spec/lib/localtower/generators/migration_spec.rb +28 -63
- data/spec/lib/localtower/generators/model_spec.rb +96 -24
- data/spec/lib/localtower/generators/service_objects/insert_array_spec.rb +47 -0
- data/spec/lib/localtower/generators/service_objects/insert_defaults_spec.rb +30 -35
- data/spec/lib/localtower/generators/service_objects/insert_foreign_keys_spec.rb +101 -0
- data/spec/lib/localtower/generators/service_objects/insert_indexes_spec.rb +90 -0
- data/spec/lib/localtower/generators/service_objects/insert_nullable_spec.rb +61 -0
- data/spec/lib/localtower/tools_spec.rb +1 -11
- data/spec/spec_helper.rb +10 -6
- metadata +130 -237
- data/app/views/localtower/pages/_migrations.html.erb +0 -57
- data/app/views/localtower/pages/models.html.erb +0 -80
- data/app/views/localtower/pages/schema.html.erb +0 -67
- data/public/css/app.css +0 -104
- data/public/js/app.js +0 -192
- data/public/light-bootstrap-dashboard-master/assets/css/animate.min.css +0 -6
- data/public/light-bootstrap-dashboard-master/assets/css/bootstrap.min.css +0 -5
- data/public/light-bootstrap-dashboard-master/assets/css/demo.css +0 -61
- data/public/light-bootstrap-dashboard-master/assets/css/light-bootstrap-dashboard.css +0 -2789
- data/public/light-bootstrap-dashboard-master/assets/css/pe-icon-7-stroke.css +0 -632
- data/public/light-bootstrap-dashboard-master/assets/fonts/Pe-icon-7-stroke.eot +0 -0
- data/public/light-bootstrap-dashboard-master/assets/fonts/Pe-icon-7-stroke.svg +0 -212
- data/public/light-bootstrap-dashboard-master/assets/fonts/Pe-icon-7-stroke.ttf +0 -0
- data/public/light-bootstrap-dashboard-master/assets/fonts/Pe-icon-7-stroke.woff +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/default-avatar.png +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/face-0.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/face-1.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/face-2.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/face-3.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/face-4.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/face-5.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/face-6.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/face-7.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/faces/tim_vector.jpe +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/favicon.ico +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/loading-bubbles.svg +0 -14
- data/public/light-bootstrap-dashboard-master/assets/img/mask.png +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/new_logo.png +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/sidebar-1.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/sidebar-2.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/sidebar-3.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/sidebar-4.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/sidebar-5.jpg +0 -0
- data/public/light-bootstrap-dashboard-master/assets/img/tim_80x80.png +0 -0
- data/public/light-bootstrap-dashboard-master/assets/js/bootstrap-checkbox-radio-switch.js +0 -502
- data/public/light-bootstrap-dashboard-master/assets/js/bootstrap-notify.js +0 -404
- data/public/light-bootstrap-dashboard-master/assets/js/bootstrap-select.js +0 -438
- data/public/light-bootstrap-dashboard-master/assets/js/bootstrap.min.js +0 -7
- data/public/light-bootstrap-dashboard-master/assets/js/chartist.min.js +0 -9
- data/public/light-bootstrap-dashboard-master/assets/js/demo.js +0 -152
- data/public/light-bootstrap-dashboard-master/assets/js/jquery-1.10.2.js +0 -9789
- data/public/light-bootstrap-dashboard-master/assets/js/light-bootstrap-dashboard.js +0 -179
- data/public/logo-localtower-white-300.png +0 -0
- data/public/logo-localtower-white.png +0 -0
- data/public/logo-localtower.png +0 -0
- data/public/vendor/font-awesome.min.css +0 -4
- data/public/vendor/highlight-js-default.min.css +0 -9
- data/spec/dummy/db/migrate/20221115190039_create_users.rb +0 -13
- data/spec/dummy/db/migrate/20221115193020_change_users.rb +0 -8
- data/spec/dummy/db/migrate/20221115193532_change_users_at1668540931.rb +0 -5
- data/spec/dummy/db/migrate/20221115193605_change_users_at1668540964.rb +0 -5
- data/spec/dummy/db/migrate/20221115193637_change_users_at1668540996.rb +0 -5
- data/spec/dummy/db/migrate/20221115193642_change_users_at1668541001.rb +0 -5
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/-Y/-YOiiBKqc2UODHFjctm8xc7xFoZaL7zOjWQj6qQ2wyE.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/-d/-dwueM4vmPt8L51S3jeSyg_AjGDcj0GUN6pDpCA1gCg.cache +0 -3
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/0g/0gaJnJQdtd2ACbihXxn8OnjLWlDjnQ_WxfgOpbiLzhg.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/0r/0rFCsCV9kZnEYtZZ6sfig8329OU31bqjecDFqSVank8.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/1J/1J2k_CpnQE3d-PZAQwOVGQALGkta4qVvhdsKjgG0e4Q.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/2p/2pYVH2Z_syqh6ok8QYxJNKxXpx1Iwppf6JGElZI0gpw.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/3W/3WBmqd-2V6q5N-jvbyp-tlcfn3aHYMwBppbOUm7x4qg.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/4K/4KFPlHkhdDW0riGUmlbaR-kmDz6JUnQvY6fwW8qsdaE.cache +0 -3
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/6x/6xMeRWmLpNK_flx6-JA3KazvUxSCxyPxHv9Zm3eC26Q.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/7d/7dNqI_dCDJLJmI1oM4xwFp9nRRNOem-4P4OD7PMyz2E.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/8X/8XquhxVcp5A8QquLtxO8NgKTMJch0eqQmzFmRGIZP6I.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Ah/AhdfXXtU63kXS4TnsH2Vi1yWgVkIEeV8Z8XA68hrNQc.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Bt/BtAePnwLSGw82xUGI7wuhWDfuwarOQVS91YqCsweMcs.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Bx/BxzoG0KxeNLac4xTNeJv3qfeytbNBw58xj2zD-xdbrE.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/CC/CCD0ROPX0yxHwNpVZmuP8ZNtgQpaVCMXpdzC0Wb5n24.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/DS/DS43oxBg6K5PMWLn2mTy_4EnxI03ehHkxpjV7NCi8yM.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Do/Do83AoOat5W-c1g7piDGy2GMmffsY6JY0Qfuh5PY3GM.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/EI/EI0Nxk-VRATWstMuVCVc0_GdYlQ-a0dx6n2g0l3vIik.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/EN/ENhJnzJAU2IK-7aHqubj9N8Jo_UTmjG_VEQqyIkolQ8.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Fc/FcS6VUHN3Bd4pHGqd5NHA8jA4OLwWrU94s3b4GGxX9c.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/G0/G0kukI-r0q0Vbrg6e_jnYJoYcOX8K__h-mwKbCf4twE.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/I1/I1Jw08-mz8xzgrgi6giCzpf1UmzGTSbl4eJEw4DAoJM.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/IV/IVOO1dXBmgjieDk__g57p6aYt0Z3CmfTa32jhegoyko.cache +0 -3
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/JY/JYPmv5WP4wxdI9EKEEPkK_fVtqeSLfmint_5E8fQLQ8.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/MX/MXI3KxaQPZGImSvCNZ_TbQVruWCJ3E0xiVxza1ZCAjM.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/OU/OUoioCqXALK909jXPV3VSyCJIdNC7bsogUfdnRTpc5o.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/PH/PHjtqNLUPAUDiSlu5AbPjlIo20mOGNm0uNjMLhX2NvM.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/RC/RC9vfALY5K634pTeau0BAhTHl7d5_5yA3tM-QTLiKtI.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/RG/RG1PrmlixwaUlG8BV0kcm_3F7OQekxsrLYjBdf403-k.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Ut/UtoMO6n6FHTpRCGk9VfxlfTI2Ao2GYJ_6kMzx3B9VH8.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/VE/VExnbpDk3LxYdPk3htUrZQXPI8NK_zlKtSFfVXJlxU4.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Wm/WmKTjykiU-Tx_Faf5zduEeEQ-DozAs5omKToM2l1cZM.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/X-/X-KjhDPd0nI155N_FaxFSgaOiYo0_ytqlmkBlLM7ayw.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/XX/XXVhj-O91tJ5c8pz7DQlTABOv8TIRVg5haw9VOq9HuI.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/YC/YCiifo5NCMwDChFqYFiV4EaYEx8hy3Efle1PsGbIdak.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Ya/YayMISAqD-Y3vBFywwKrXbUovGf5o77HUF5s8mnQgO0.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Zl/Zl-NEb0aDLmZ9gN4gdY1OYlbUXD4JhkFY_y23m55zmo.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/_h/_hnjPptBeD3GP5B0iJR6pvyVkiMiq-o2TxaYmGf9KJo.cache +0 -3
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/_p/_poEF6QbTPYJiQCFGoXxIXjmvcn6T0I87ElzJGHguk0.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/aa/aaSj2zt8ddc87nZqTpOI9gRCKVnoalXKFBww7t4t3Kg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/bZ/bZHWUkrOLp0WM_Ogo36Qjt4cxDt-rOFgtcj4LNB-BVE.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/cP/cPSNG_663TNT944Rke919luRS6FtpMwVc_7aDph645w.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/ce/ceq8fcZGIoqWrCl9vrCRrywEdx42iy9PrGG9CwFSIF4.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/cl/cljhP0Jc018nLnG1rpdg-FUf6mlIqrQYvXTNXTNG9Bw.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/dm/dmod3fTZdoKso2FGM5RTQtb4kTB6vywsiXLWDygYFN4.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/dy/dySDGcUTqlKx2MTvOmIEP-WzhyhCfU5xhN9qgxbz3rI.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/gQ/gQYdmEzbLjTcFCnsfzXzEmeminOchF263snAk3IvXM0.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/gh/ghvuMAqccBGljlmEaI3Gt5tH5rEg6hseKYMYfRMkHdY.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/gt/gt8QC7k92A4hXA3HlCpQulW73tqd6x63I3uT-YrGMj0.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/hf/hfVg-y7dPSQKbb7V3I7M5w7IpOhDiIB2H31d2tmbZMU.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/iF/iFLwyhZIu1Jxm77NUT2qWeTDMmyELW4U85t9rGE_KVg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/kF/kFlIcBBnSyKE00OjpM90pqSn93mLMUv9esz86nrO-Cs.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/ma/MazNt_5OaYexRuZnccZZ_7AONlxn1a4W3KdWyHyBdws.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/ma/ma3w08gnDTeqwY2-C9BlToxA6-AS8bvXlu-nBiz0UYs.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/n_/n_xYqQYhwEMQknb3jFQnjlxxBE9TzMNHCdJ-bEyZFIw.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/nx/nxTv3sKVUQZADJyM3dPaVmUA78MIsMLD_K279yN_GsI.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/pv/pv6tV3CDkIAmLXdU8EPLlNEkXAKJPufVD4VP30o4fWo.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/qP/qPmv5snMrDw830S6hSICDcnIy7kVEWoFKXhGKT38lG4.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/sY/sYvTb1uPWWmnHJNXKuW_xSco-aUb-rN2f0J35zSIzuc.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/su/suQ_jjDxRiIn4VEqFJYKaBWJILaeGKBvoTv49XNX0vo.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/u8/u8IrW5IIQ7espwk2Vpk23zheL9YZA0tnbKq9X7E-WA0.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/wh/whzETExjcZCkn4msasD2aylgfhfpKPZrNxTkY-SOIDg.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7PYh8DJvPykcEqpVab2vcY9-GFz-3cqtoMlRAu94Uc.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/y6/y6oxsJD3pAY9ph1_5M-77uiEjTVw8BheLZNygCKPm1g.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/yH/yHZ-a1J23ZCf2n5mEHINMz23Iec2cLGTKauW7k4yGTE.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/z7/z7KfUWYoSaGq8tQ5mbHwyfXyT3Pa4FWKJswHcIdJuds.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/zu/zuExWc5WHxeOUPZUKHl9a9ZRmN50g7jMOD28macn6M0.cache +0 -0
- data/spec/lib/localtower/generators/relation_spec.rb +0 -65
@@ -0,0 +1,21 @@
|
|
1
|
+
<% content_for :title do %>New Model<% end %>
|
2
|
+
<div>
|
3
|
+
<%= form_tag models_path, class: "" do %>
|
4
|
+
<div class="flex flex-col gap-2">
|
5
|
+
<div class="block text-localtower-100">Model name <span class="text-localtower-400">(required)</span></div>
|
6
|
+
<div class="w-80">
|
7
|
+
<input autocomplete="off" type="text" data-selector="modelName" name="model[model_name]" class="px-2 py-1.5 rounded bg-localtower-600 border border-localtower-500 inline-block w-full outline-none focus:border-localtower-400 transition-colors text-localtower-100 placeholder:italic placeholder:text-localtower-450 focus:placeholder:text-localtower-600" placeholder="Ex: User" required>
|
8
|
+
</div>
|
9
|
+
<input type="hidden" id="form_attributes" name="model[attributes]">
|
10
|
+
</div>
|
11
|
+
<div class="py-4 flex flex-col gap-2">
|
12
|
+
<label class="block text-localtower-100">Columns</label>
|
13
|
+
<div id="react-container-new-model"></div>
|
14
|
+
</div>
|
15
|
+
<div>
|
16
|
+
<button type="submit" value="true" class="px-3 py-1.5 rounded-md bg-green-800 text-localtower-100 border border-green-700 inline-block outline-none hover:border-green-500 hover:bg-green-700 hover:text-white active:opacity-60 transition-colors text-md">
|
17
|
+
Generate Model
|
18
|
+
</button>
|
19
|
+
</div>
|
20
|
+
<% end %>
|
21
|
+
</div>
|
data/config/routes.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
Localtower::Engine.routes.draw do
|
2
|
+
get 'migrations/new', to: 'pages#new_migration', as: :new_migration
|
2
3
|
get 'migrations', to: 'pages#migrations', as: :migrations
|
3
4
|
post 'migrations', to: 'pages#post_migrations'
|
4
5
|
|
5
|
-
get 'models', to: 'pages#
|
6
|
+
get 'models/new', to: 'pages#new_model', as: :new_model
|
6
7
|
post 'models', to: 'pages#post_models'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
post 'actions', to: 'pages#post_actions', as: 'actions'
|
9
|
+
post 'actions', to: 'pages#post_actions', as: :actions
|
10
|
+
post 'rm_file', to: 'pages#rm_file', as: :rm_file
|
11
11
|
|
12
|
-
root :to => redirect('models')
|
12
|
+
root :to => redirect('models/new')
|
13
13
|
end
|
data/lib/localtower/engine.rb
CHANGED
@@ -2,8 +2,11 @@ module Localtower
|
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
isolate_namespace Localtower
|
4
4
|
|
5
|
-
initializer '
|
6
|
-
app.middleware.use ::
|
5
|
+
initializer 'localtower.add_static_assets', before: :build_middleware_stack do |app|
|
6
|
+
app.config.middleware.use Rack::Deflater
|
7
|
+
app.config.middleware.use ::ActionDispatch::Static, "#{root}/public"
|
8
|
+
# Later: have a better assets pipeline to be able to version and cache assets forever
|
9
|
+
# app.config.middleware.use ::ActionDispatch::Static, "#{root}/public", headers: { "Cache-Control" => "public, max-age=31536000" }
|
7
10
|
end
|
8
11
|
end
|
9
12
|
end
|
@@ -1,120 +1,115 @@
|
|
1
|
+
#
|
2
|
+
# @see https://github.com/rails/rails/blob/main/activerecord/lib/active_record/migration.rb
|
3
|
+
# @see https://github.com/rails/rails/blob/main/activerecord/lib/active_record/migration/command_recorder.rb
|
4
|
+
# @see https://api.rubyonrails.org/v7.2.1/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html
|
5
|
+
#
|
1
6
|
module Localtower
|
2
7
|
module Generators
|
3
8
|
class ThorGeneratorMigration < Thor
|
9
|
+
SPACE_PADDING = " "
|
10
|
+
|
4
11
|
include Thor::Base
|
5
12
|
include Thor::Actions
|
6
13
|
|
7
14
|
no_commands do
|
8
|
-
# data = {last_migration_file: "", column_type: "", table_name: "", column: "", nullable: true, index: true}
|
9
15
|
def migration_add_column(data)
|
10
|
-
|
16
|
+
raise "No table name provided" if data['table_name'].blank?
|
17
|
+
raise "No attribute name provided" if data['column_name'].blank?
|
11
18
|
|
12
19
|
# Special case for array
|
13
|
-
if %w
|
14
|
-
line = "
|
15
|
-
line << ", default: []"
|
20
|
+
if %w[array].include?(data["column_type"])
|
21
|
+
line = "#{SPACE_PADDING}add_column :#{data['table_name']}, :#{data['column_name']}, :string"
|
22
|
+
line << ", default: #{data['default']}" if data['default'].present?
|
16
23
|
line << ", array: true"
|
17
|
-
|
18
|
-
# Add an gin inde as well:
|
19
|
-
line << "\n"
|
20
|
-
line << " add_index :#{data['table_name']}, :#{data['column']}, using: :gin"
|
21
24
|
else
|
22
|
-
line = "
|
25
|
+
line = "#{SPACE_PADDING}add_column :#{data['table_name']}, :#{data['column_name']}, :#{data['column_type']}"
|
23
26
|
line << ", default: #{data['default']}" if data['default'].present?
|
24
|
-
line << ", null: false" if
|
25
|
-
line << ", index: true" if data['index'] == true
|
27
|
+
line << ", null: false" if data['nullable'] == false
|
26
28
|
end
|
27
29
|
|
28
30
|
line << "\n"
|
29
31
|
|
30
32
|
inject_in_migration(file, line)
|
33
|
+
|
34
|
+
if data["index"].present?
|
35
|
+
migration_add_index_to_column(data)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
39
|
def migration_remove_column(data)
|
34
|
-
|
40
|
+
raise "No table name provided" if data['table_name'].blank?
|
41
|
+
raise "No attribute name provided" if data['column_name'].blank?
|
35
42
|
|
36
|
-
line = "
|
43
|
+
line = "#{SPACE_PADDING}remove_column :#{data['table_name']}, :#{data['column_name']}\n"
|
37
44
|
|
38
45
|
inject_in_migration(file, line)
|
39
46
|
end
|
40
47
|
|
41
48
|
def migration_rename_column(data)
|
42
|
-
|
49
|
+
raise "No table name provided" if data['table_name'].blank?
|
50
|
+
raise "No attribute name provided" if data['column_name'].blank?
|
51
|
+
raise "No new attribute name provided" if data['new_column_name'].blank?
|
43
52
|
|
44
|
-
line = "
|
53
|
+
line = "#{SPACE_PADDING}rename_column :#{data['table_name']}, :#{data['column_name']}, :#{data['new_column_name']}\n"
|
45
54
|
|
46
55
|
inject_in_migration(file, line)
|
47
56
|
end
|
48
57
|
|
49
58
|
def migration_change_column_type(data)
|
50
|
-
|
59
|
+
raise "No table name provided" if data['table_name'].blank?
|
60
|
+
raise "No attribute name provided" if data['column_name'].blank?
|
61
|
+
raise "No new attribute type provided" if data['new_column_type'].blank?
|
51
62
|
|
52
|
-
line = "
|
63
|
+
line = "#{SPACE_PADDING}change_column :#{data['table_name']}, :#{data['column_name']}, :#{data['new_column_type']}\n"
|
53
64
|
|
54
65
|
inject_in_migration(file, line)
|
55
66
|
end
|
56
67
|
|
57
68
|
def migration_add_index_to_column(data)
|
58
|
-
|
69
|
+
raise "No table name provided" if data['table_name'].blank?
|
70
|
+
raise "No attribute name provided" if data['column_name'].blank?
|
71
|
+
raise "No index provided" if data['index'].blank?
|
59
72
|
|
60
|
-
line = "
|
73
|
+
line = "#{SPACE_PADDING}add_index :#{data['table_name']}, :#{data['column_name']}\n"
|
61
74
|
|
62
75
|
inject_in_migration(file, line)
|
63
|
-
end
|
64
|
-
|
65
|
-
# def migration_add_index_to_column_combined(data)
|
66
|
-
# file = data["last_migration_file"]
|
67
|
-
# attr_names = data["column"].split(",")
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
77
|
+
# Custom options:
|
78
|
+
params = [data]
|
79
|
+
.select { |attr| attr["index"].present? }
|
80
|
+
.each_with_object([]) do |attr, arr|
|
81
|
+
arr << Hash[attr['column_name'],
|
82
|
+
{ "using" => attr['index'], "algorithm" => attr['index_algorithm'], "unique" => attr['unique'] }]
|
83
|
+
end
|
84
|
+
::Localtower::Generators::ServiceObjects::InsertIndexes.new(params).call
|
85
|
+
end
|
76
86
|
|
77
87
|
def migration_remove_index_to_column(data)
|
78
|
-
|
88
|
+
raise "No table name provided" if data['table_name'].blank?
|
89
|
+
raise "No index_name provided" if data['index_name'].blank?
|
79
90
|
|
80
|
-
line = "
|
91
|
+
line = "#{SPACE_PADDING}remove_index :#{data['table_name']}, name: :#{data['index_name']}\n"
|
81
92
|
|
82
93
|
inject_in_migration(file, line)
|
83
94
|
end
|
84
95
|
|
85
96
|
def migration_belongs_to(data)
|
86
|
-
|
87
|
-
|
88
|
-
line = " add_reference :#{data["table_name"]}, :#{data["column"]}, foreign_key: true, index: true\n"
|
89
|
-
|
90
|
-
inject_in_migration(file, line)
|
97
|
+
raise "No table name provided" if data['table_name'].blank?
|
98
|
+
raise "No attribute name provided" if data['column_name'].blank?
|
91
99
|
|
92
|
-
|
93
|
-
after = /class #{data["table_name"].camelize.singularize} < ApplicationRecord\n/
|
94
|
-
line1 = " belongs_to :#{data["column"].singularize.underscore}\n"
|
100
|
+
line = "#{SPACE_PADDING}add_reference :#{data['table_name']}, :#{data['column_name']}"
|
95
101
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
file = "#{Rails.root}/app/models/#{data["column"].underscore.singularize}.rb"
|
100
|
-
after = /class #{data["column"].camelize.singularize} < ApplicationRecord\n/
|
101
|
-
line1 = " has_many :#{data["table_name"].pluralize.underscore}\n"
|
102
|
-
|
103
|
-
::Localtower::Tools::ThorTools.new.insert_after_word(file, after, line1)
|
104
|
-
end
|
105
|
-
|
106
|
-
def migration_create_table(data)
|
107
|
-
file = data["last_migration_file"]
|
108
|
-
|
109
|
-
line = " create_table :#{data["table_name"]}\n"
|
102
|
+
line << ", foreign_key: true" if data['foreign_key'].present?
|
103
|
+
line << ", index: true"
|
104
|
+
line << "\n"
|
110
105
|
|
111
106
|
inject_in_migration(file, line)
|
112
107
|
end
|
113
108
|
|
114
109
|
def migration_drop_table(data)
|
115
|
-
|
110
|
+
raise "No table name provided" if data['table_name'].blank?
|
116
111
|
|
117
|
-
line = "
|
112
|
+
line = "#{SPACE_PADDING}drop_table :#{data['table_name']}\n"
|
118
113
|
|
119
114
|
inject_in_migration(file, line)
|
120
115
|
end
|
@@ -122,133 +117,196 @@ module Localtower
|
|
122
117
|
private
|
123
118
|
|
124
119
|
def inject_in_migration(file, line)
|
125
|
-
inject_into_file(file, line,
|
120
|
+
inject_into_file(file, line, before: " end\nend")
|
121
|
+
end
|
122
|
+
|
123
|
+
def file
|
124
|
+
Localtower::Tools.last_migration_pending
|
126
125
|
end
|
127
126
|
end
|
128
127
|
end
|
129
128
|
|
130
129
|
class Migration
|
131
|
-
TYPES =
|
130
|
+
TYPES = [
|
131
|
+
{
|
132
|
+
name: "string",
|
133
|
+
example: "'foo'",
|
134
|
+
},
|
135
|
+
{
|
136
|
+
name: "text",
|
137
|
+
example: "'long foo'",
|
138
|
+
},
|
139
|
+
{
|
140
|
+
name: "datetime",
|
141
|
+
example: "2024-07-22 12:28:31.487318",
|
142
|
+
},
|
143
|
+
{
|
144
|
+
name: "date",
|
145
|
+
example: "2024-09-24",
|
146
|
+
},
|
147
|
+
{
|
148
|
+
name: "uuid",
|
149
|
+
example: "'860f5e00-0000-0000-0000-000000000000'",
|
150
|
+
},
|
151
|
+
{
|
152
|
+
name: "integer",
|
153
|
+
example: "123",
|
154
|
+
},
|
155
|
+
{
|
156
|
+
name: "bigint",
|
157
|
+
example: "123",
|
158
|
+
},
|
159
|
+
{
|
160
|
+
name: "float",
|
161
|
+
example: "30.12",
|
162
|
+
},
|
163
|
+
{
|
164
|
+
name: "numeric",
|
165
|
+
example: "30.12",
|
166
|
+
},
|
167
|
+
{
|
168
|
+
name: "decimal",
|
169
|
+
example: "30.12",
|
170
|
+
},
|
171
|
+
{
|
172
|
+
name: "json",
|
173
|
+
example: "{\"foo\": \"bar\"}",
|
174
|
+
},
|
175
|
+
{
|
176
|
+
name: "jsonb",
|
177
|
+
example: "{\"foo\": \"bar\"}",
|
178
|
+
},
|
179
|
+
{
|
180
|
+
name: "binary",
|
181
|
+
example: "01010001",
|
182
|
+
},
|
183
|
+
{
|
184
|
+
name: "boolean",
|
185
|
+
example: "true/false",
|
186
|
+
},
|
187
|
+
{
|
188
|
+
name: "array",
|
189
|
+
example: "[1, 2, 3]",
|
190
|
+
},
|
191
|
+
{
|
192
|
+
name: "blob",
|
193
|
+
example: "x3F7F2A9",
|
194
|
+
},
|
195
|
+
{
|
196
|
+
name: "references",
|
197
|
+
example: "MyModel",
|
198
|
+
}
|
199
|
+
]
|
200
|
+
|
132
201
|
ACTIONS = [
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
202
|
+
{
|
203
|
+
name: "add_column",
|
204
|
+
label: "Add column",
|
205
|
+
example: "add_column :users, :name, :string",
|
206
|
+
},
|
207
|
+
{
|
208
|
+
name: "add_index_to_column",
|
209
|
+
label: "Add index",
|
210
|
+
example: "add_index :users, :name",
|
211
|
+
},
|
212
|
+
{
|
213
|
+
name: "belongs_to",
|
214
|
+
label: "Add reference",
|
215
|
+
example: "add_reference :posts, :user",
|
216
|
+
},
|
217
|
+
{
|
218
|
+
name: "remove_index_to_column",
|
219
|
+
label: "Remove index",
|
220
|
+
example: "remove_index :users, :name",
|
221
|
+
},
|
222
|
+
{
|
223
|
+
name: "remove_column",
|
224
|
+
label: "Remove column",
|
225
|
+
example: "remove_column :users, :name",
|
226
|
+
},
|
227
|
+
{
|
228
|
+
name: "change_column_type",
|
229
|
+
label: "Change column type",
|
230
|
+
example: "change_column :users, :name, :string",
|
231
|
+
},
|
232
|
+
{
|
233
|
+
name: "rename_column",
|
234
|
+
label: "Rename column",
|
235
|
+
example: "rename_column :users, :name, :new_name",
|
236
|
+
},
|
237
|
+
{
|
238
|
+
name: "drop_table",
|
239
|
+
label: "Drop table",
|
240
|
+
example: "drop_table :users",
|
241
|
+
}
|
145
242
|
]
|
146
243
|
|
147
244
|
# @opts =
|
148
|
-
def initialize(
|
245
|
+
def initialize(migrations, migration_name = nil)
|
149
246
|
@thor = ThorGeneratorMigration.new
|
150
|
-
@opts = JSON[opts.to_json]
|
151
|
-
end
|
152
247
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
model_names = @opts['migrations'].map { |line| line['table_name'].camelize }.join
|
157
|
-
|
158
|
-
cmd = "Change#{model_names}#{@opts['migration_name']}At#{Time.now.to_i}"
|
159
|
-
::Localtower::Tools.perform_migration(cmd, true)
|
160
|
-
|
161
|
-
@opts['migrations'].each do |action_line|
|
162
|
-
next unless action_line['action'].present?
|
163
|
-
|
164
|
-
# table_name = action_line['table_name']
|
165
|
-
# column = action_line['column']
|
166
|
-
# index = action_line['index']
|
167
|
-
# default = action_line['default']
|
168
|
-
# null = action_line['null']
|
169
|
-
# unique = action_line['unique']
|
170
|
-
# column_type = action_line['column_type']
|
171
|
-
# new_column_type = action_line['new_column_type']
|
172
|
-
# new_column_name = action_line['new_column_name']
|
173
|
-
action_line["last_migration_file"] = last_migration_file
|
174
|
-
|
175
|
-
{
|
176
|
-
'add_column' => -> { add_column(action_line) },
|
177
|
-
'remove_column' => -> { remove_column(action_line) },
|
178
|
-
'rename_column' => -> { rename_column(action_line) },
|
179
|
-
'change_column_type' => -> { change_column_type(action_line) },
|
180
|
-
'add_index_to_column' => -> { add_index_to_column(action_line) },
|
181
|
-
'belongs_to' => -> { belongs_to(action_line) },
|
182
|
-
'remove_index_to_column' => -> { remove_index_to_column(action_line) },
|
183
|
-
'create_table' => -> { create_table(action_line) },
|
184
|
-
'drop_table' => -> { drop_table(action_line) }
|
185
|
-
}[action_line['action'].downcase].call
|
186
|
-
end
|
187
|
-
|
188
|
-
if @opts['run_migrate']
|
189
|
-
run_migration_or_nil
|
190
|
-
end
|
248
|
+
# stringify keys:
|
249
|
+
@migrations = JSON[migrations.to_json]
|
250
|
+
@migration_name = migration_name
|
191
251
|
end
|
192
252
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
#
|
199
|
-
|
253
|
+
# const DEFAULT_LINE = {
|
254
|
+
# model_name: MODELS[0] ? MODELS[0].value : '',
|
255
|
+
# table_name: MODELS[0] ? MODELS[0].table_name : '',
|
256
|
+
# action_name: 'add_column',
|
257
|
+
# column_type: 'string',
|
258
|
+
# column_name: '',
|
259
|
+
# new_column_name: '',
|
260
|
+
# new_column_type: '',
|
261
|
+
# default: '',
|
262
|
+
# unique: false,
|
263
|
+
# foreign_key: false,
|
264
|
+
# index: '',
|
265
|
+
# index_algorithm: 'default',
|
266
|
+
# index_name: '',
|
267
|
+
# nullable: true
|
268
|
+
# };
|
200
269
|
|
201
|
-
def
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
end
|
212
|
-
|
213
|
-
def change_column_type(data)
|
214
|
-
@thor.migration_change_column_type(data)
|
215
|
-
end
|
270
|
+
def run
|
271
|
+
if Localtower::Tools.pending_migrations.any?
|
272
|
+
# raise "There is a pending migration. You can't generate a migration until the pending migration is committed."
|
273
|
+
else
|
274
|
+
migration_name_final = if @migration_name.present?
|
275
|
+
@migration_name
|
276
|
+
else
|
277
|
+
action_names = migrations.map { |line| line['action_name'].camelize }.uniq.take(1).join
|
278
|
+
model_names = migrations.map { |line| line['model_name'].camelize }.uniq.take(2).join
|
279
|
+
column_names = migrations.map { |line| (line['column_name'].presence || "").camelize }.uniq.take(2).join
|
216
280
|
|
217
|
-
|
218
|
-
|
219
|
-
end
|
281
|
+
"#{action_names}#{column_names}For#{model_names}"
|
282
|
+
end
|
220
283
|
|
221
|
-
|
222
|
-
|
223
|
-
data['column_type'] = "references"
|
284
|
+
::Localtower::Tools.perform_migration(migration_name_final)
|
285
|
+
end
|
224
286
|
|
225
|
-
|
226
|
-
|
287
|
+
migrations.each do |action_line|
|
288
|
+
next if action_line['action_name'].blank?
|
227
289
|
|
228
|
-
|
229
|
-
@thor.migration_remove_index_to_column(data)
|
230
|
-
end
|
290
|
+
# action_line['table_name'] = action_line['model_name'].pluralize.underscore
|
231
291
|
|
232
|
-
|
233
|
-
|
234
|
-
|
292
|
+
proc_var = {
|
293
|
+
'add_column' => -> { thor.migration_add_column(action_line) },
|
294
|
+
'remove_column' => -> { thor.migration_remove_column(action_line) },
|
295
|
+
'rename_column' => -> { thor.migration_rename_column(action_line) },
|
296
|
+
'change_column_type' => -> { thor.migration_change_column_type(action_line) },
|
297
|
+
'add_index_to_column' => -> { thor.migration_add_index_to_column(action_line) },
|
298
|
+
'belongs_to' => -> { thor.migration_belongs_to(action_line) },
|
299
|
+
'remove_index_to_column' => -> { thor.migration_remove_index_to_column(action_line) },
|
300
|
+
'drop_table' => -> { thor.migration_drop_table(action_line) }
|
301
|
+
}[action_line['action_name']]
|
235
302
|
|
236
|
-
|
237
|
-
@thor.migration_drop_table(data)
|
238
|
-
end
|
303
|
+
raise "No proc found for action_name #{action_line['action_name']}" unless proc_var
|
239
304
|
|
240
|
-
|
241
|
-
if last_migration_changed?
|
242
|
-
::Localtower::Tools.perform_cmd('rake db:migrate')
|
243
|
-
else
|
244
|
-
File.delete(last_migration_file)
|
245
|
-
nil
|
305
|
+
proc_var.call
|
246
306
|
end
|
247
307
|
end
|
248
308
|
|
249
|
-
|
250
|
-
File.readlines(last_migration_file).join != ~ /def change\n end/
|
251
|
-
end
|
309
|
+
attr_reader :thor, :migrations
|
252
310
|
end
|
253
311
|
end
|
254
312
|
end
|
@@ -3,52 +3,85 @@ module Localtower
|
|
3
3
|
class Model
|
4
4
|
def initialize(opts)
|
5
5
|
@opts = JSON[opts.to_json] # stringify keys
|
6
|
+
@model_name = @opts['model_name']
|
7
|
+
@attributes = @opts['attributes']
|
8
|
+
|
9
|
+
raise "No model_name provided" if @model_name.blank?
|
10
|
+
raise "No attributes provided" if @attributes.blank?
|
6
11
|
end
|
7
12
|
|
8
|
-
# data = {attributes: "", model_name: ""}
|
9
13
|
def run
|
10
|
-
|
11
|
-
|
14
|
+
attributes_str = parse_attributes.join(" ")
|
15
|
+
cmd = "rails generate model #{model_name.camelize} #{attributes_str} --force"
|
16
|
+
::Localtower::Tools.perform_cmd(cmd)
|
12
17
|
|
13
|
-
|
18
|
+
insert_non_nullable_values
|
19
|
+
insert_default_values
|
20
|
+
insert_array
|
21
|
+
insert_indexes
|
22
|
+
insert_foreign_keys
|
23
|
+
end
|
14
24
|
|
15
|
-
|
16
|
-
str = "#{attribute_data["attribute_name"]}:#{attribute_data["attribute_type"]}"
|
17
|
-
str << ":index" if attribute_data["index"]
|
25
|
+
private
|
18
26
|
|
19
|
-
|
20
|
-
end
|
27
|
+
attr_reader :model_name, :attributes
|
21
28
|
|
22
|
-
|
23
|
-
|
29
|
+
def parse_attributes
|
30
|
+
attributes.map do |attr_hash|
|
31
|
+
[
|
32
|
+
attr_hash['column_name'],
|
33
|
+
# we need this transformation of "array":
|
34
|
+
(attr_hash['column_type'] == 'array' ? 'string' : attr_hash['column_type']),
|
35
|
+
attr_hash["index"].present? ? 'index' : nil
|
36
|
+
].compact.join(':')
|
37
|
+
end
|
38
|
+
end
|
24
39
|
|
25
|
-
|
40
|
+
def insert_array
|
41
|
+
params = attributes
|
42
|
+
.select { |attr| attr['column_type'] == 'array' }
|
43
|
+
.map { |attr| attr['column_name'] }
|
26
44
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
45
|
+
Localtower::Generators::ServiceObjects::InsertArray.new(params).call
|
46
|
+
end
|
30
47
|
|
31
|
-
|
32
|
-
|
48
|
+
def insert_default_values
|
49
|
+
params = attributes
|
50
|
+
.select { |attr| attr['default'].present? }
|
51
|
+
.each_with_object([]) do |attr, arr|
|
52
|
+
arr << Hash[attr['column_name'], attr['default']]
|
33
53
|
end
|
34
54
|
|
35
|
-
|
55
|
+
Localtower::Generators::ServiceObjects::InsertDefaults.new(params).call
|
36
56
|
end
|
37
57
|
|
38
|
-
|
58
|
+
def insert_non_nullable_values
|
59
|
+
params = attributes
|
60
|
+
.select { |attr| attr['nullable'] == false }
|
61
|
+
.map { |attr| attr['column_name'] }
|
39
62
|
|
40
|
-
|
41
|
-
@opts['attributes'].any? { |attr| attr["defaults"].present? }
|
63
|
+
::Localtower::Generators::ServiceObjects::InsertNullable.new(params).call
|
42
64
|
end
|
43
65
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
66
|
+
def insert_indexes
|
67
|
+
params = attributes
|
68
|
+
.select { |attr| attr["index"].present? }
|
69
|
+
.each_with_object([]) do |attr, arr|
|
70
|
+
arr << Hash[attr['column_name'],
|
71
|
+
{ "using" => attr['index'], "algorithm" => attr['index_algorithm'], "unique" => attr['unique'] }]
|
47
72
|
end
|
73
|
+
|
74
|
+
::Localtower::Generators::ServiceObjects::InsertIndexes.new(params).call
|
48
75
|
end
|
49
76
|
|
50
|
-
def
|
51
|
-
|
77
|
+
def insert_foreign_keys
|
78
|
+
params = attributes
|
79
|
+
.each_with_object([]) do |attr, arr|
|
80
|
+
arr << Hash[attr['column_name'],
|
81
|
+
{ "foreign_key" => attr['foreign_key'] }]
|
82
|
+
end
|
83
|
+
|
84
|
+
::Localtower::Generators::ServiceObjects::InsertForeignKeys.new(params).call
|
52
85
|
end
|
53
86
|
end
|
54
87
|
end
|