agile_rails 0.0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +285 -0
  5. data/Rakefile +39 -0
  6. data/agile_rails.gemspec +36 -0
  7. data/app/assets/fonts/ibm-plex-sans-300.woff2 +0 -0
  8. data/app/assets/fonts/ibm-plex-sans-400.woff2 +0 -0
  9. data/app/assets/fonts/ibm-plex-sans-500.woff2 +0 -0
  10. data/app/assets/fonts/ibm-plex-sans-600.woff2 +0 -0
  11. data/app/assets/fonts/ibm-plex-sans-700.woff2 +0 -0
  12. data/app/assets/fonts/ibm-plex-sans-italic.woff2 +0 -0
  13. data/app/assets/images/32px.png +0 -0
  14. data/app/assets/images/throbber.gif +0 -0
  15. data/app/assets/javascripts/agile/agile.js +1489 -0
  16. data/app/assets/javascripts/agile/jquery-migrate.js +702 -0
  17. data/app/assets/javascripts/agile/jquery.bpopup.js +372 -0
  18. data/app/assets/javascripts/agile/jquery.datetimepicker.js +1353 -0
  19. data/app/assets/javascripts/agile/jstree.min.js +6 -0
  20. data/app/assets/javascripts/agile/select-multiple.js +459 -0
  21. data/app/assets/javascripts/agile/some_scripts.js +33 -0
  22. data/app/assets/javascripts/agile.js +22 -0
  23. data/app/assets/javascripts/agile_application.js +22 -0
  24. data/app/assets/javascripts/agile_editor.js +22 -0
  25. data/app/assets/stylesheets/agile/agile.css +1882 -0
  26. data/app/assets/stylesheets/agile/agile_apps.css +149 -0
  27. data/app/assets/stylesheets/agile/jquery.datetimepicker.css +304 -0
  28. data/app/assets/stylesheets/agile/jstree.css +1107 -0
  29. data/app/assets/stylesheets/agile/select-multiple.css +110 -0
  30. data/app/assets/stylesheets/agile/th-bg.png +0 -0
  31. data/app/assets/stylesheets/agile/theme.css +49 -0
  32. data/app/assets/stylesheets/agile.css +21 -0
  33. data/app/assets/stylesheets/agile_application.css +20 -0
  34. data/app/assets/stylesheets/agile_editor.css +19 -0
  35. data/app/controllers/agile_application_controller.rb +735 -0
  36. data/app/controllers/agile_common_controller.rb +345 -0
  37. data/app/controllers/agile_controller.rb +977 -0
  38. data/app/controllers/agile_main_controller.rb +36 -0
  39. data/app/controls/agile_control.rb +120 -0
  40. data/app/controls/agile_report.rb +364 -0
  41. data/app/controls/ar_category_control.rb +39 -0
  42. data/app/controls/ar_help_control.rb +139 -0
  43. data/app/controls/ar_image_control.rb +180 -0
  44. data/app/controls/ar_journal_control.rb +47 -0
  45. data/app/controls/ar_menu_item_control.rb +55 -0
  46. data/app/controls/ar_page_control.rb +64 -0
  47. data/app/controls/ar_poll_result_control.rb +84 -0
  48. data/app/controls/ar_setup_control.rb +62 -0
  49. data/app/controls/belongs_to_control.rb +61 -0
  50. data/app/controls/browse_models_control.rb +98 -0
  51. data/app/controls/settings_form_control.rb +137 -0
  52. data/app/forms/agile_help.yml +112 -0
  53. data/app/forms/agile_menu.yml +140 -0
  54. data/app/forms/agile_report_defaults.yml +39 -0
  55. data/app/forms/all_options.yml +810 -0
  56. data/app/forms/ar_ad.yml +121 -0
  57. data/app/forms/ar_big_table.yml +60 -0
  58. data/app/forms/ar_big_table_value.yml +52 -0
  59. data/app/forms/ar_browse_fields.yml +35 -0
  60. data/app/forms/ar_browse_models.yml +48 -0
  61. data/app/forms/ar_category.yml +73 -0
  62. data/app/forms/ar_category_as_tree.yml +31 -0
  63. data/app/forms/ar_design.yml +75 -0
  64. data/app/forms/ar_filter.yml +52 -0
  65. data/app/forms/ar_folder_permission.yml +56 -0
  66. data/app/forms/ar_folder_rule.yml +48 -0
  67. data/app/forms/ar_gallery.yml +55 -0
  68. data/app/forms/ar_image.yml +126 -0
  69. data/app/forms/ar_image_search.yml +83 -0
  70. data/app/forms/ar_journal.yml +76 -0
  71. data/app/forms/ar_json_ld.yml +56 -0
  72. data/app/forms/ar_key_value.yml +33 -0
  73. data/app/forms/ar_key_value_store.yml +33 -0
  74. data/app/forms/ar_link.yml +60 -0
  75. data/app/forms/ar_menu.yml +67 -0
  76. data/app/forms/ar_menu_item.yml +141 -0
  77. data/app/forms/ar_page.yml +187 -0
  78. data/app/forms/ar_part.yml +91 -0
  79. data/app/forms/ar_permission.yml +52 -0
  80. data/app/forms/ar_permission_rule.yml +40 -0
  81. data/app/forms/ar_piece.yml +106 -0
  82. data/app/forms/ar_policy.yml +64 -0
  83. data/app/forms/ar_policy_rule.yml +42 -0
  84. data/app/forms/ar_policy_rule_nocms.yml +40 -0
  85. data/app/forms/ar_poll.yml +118 -0
  86. data/app/forms/ar_poll_item.yml +78 -0
  87. data/app/forms/ar_poll_result.yml +88 -0
  88. data/app/forms/ar_poll_result_export.yml +35 -0
  89. data/app/forms/ar_removed_url.yml +41 -0
  90. data/app/forms/ar_role.yml +43 -0
  91. data/app/forms/ar_seo.yml +32 -0
  92. data/app/forms/ar_setup.yml +45 -0
  93. data/app/forms/ar_site.yml +149 -0
  94. data/app/forms/ar_steps_template.yml +51 -0
  95. data/app/forms/ar_user.yml +140 -0
  96. data/app/forms/ar_user_role.yml +57 -0
  97. data/app/forms/help/dc_category_as_tree.en +4 -0
  98. data/app/forms/help/dc_category_as_tree.sl +5 -0
  99. data/app/forms/json_ld_schema.yml +168 -0
  100. data/app/helpers/agile_application_helper.rb +1162 -0
  101. data/app/helpers/agile_category_helper.rb +128 -0
  102. data/app/helpers/agile_common_helper.rb +308 -0
  103. data/app/helpers/agile_edit_helper.rb +645 -0
  104. data/app/helpers/agile_helper.rb +509 -0
  105. data/app/helpers/agile_index_helper.rb +677 -0
  106. data/app/helpers/ar_image_helper.rb +128 -0
  107. data/app/models/agile_form_fields/action.rb +61 -0
  108. data/app/models/agile_form_fields/agile_form_field.rb +322 -0
  109. data/app/models/agile_form_fields/belongs_to.rb +112 -0
  110. data/app/models/agile_form_fields/check_box.rb +73 -0
  111. data/app/models/agile_form_fields/comment.rb +62 -0
  112. data/app/models/agile_form_fields/date_picker.rb +104 -0
  113. data/app/models/agile_form_fields/date_select.rb +68 -0
  114. data/app/models/agile_form_fields/datetime_picker.rb +88 -0
  115. data/app/models/agile_form_fields/datetime_select.rb +73 -0
  116. data/app/models/agile_form_fields/file_field.rb +52 -0
  117. data/app/models/agile_form_fields/file_select.rb +69 -0
  118. data/app/models/agile_form_fields/hidden_field.rb +51 -0
  119. data/app/models/agile_form_fields/html_field.rb +69 -0
  120. data/app/models/agile_form_fields/journal_diff.rb +62 -0
  121. data/app/models/agile_form_fields/link_to.rb +69 -0
  122. data/app/models/agile_form_fields/method.rb +66 -0
  123. data/app/models/agile_form_fields/multitext_autocomplete.rb +215 -0
  124. data/app/models/agile_form_fields/number_field.rb +92 -0
  125. data/app/models/agile_form_fields/password_field.rb +63 -0
  126. data/app/models/agile_form_fields/radio_button.rb +95 -0
  127. data/app/models/agile_form_fields/readonly.rb +77 -0
  128. data/app/models/agile_form_fields/select.rb +281 -0
  129. data/app/models/agile_form_fields/submit_tag.rb +58 -0
  130. data/app/models/agile_form_fields/text_area.rb +61 -0
  131. data/app/models/agile_form_fields/text_autocomplete.rb +171 -0
  132. data/app/models/agile_form_fields/text_field.rb +55 -0
  133. data/app/models/agile_form_fields/text_with_select.rb +94 -0
  134. data/app/models/agile_form_fields/tree_select.rb +170 -0
  135. data/app/models/ar_big_table.rb +82 -0
  136. data/app/models/ar_big_table_value.rb +53 -0
  137. data/app/models/ar_category.rb +109 -0
  138. data/app/models/ar_design.rb +116 -0
  139. data/app/models/ar_filter.rb +200 -0
  140. data/app/models/ar_folder_permission.rb +50 -0
  141. data/app/models/ar_folder_rule.rb +47 -0
  142. data/app/models/ar_gallery.rb +53 -0
  143. data/app/models/ar_image.rb +198 -0
  144. data/app/models/ar_internals.rb +60 -0
  145. data/app/models/ar_journal.rb +46 -0
  146. data/app/models/ar_json_ld.rb +131 -0
  147. data/app/models/ar_key_value_store.rb +128 -0
  148. data/app/models/ar_link.rb +48 -0
  149. data/app/models/ar_memory.rb +172 -0
  150. data/app/models/ar_menu.rb +144 -0
  151. data/app/models/ar_menu_item.rb +106 -0
  152. data/app/models/ar_page.rb +74 -0
  153. data/app/models/ar_part.rb +66 -0
  154. data/app/models/ar_permission.rb +180 -0
  155. data/app/models/ar_permission_rule.rb +65 -0
  156. data/app/models/ar_policy.rb +78 -0
  157. data/app/models/ar_policy_rule.rb +65 -0
  158. data/app/models/ar_poll.rb +74 -0
  159. data/app/models/ar_poll_item.rb +47 -0
  160. data/app/models/ar_poll_result.rb +38 -0
  161. data/app/models/ar_removed_url.rb +42 -0
  162. data/app/models/ar_role.rb +84 -0
  163. data/app/models/ar_setup.rb +115 -0
  164. data/app/models/ar_site.rb +68 -0
  165. data/app/models/ar_temp.rb +150 -0
  166. data/app/models/ar_user.rb +72 -0
  167. data/app/models/ar_user_group.rb +38 -0
  168. data/app/models/ar_user_role.rb +54 -0
  169. data/app/models/ar_visit.rb +41 -0
  170. data/app/models/concerns/ar_page_concern.rb +128 -0
  171. data/app/models/concerns/ar_part_concern.rb +48 -0
  172. data/app/models/concerns/ar_piece_concern.rb +48 -0
  173. data/app/models/concerns/ar_policy_rule_concern.rb +87 -0
  174. data/app/models/concerns/ar_seo_concern.rb +66 -0
  175. data/app/models/concerns/ar_site_concern.rb +103 -0
  176. data/app/models/concerns/ar_user_concern.rb +195 -0
  177. data/app/renderers/agile_common_renderer.rb +93 -0
  178. data/app/renderers/agile_renderer.rb +59 -0
  179. data/app/renderers/ar_ad_renderer.rb +219 -0
  180. data/app/renderers/ar_captcha_renderer.rb +113 -0
  181. data/app/renderers/ar_common_renderer.rb +90 -0
  182. data/app/renderers/ar_gallery_renderer.rb +107 -0
  183. data/app/renderers/ar_menu_renderer.rb +195 -0
  184. data/app/renderers/ar_page_renderer.rb +147 -0
  185. data/app/renderers/ar_part_renderer.rb +235 -0
  186. data/app/renderers/ar_piece_renderer.rb +119 -0
  187. data/app/renderers/ar_poll_renderer.rb +272 -0
  188. data/app/views/agile/_edit_stuff.html.erb +57 -0
  189. data/app/views/agile/_form.html.erb +24 -0
  190. data/app/views/agile/_result.html.erb +28 -0
  191. data/app/views/agile/edit.html.erb +13 -0
  192. data/app/views/agile/error.html.erb +2 -0
  193. data/app/views/agile/index.html.erb +14 -0
  194. data/app/views/agile/login.html.erb +19 -0
  195. data/app/views/agile/new.html.erb +12 -0
  196. data/app/views/agile_common/_help.html.erb +18 -0
  197. data/app/views/agile_common/_iframe_edit.html.erb +2 -0
  198. data/app/views/agile_common/paste_clipboard.html.erb +17 -0
  199. data/app/views/layouts/agile.html.erb +17 -0
  200. data/app/views/layouts/content.html.erb +20 -0
  201. data/app/views/models/dump_models.html.erb +47 -0
  202. data/config/initializers/kaminari_patch.rb +56 -0
  203. data/config/locales/agile_de.yml +138 -0
  204. data/config/locales/agile_en.yml +162 -0
  205. data/config/locales/agile_sl.yml +163 -0
  206. data/config/locales/datetimepicker.yml +19 -0
  207. data/config/locales/de.yml +231 -0
  208. data/config/locales/en.yml +13 -0
  209. data/config/locales/kaminari.yml +26 -0
  210. data/config/locales/models_en.yml +1032 -0
  211. data/config/locales/models_sl.yml +1065 -0
  212. data/config/locales/sl.yml +211 -0
  213. data/db/migrate/20240120160001_add_sessions_table.rb +12 -0
  214. data/db/migrate/20240120160002_ar_big_table.rb +17 -0
  215. data/db/migrate/20240120160003_ar_big_table_value.rb +18 -0
  216. data/db/migrate/20240120160004_ar_category.rb +22 -0
  217. data/db/migrate/20240120160005_ar_design.rb +20 -0
  218. data/db/migrate/20240120160006_ar_filter.rb +17 -0
  219. data/db/migrate/20240120160007_ar_gallery.rb +21 -0
  220. data/db/migrate/20240120160008_ar_journal.rb +19 -0
  221. data/db/migrate/20240120160009_ar_key_value_store.rb +11 -0
  222. data/db/migrate/20240120160010_ar_link.rb +19 -0
  223. data/db/migrate/20240120160011_ar_memory.rb +8 -0
  224. data/db/migrate/20240120160012_ar_menu.rb +21 -0
  225. data/db/migrate/20240120160013_ar_menu_item.rb +28 -0
  226. data/db/migrate/20240120160014_ar_page.rb +50 -0
  227. data/db/migrate/20240120160015_ar_part.rb +33 -0
  228. data/db/migrate/20240120160016_ar_permission.rb +16 -0
  229. data/db/migrate/20240120160017_ar_permission_rule.rb +17 -0
  230. data/db/migrate/20240120160018_ar_piece.rb +28 -0
  231. data/db/migrate/20240120160019_ar_policy.rb +21 -0
  232. data/db/migrate/20240120160020_ar_policy_rule.rb +18 -0
  233. data/db/migrate/20240120160021_ar_poll.rb +27 -0
  234. data/db/migrate/20240120160022_ar_poll_item.rb +23 -0
  235. data/db/migrate/20240120160023_ar_poll_result.rb +14 -0
  236. data/db/migrate/20240120160024_ar_removed_url.rb +16 -0
  237. data/db/migrate/20240120160025_ar_role.rb +17 -0
  238. data/db/migrate/20240120160026_ar_site.rb +37 -0
  239. data/db/migrate/20240120160027_ar_temp.rb +11 -0
  240. data/db/migrate/20240120160028_ar_user.rb +42 -0
  241. data/db/migrate/20240120160029_ar_user_group.rb +12 -0
  242. data/db/migrate/20240120160030_ar_user_role.rb +18 -0
  243. data/db/migrate/20240120160031_ar_visit.rb +15 -0
  244. data/db/migrate/20240703016001_ar_setup.rb +16 -0
  245. data/db/migrate/20240703016002_ar_folder_permission.rb +15 -0
  246. data/db/migrate/20240703016003_ar_folder_rule.rb +14 -0
  247. data/db/migrate/20250115000001_ar_image.rb +25 -0
  248. data/lib/agile/configuration.rb +43 -0
  249. data/lib/agile/engine.rb +29 -0
  250. data/lib/agile/version.rb +27 -0
  251. data/lib/agile.rb +282 -0
  252. data/lib/agile_rails.rb +1 -0
  253. data/lib/generators/agile/USAGE +11 -0
  254. data/lib/generators/agile/new_form_generator.rb +369 -0
  255. data/lib/generators/convert_to_ar/convert_to_ar_generator.rb +158 -0
  256. data/lib/tasks/agile_db_clone.rake +132 -0
  257. data/lib/tasks/agile_db_export_to_yaml.rake +37 -0
  258. data/lib/tasks/agile_db_migrate.rake +35 -0
  259. metadata +414 -0
@@ -0,0 +1,11 @@
1
+ Description:
2
+ agile:new_form generator will create Agile Rails form from model description.
3
+ Options:
4
+ --extra: Will create some extra commented code for help default: --no-extra
5
+ --tabs: Will create form entry fields with tabs default: --no-tabs
6
+
7
+ Example:
8
+ rails generate agile:new_form model_name
9
+
10
+ This will create:
11
+ forms/model_name.yml
@@ -0,0 +1,369 @@
1
+ #--
2
+ # Copyright (c) 2024+ Damjan Rems
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Agile
25
+ module Generators
26
+
27
+ # rails g agile_rails:new_form MODEL
28
+ class NewFormGenerator < Rails::Generators::NamedBase # :nodoc:
29
+
30
+ source_root File.expand_path('../templates', __FILE__)
31
+
32
+ class_option :tabs, type: :boolean, default: false, description: "Create tabbed form"
33
+ class_option :extra, type: :boolean, default: false, description: "Add some extra commented code to the form"
34
+
35
+ def self.banner #:nodoc:
36
+ <<-BANNER.chomp
37
+ rails g agile_rails:new_form MODEL [options]
38
+
39
+ Generates Agile Rails form for specified Rails model
40
+
41
+ - options: --tabs will create form entry fields with tabs (default: --no-tabs)
42
+ --extra will create some extra commented code for help (default: --no-extra)
43
+ BANNER
44
+ end
45
+
46
+ ###########################################################################
47
+ # Will create output and save it to form filename.
48
+ ###########################################################################
49
+ def create_form_file
50
+ @file_name = file_name.underscore
51
+ @tabs = options[:tabs]
52
+ pp options
53
+ @extra = options[:extra]
54
+ begin
55
+ @model = @file_name.classify.constantize
56
+ rescue Exception => e
57
+ pp ([e.message] + e.backtrace).join($/)
58
+ @model = nil
59
+ end
60
+ return (pp "Error loading #{file_name.classify} model! Aborting.") if @model.nil?
61
+
62
+ form = top_level_options +
63
+ index_options +
64
+ data_set_options +
65
+ form_top_options +
66
+ form_fields_options +
67
+ localize_options
68
+ create_file "app/forms/#{@file_name}.yml", form
69
+ end
70
+
71
+ private
72
+ ###########################################################################
73
+ #
74
+ ###########################################################################
75
+ def top_level_options
76
+ extra = <<EOT
77
+ #title: Alternative title
78
+ #extend: extend
79
+ #controls: controls_file
80
+ #readonly: true
81
+ #permissions:
82
+ # can_view: role_name
83
+ EOT
84
+
85
+ <<EOT
86
+ # Form for #{file_name}
87
+ table: #{file_name}
88
+ #{extra if @extra}
89
+ EOT
90
+ end
91
+
92
+ ###########################################################################
93
+ #
94
+ ###########################################################################
95
+ def index_options
96
+ extra = <<EOT
97
+
98
+ # actions:
99
+ # 10:
100
+ # type: link
101
+ # controller: controller_name
102
+ # action: action_name
103
+ # table: table_name
104
+ # form_name: form_name
105
+ EOT
106
+
107
+ <<EOT
108
+ index:
109
+ filter: some_id as text_field
110
+ actions: standard
111
+ #{extra if @extra}
112
+ EOT
113
+ end
114
+
115
+ ###########################################################################
116
+ #
117
+ ###########################################################################
118
+ def data_set_options
119
+ extra = <<EOT
120
+ # filter: controls_filter
121
+ # per_page: 10
122
+
123
+ # actions:
124
+ # 10:
125
+ # type: link
126
+ # controller: controller_name
127
+ # action: action_name
128
+ # table: table_name
129
+ # form_name: form_name
130
+ # target: target
131
+ # method: (get),put,post
132
+
133
+ EOT
134
+
135
+ <<EOT
136
+ data_set:
137
+ actions: standard
138
+ #{extra if @extra}
139
+ #
140
+ # Choose columns from
141
+ # #{@model.attribute_names.join(',')}
142
+ columns:
143
+ 10:
144
+ name: #{@model.attribute_names[1]}
145
+ 20:
146
+ name: #{@model.attribute_names[2]}
147
+ 30:
148
+ name: #{@model.attribute_names[3]}
149
+ 40:
150
+ name: #{@model.attribute_names[4]}
151
+
152
+ # style: 'color: red'
153
+ # width: 10%
154
+ # align: right
155
+ # format: '%d.%m.%Y'
156
+ # format: N2
157
+ # sort: n
158
+ # eval: agile_name_for_id,ar_user,name
159
+ # eval: agile_icon_for_boolean
160
+
161
+ EOT
162
+ end
163
+
164
+ ###########################################################################
165
+ #
166
+ ###########################################################################
167
+ def form_top_options
168
+ extra = <<EOT
169
+
170
+ # title:
171
+ # field: name
172
+ # edit: Title for edit
173
+ # show: Title for show
174
+
175
+ #
176
+ # actions:
177
+ # 1:
178
+ # type: ajax
179
+ # controller: ppk
180
+ # action: prepare_document
181
+ # method: (get),put,post
182
+ # caption: Prepare document
183
+ # 2:
184
+ # type: script
185
+ # caption: Cancle
186
+ # js: parent.reload();
187
+ # 3:
188
+ # type: submit
189
+ # caption: Send
190
+ # params:
191
+ # before-save: send_mail
192
+ # after-save: return_to parent.reload
193
+
194
+ EOT
195
+
196
+ <<EOT
197
+ form:
198
+ actions: standard
199
+ #{extra if @extra}
200
+ EOT
201
+ end
202
+
203
+ ###########################################################################
204
+ #
205
+ ###########################################################################
206
+ def form_field(attribute, index, offset)
207
+ field, value = attribute
208
+ helper = I18n.t("helpers.label.#{@file_name}.choices4_#{field}")
209
+ type, eval = 'select', ''
210
+ if helper.match( /Translation missing/i )
211
+ if field[-3, 3] == '_id'
212
+ eval = "choices: eval agile_choices_for('#{field[0, field.size - 3]}','description_field_name','id')\n"
213
+ else
214
+ type = if value.is_a?(TrueClass) || value.is_a?(FalseClass)
215
+ 'check_box'
216
+ else
217
+ 'text_field'
218
+ end
219
+ end
220
+ end
221
+ yml = ' '*offset
222
+ yml << "#{index}:\n"
223
+ offset += 2
224
+
225
+ yml << ' '*offset + "name: #{field}\n"
226
+ yml << ' '*offset + "type: #{type}\n"
227
+ yml << ' '*offset + eval if eval.size > 0
228
+ yml << ' '*offset + "size: 50\n" if type == 'text_field'
229
+ if type == 'select'
230
+ yml << ' '*offset + "html:\n"
231
+ offset += 2
232
+ yml << ' '*offset + "include_blank: true\n"
233
+ end
234
+ yml
235
+ end
236
+
237
+ ###########################################################################
238
+ #
239
+ ###########################################################################
240
+ def embedded_form_field(offset)
241
+ yml = ''
242
+ field_index = 10
243
+ @model.embedded_relations.keys.each do |embedded_name|
244
+ yml << ' '*offset + "#{field_index}:\n"
245
+ yml << ' '*(offset + 2) + "name: #{embedded_name}\n"
246
+ yml << ' '*(offset + 2) + "type: embedded\n"
247
+ yml << ' '*(offset + 2) + "form_name: #{embedded_name[0,embedded_name.size - 1]}\n"
248
+ yml << '#' + ' '*(offset + 2) + "html:\n"
249
+ field_index += 10
250
+ end
251
+ yml
252
+ end
253
+
254
+ ###########################################################################
255
+ #
256
+ ###########################################################################
257
+ def form_fields_options
258
+ extra = <<EOT
259
+
260
+ # group: 2
261
+ # line: top bottom
262
+ # readonly: yes 1 true
263
+ # default: 10
264
+ # eval: some_method, session[:], params[:],@site.name
265
+
266
+ # type: comment
267
+ # text: myapp.comment_text
268
+ # caption: false
269
+ # html:
270
+ # style: 'color: red'
271
+ # class: some_class
272
+
273
+ # type: datetime_picker
274
+ # type: date_picker
275
+ # options: 'step: 60, inline: true'
276
+ # options: 'inline: true'
277
+
278
+ # type: text_autocomplete
279
+ # search: model_name.field_name
280
+ # search: model_name..method_name
281
+ # is_id: no
282
+
283
+ # type: select
284
+ # choices:
285
+ # eval: ModelClass.method_name
286
+ # depend: field1, field2
287
+ # include_blank: true
288
+
289
+ # type: text_area
290
+ # size: 90x10
291
+ # type: check_box
292
+
293
+ # type: number_field
294
+ # size: 10
295
+ # format: N2
296
+
297
+ # type: radio_button
298
+ # choices: 'Marantz:1,Sony:2,Bose:3,Pioneer:4'
299
+ # inline: true
300
+
301
+ # type: readonly
302
+ # name: user_id
303
+ # eval: agile_name_for_id,model_name,field_name
304
+
305
+ # type: hidden_field
306
+ # type: file_field
307
+ # type: file_select
308
+ # size: 50
309
+ # html:
310
+ # type: email
311
+ # required: true
312
+
313
+
314
+ EOT
315
+
316
+ forbidden = %w[id created_by updated_by created_at updated_at]
317
+ tab_index = 1
318
+ field_index = 0
319
+ if @tabs
320
+ yml = " tabs:\n"
321
+ @model.new.attributes.each do |attribute|
322
+ next if forbidden.include?(attribute.first)
323
+
324
+ if field_index%100 == 0
325
+ yml << "\n tab#{tab_index}:\n"
326
+ field_index = 0
327
+ tab_index += 1
328
+ end
329
+ yml << form_field(attribute, field_index += 10, 6)
330
+ end
331
+ else
332
+ yml = " fields:\n"
333
+ @model.new.attributes.each do |attribute|
334
+ next if forbidden.include?(attribute.first)
335
+
336
+ yml << form_field(attribute, field_index += 10, 4)
337
+ end
338
+ end
339
+ yml + (@extra ? extra : '')
340
+ end
341
+
342
+ ###########################################################################
343
+ #
344
+ ###########################################################################
345
+ def localize_options
346
+ forbidden = %w[id created_by updated_by created_at updated_at]
347
+ yml =<<EOT
348
+
349
+ #################################################################
350
+ # Localization
351
+ en:
352
+ helpers:
353
+ label:
354
+ #{file_name}:
355
+ table_title:
356
+ choices_for_:
357
+
358
+ EOT
359
+ @model.attribute_names.each do |attr_name|
360
+ next if forbidden.include?(attr_name)
361
+
362
+ yml << " #{attr_name}: \n"
363
+ end
364
+ yml
365
+ end
366
+
367
+ end
368
+ end
369
+ end
@@ -0,0 +1,158 @@
1
+ class ConvertToArGenerator < Rails::Generators::NamedBase
2
+
3
+ source_root File.expand_path('../templates', __FILE__)
4
+ desc 'This generator converts mongoid model to active_record migration'
5
+ argument :model_name, :type => :string, :default => 'dc_*'
6
+ argument :migration_name, :type => :string, :default => 'initial_migration'
7
+
8
+ TYPES = {
9
+ String => :string,
10
+ Time => :datetime,
11
+ DateTime => :datetime,
12
+ Object => :integer,
13
+ Integer => :integer,
14
+ BSON::ObjectId => :integer,
15
+ Mongoid::Boolean => :boolean,
16
+ BigDecimal => [:decimal, :precision => 8, :scale => 2, :default => 0.00],
17
+ Date => :date,
18
+ Hash => :text,
19
+ Array => :text
20
+ }
21
+
22
+ ###########################################################################
23
+ #
24
+ ###########################################################################
25
+ def create_migration
26
+ p model_name, migration_name
27
+
28
+ code = model_name.match(/\*/) ? migrate_many(model_name) : migrate_one(model_name)
29
+ code = top(migration_name) + code + bottom
30
+ create_file "db/#{source_file_name(migration_name).underscore}.rb", code
31
+ end
32
+
33
+ private
34
+
35
+ ###########################################################################
36
+ #
37
+ ###########################################################################
38
+ def source_file_name(migration)
39
+ "#{Time.now.strftime("%Y%m%d%H%M%S")}_#{migration}"
40
+ end
41
+
42
+ ###########################################################################
43
+ #
44
+ ###########################################################################
45
+ def migrate_one(model_name)
46
+ mongo_model = model_name.classify.constantize
47
+ new_model_name = model_name.start_with?('dc_') ? model_name.sub('dc_', 'ar_') : model_name
48
+ code = %( create_table :#{new_model_name.pluralize} do |t|\n)
49
+ left = ' t.'
50
+ timestamps = false
51
+ # fields
52
+ document = mongo_model.new
53
+ document.attribute_names.each do |attribute_name|
54
+ next if attribute_name == '_id'
55
+ if %w[created_at updated_at].include?(attribute_name)
56
+ timestamps = true
57
+ next
58
+ end
59
+
60
+ options = mongo_model.fields[attribute_name].options
61
+ pp "Undefined type #{options[:type]} for #{mongo_model}.#{attribute_name}" unless TYPES[options[:type]]
62
+ att_name = attribute_name.sub(/^dc_/,'ar_')
63
+ code << %(#{left}#{TYPES[options[:type]]} :#{att_name})
64
+ code << %(, default: #{get_default(options[:default], options[:type])}) if options[:default]
65
+ code << "\n"
66
+ end
67
+ code << %(\n#{left}timestamps\n) if timestamps
68
+
69
+ # indexes
70
+ if document.index_specifications.any?
71
+ code << "\n"
72
+ document.index_specifications.each do |index|
73
+ code << "#{left}index "
74
+ code << (index.fields.size > 1 ? "[:#{index.fields.join(', :')}]" : ":#{index.fields.first}")
75
+ code << ", #{index.options.to_s.gsub(/\{|\}/, '')}" if index.options.size > 0
76
+ code << "\n"
77
+ end
78
+ end
79
+
80
+ # export some test data
81
+ data = []
82
+ mongo_model.all.limit(5).each do |doc|
83
+ #data << doc.as_document.inject([]) { |r, e| [e.first.sub(/^dc_/,'ar_'), e.last] }
84
+ data << doc.as_document.map { |e| [e.first.sub(/^dc_/,'ar_'), e.last] }
85
+ end
86
+ File.write("db/#{new_model_name}.json", data.to_json)
87
+
88
+ code << " end\n\n"
89
+ end
90
+
91
+ ###########################################################################
92
+ #
93
+ ###########################################################################
94
+ def get_default(default, type)
95
+ case type.to_s
96
+ when 'String' then "'#{default}'"
97
+ else default
98
+ end
99
+ end
100
+
101
+ #########################################################################
102
+ # Return array of all models found in application.
103
+ #########################################################################
104
+ def all_collections
105
+ collections = []
106
+ AgileRAils.paths(:forms).each do |path|
107
+ models_dir = File.expand_path('../models', path)
108
+ Dir["#{models_dir}/*.rb"].each do |model_file|
109
+ model_file =~ /(.*)\/(.*).rb/
110
+ # check if model exists
111
+ collection = $2.camelize.constantize.new rescue nil
112
+ collections << collection.class.to_s.underscore if collection&.respond_to?(:_id)
113
+ end
114
+ end
115
+ collections.sort
116
+ end
117
+
118
+ ###########################################################################
119
+ #
120
+ ###########################################################################
121
+ def migrate_many(model_name)
122
+ selector = model_name[0, model_name.index('*') - 1].downcase
123
+ p selector
124
+
125
+ list = all_collections.select { |name| name.starts_with?(selector) }
126
+ list.inject('') { |r, e| r << migrate_one(e) }
127
+ end
128
+
129
+ ###########################################################################
130
+ #class #{migration_name} < ActiveRecord::Migration[7.0]
131
+ # def change
132
+ # create_table :products do |t|
133
+ # t.string :name
134
+ # t.text :description
135
+ #
136
+ # t.timestamps = true
137
+ # end
138
+ # end
139
+ # end
140
+ ###########################################################################
141
+ def top(migration_name)
142
+ <<~EOT
143
+ class #{migration_name.classify} < ActiveRecord::Migration[7.0]
144
+ def change
145
+ EOT
146
+ end
147
+
148
+ ###########################################################################
149
+ #
150
+ ###########################################################################
151
+ def bottom
152
+ <<~EOT
153
+ end
154
+ end
155
+ EOT
156
+ end
157
+
158
+ end
@@ -0,0 +1,132 @@
1
+ # Thanks to Jimmy https://github.com/kejiro
2
+ #
3
+ # https://gist.githubusercontent.com/kejiro/484416/raw/56b8f3db8a62aac0fb0d007b1afd7e7b56b3ff07/Rakefile
4
+ #
5
+ #require 'activerecord'
6
+ #require 'yaml'
7
+
8
+ module DataCopier
9
+ @source = nil
10
+ @destination = nil
11
+
12
+
13
+ module Source
14
+ class Base < ActiveRecord::Base
15
+ self.abstract_class = true
16
+ end
17
+ end
18
+
19
+ module Destination
20
+ class Base < ActiveRecord::Base
21
+ self.abstract_class = true
22
+ end
23
+ end
24
+
25
+ class Base
26
+ @source = nil
27
+ @destination = nil
28
+
29
+ def write(text="")
30
+ puts(text)# if verbose
31
+ end
32
+
33
+ def announce(message)
34
+ text = "#{message}"
35
+ length = [0, 75 - text.length].max
36
+ write "== %s %s" % [text, "=" * length]
37
+ end
38
+
39
+ def say(message, subitem=false)
40
+ write "#{subitem ? " ->" : "--"} #{message}"
41
+ end
42
+
43
+ def say_with_time(message)
44
+ say(message)
45
+ result = nil
46
+ time = Benchmark.measure { result = yield }
47
+ say "%.4fs" % time.real, :subitem
48
+ say("#{result} rows", :subitem) if result.is_a?(Integer)
49
+ result
50
+ end
51
+
52
+ def initialize(configuration)
53
+ ActiveRecord::Base.configurations = configuration
54
+
55
+ @source = Source::Base.establish_connection(:source).connection
56
+ @destination = Destination::Base.establish_connection(:destination).connection
57
+
58
+ end
59
+
60
+
61
+ def create_destination_tables(source = @source, destination = @destination)
62
+ return unless destination.tables.empty?
63
+
64
+ schema_definitions = StringIO.new
65
+ ActiveRecord::Base.establish_connection(:destination)
66
+
67
+ say_with_time("Dumping the schema from the source"){ActiveRecord::SchemaDumper.dump(source, schema_definitions)}
68
+ say_with_time("Loading the schema in the destination"){eval(schema_definitions.string)}
69
+ end
70
+
71
+ def create_models(tables = @source.tables)
72
+ tables.each do |table|
73
+ class_name = table.downcase.classify
74
+ Source.module_eval <<-DECL
75
+ class #{class_name} < Source::Base
76
+ #set_table_name "#{table}"
77
+ self.table_name = "#{table}"
78
+ end
79
+ DECL
80
+
81
+ Destination.module_eval <<-DECL
82
+ class #{class_name} < Destination::Base
83
+ #set_table_name "#{table}"
84
+ self.table_name = "#{table}"
85
+ end
86
+ DECL
87
+ end
88
+ end
89
+
90
+ def copy_data(tables = @source.tables)
91
+ skip = %w[schema_migrations ar_journals]
92
+ tables.each do |table|
93
+ next if skip.include?(table)
94
+
95
+ source_model = "DataCopier::Source::#{table.downcase.classify}".constantize
96
+ destination_model = "DataCopier::Destination::#{table.downcase.classify}".constantize
97
+ destination_model.delete_all
98
+ rows_to_copy = source_model.count
99
+ rows_copied = 0
100
+ say_with_time("Copying #{rows_to_copy} rows from #{table.downcase}"){
101
+ source_model.all.each do |row|
102
+ destination_model.create(row.attributes)
103
+ rows_copied += 1
104
+ end
105
+ rows_copied
106
+ }
107
+ end
108
+ end
109
+
110
+
111
+ def run
112
+ create_destination_tables(@source, @destination)
113
+ create_models(@source.tables)
114
+ copy_data(@source.tables)
115
+ end
116
+ end
117
+ end
118
+
119
+ #########################################################################
120
+ namespace :agile do
121
+ namespace :db do
122
+ task :setup do
123
+ configuration_file = ENV['config'] || 'config/database.yml'
124
+ raise "Can't find the configuration file, please specify with: env config=<path to file>" unless File.exist?(configuration_file)
125
+ @configuration = YAML.load_file(configuration_file, aliases: true)
126
+ end
127
+
128
+ task :clone => :setup do
129
+ DataCopier::Base.new(@configuration).run
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,37 @@
1
+ #Rails.initialize!
2
+
3
+ #########################################################################
4
+ #
5
+ #########################################################################
6
+ def agile_db_export_to_yaml
7
+ h = {}
8
+ all_models = (ActiveRecord::Base.connection.tables - %w[schema_migrations sessions])
9
+ all_models.each do |model_name|
10
+ p model_name
11
+
12
+ model = model_name.classify.constantize rescue nil
13
+ next if model.nil?
14
+ next unless model.all.count > 0
15
+
16
+ p model.column_names
17
+ a = []
18
+ model.all.each do |record|
19
+ a << model.column_names.each_with_object({}) do |column, r|
20
+ r[column] = record[column] if record[column].present?
21
+ end
22
+ end
23
+ h[model_name] = a
24
+ end
25
+ File.write('out.txt', h.to_yaml)
26
+ end
27
+
28
+ #########################################################################
29
+ namespace :agile do
30
+ namespace :db do
31
+ desc "agile:db:export, export database to text file in yaml format"
32
+ task :export => :environment do
33
+ agile_db_export_to_yaml
34
+ end
35
+ end
36
+
37
+ end