card 1.19.6 → 1.20.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.
Files changed (298) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +8 -7
  4. data/config/initializers/01_core_extensions/array.rb +4 -0
  5. data/config/initializers/01_core_extensions/persistent_identifiers.rb +12 -0
  6. data/config/initializers/02_patches/better_errors.rb +56 -0
  7. data/config/initializers/core_extensions.rb +13 -18
  8. data/config/initializers/patches.rb +8 -0
  9. data/config/locales/de.yml +0 -2
  10. data/db/migrate_core_cards/20150202143810_import_bootstrap_layout.rb +22 -12
  11. data/db/migrate_core_cards/20161102202156_tweak_recaptcha_setting_cards.rb +17 -0
  12. data/db/migrate_core_cards/20161103154836_update_keys.rb +46 -0
  13. data/lib/card.rb +1 -8
  14. data/lib/card/act_manager.rb +4 -0
  15. data/lib/card/auth/permissions.rb +5 -3
  16. data/lib/card/cache.rb +1 -20
  17. data/lib/card/cache/persistent.rb +6 -0
  18. data/lib/card/content/chunk.rb +4 -3
  19. data/lib/card/content/diff.rb +2 -2
  20. data/lib/card/content/diff/result.rb +11 -0
  21. data/lib/card/env/success.rb +4 -0
  22. data/lib/card/error.rb +2 -0
  23. data/lib/card/format.rb +14 -17
  24. data/lib/card/format/content.rb +16 -8
  25. data/lib/card/format/error.rb +3 -5
  26. data/lib/card/format/names.rb +22 -16
  27. data/lib/card/format/nest.rb +67 -61
  28. data/lib/card/format/nest/fetch.rb +40 -33
  29. data/lib/card/format/nest/main.rb +39 -19
  30. data/lib/card/format/nest/subformat.rb +3 -16
  31. data/lib/card/format/nest/view.rb +23 -32
  32. data/lib/card/format/permission.rb +49 -34
  33. data/lib/card/format/registration.rb +12 -6
  34. data/lib/card/format/render.rb +62 -73
  35. data/lib/card/migration.rb +14 -10
  36. data/lib/card/migration/import.rb +20 -19
  37. data/lib/card/migration/import/import_data.rb +50 -59
  38. data/lib/card/migration/import/import_data/card_attributes.rb +56 -0
  39. data/lib/card/migration/import/import_data/card_content.rb +33 -0
  40. data/lib/card/migration/import/merger.rb +47 -0
  41. data/lib/card/mod/loader.rb +4 -4
  42. data/lib/card/model/save_helper.rb +49 -10
  43. data/lib/card/name.rb +16 -52
  44. data/lib/card/name/fields_and_traits.rb +67 -0
  45. data/lib/card/name/variants.rb +17 -0
  46. data/lib/card/query.rb +6 -2
  47. data/lib/card/query/attributes.rb +1 -1
  48. data/lib/card/query/interpretation.rb +3 -3
  49. data/lib/card/set/event.rb +2 -1
  50. data/lib/card/set/format.rb +18 -7
  51. data/lib/card/set_pattern.rb +17 -13
  52. data/lib/card/tasks/card.rake +1 -1
  53. data/lib/card/view.rb +55 -0
  54. data/lib/card/view/cache.rb +90 -0
  55. data/lib/card/view/fetch.rb +109 -0
  56. data/lib/card/view/options.rb +164 -0
  57. data/lib/card/view/stub.rb +30 -0
  58. data/lib/card/view/visibility.rb +95 -0
  59. data/lib/cardio.rb +3 -2
  60. data/lib/cardio/schema.rb +21 -8
  61. data/lib/generators/card.rb +16 -2
  62. data/lib/generators/card/format/format_generator.rb +10 -9
  63. data/lib/generators/card/migration/migration_generator.rb +10 -5
  64. data/lib/generators/card/set/USAGE +1 -1
  65. data/lib/generators/card/set/set_generator.rb +11 -9
  66. data/mod/account/set/right/account.rb +38 -40
  67. data/mod/account/set/right/token.rb +2 -1
  68. data/mod/account/set/self/account_links.rb +34 -54
  69. data/mod/account/set/self/signin.rb +107 -93
  70. data/mod/account/set/type/signup.rb +33 -32
  71. data/mod/account/set/type/user.rb +28 -21
  72. data/mod/account/spec/set/all/account_spec.rb +9 -9
  73. data/mod/account/spec/set/right/account_spec.rb +23 -14
  74. data/mod/account/spec/set/right/email_spec.rb +6 -6
  75. data/mod/account/spec/set/right/password_spec.rb +4 -4
  76. data/mod/account/spec/set/right/token_spec.rb +3 -3
  77. data/mod/account/spec/set/self/account_links_spec.rb +3 -3
  78. data/mod/account/spec/set/self/signin_spec.rb +2 -2
  79. data/mod/account/spec/set/type/signup_spec.rb +7 -8
  80. data/mod/ace_editor/set/abstract/ace_editor.rb +1 -4
  81. data/mod/admin/set/self/admin.rb +2 -2
  82. data/mod/admin/set/self/admin_info.rb +1 -1
  83. data/mod/admin/set/self/recaptcha_private_key.rb +3 -0
  84. data/mod/admin/set/self/recaptcha_proxy.rb +3 -0
  85. data/mod/admin/set/self/recaptcha_public_key.rb +3 -0
  86. data/mod/admin/set/self/trash.rb +4 -4
  87. data/mod/admin/spec/set/self/admin_spec.rb +4 -4
  88. data/mod/admin/spec/set/self/version_spec.rb +1 -1
  89. data/mod/basic_formats/set/all/all_css.rb +3 -3
  90. data/mod/basic_formats/set/all/all_csv.rb +6 -6
  91. data/mod/basic_formats/set/all/all_js.rb +4 -0
  92. data/mod/basic_formats/set/all/base.rb +40 -62
  93. data/mod/basic_formats/set/all/json.rb +34 -39
  94. data/mod/basic_formats/set/all/rss.rb +6 -6
  95. data/mod/basic_formats/set/all/text.rb +3 -2
  96. data/mod/basic_formats/set/self/01_head/javascript.rb +2 -2
  97. data/mod/basic_formats/set/self/head.rb +6 -10
  98. data/mod/basic_formats/spec/set/all/all_css_spec.rb +1 -1
  99. data/mod/basic_formats/spec/set/all/all_csv_spec.rb +1 -1
  100. data/mod/basic_formats/spec/set/all/base_spec.rb +8 -5
  101. data/mod/basic_formats/spec/set/all/json_spec.rb +2 -2
  102. data/mod/basic_formats/spec/set/all/rss_spec.rb +4 -4
  103. data/mod/basic_types/set/type/plain_text.rb +3 -5
  104. data/mod/basic_types/spec/set/type/plain_text_spec.rb +2 -2
  105. data/mod/bootstrap/lib/bootstrap.rb +16 -0
  106. data/mod/bootstrap/lib/bootstrap/basic_tags.rb +26 -0
  107. data/mod/bootstrap/lib/bootstrap/component.rb +133 -0
  108. data/mod/bootstrap/lib/bootstrap/component/form.rb +31 -0
  109. data/mod/bootstrap/lib/bootstrap/component/horizontal_form.rb +38 -0
  110. data/mod/bootstrap/lib/bootstrap/component/layout.rb +83 -0
  111. data/mod/bootstrap/lib/bootstrap/component/panel.rb +9 -0
  112. data/mod/bootstrap/lib/bootstrap/component_loader.rb +30 -0
  113. data/mod/bootstrap/lib/bootstrap/delegate.rb +16 -0
  114. data/mod/bootstrap/lib/bootstrapper.rb +16 -0
  115. data/mod/bootstrap/lib/stylesheets/bootstrap/_tables.scss +55 -52
  116. data/mod/bootstrap/lib/stylesheets/bootstrap/mixins/_table-row.scss +12 -12
  117. data/mod/bootstrap/lib/stylesheets/bootstrap_cards.scss +12 -0
  118. data/mod/bootstrap/set/all/bootstrap/accordion.rb +63 -0
  119. data/mod/bootstrap/set/all/bootstrap/helper.rb +7 -140
  120. data/mod/bootstrap/set/all/bootstrap/navbar.rb +74 -0
  121. data/mod/bootstrap/set/all/bootstrap/table.rb +76 -46
  122. data/mod/bootstrap/set/all/bootstrap/tabs.rb +58 -23
  123. data/mod/bootstrap/set/all/bootstrap/wrapper.rb +14 -8
  124. data/mod/bootstrap/set/all/rich_bootstrap.rb +5 -3
  125. data/mod/bootstrap/spec/set/all/bootstrap/bootstrap_builder_spec.rb +31 -0
  126. data/mod/bootstrap/spec/set/all/bootstrap/bootstrap_spec.rb +20 -0
  127. data/mod/bootstrap/spec/set/all/bootstrap/form_spec.rb +59 -1
  128. data/mod/bootstrap/spec/set/all/bootstrap/layout_spec.rb +104 -15
  129. data/mod/carrierwave/set/abstract/attachment.rb +4 -3
  130. data/mod/carrierwave/set/abstract/attachment/paths.rb +1 -1
  131. data/mod/carrierwave/set/abstract/attachment/storage_type.rb +5 -11
  132. data/mod/carrierwave/set/type/file.rb +39 -32
  133. data/mod/carrierwave/set/type/image.rb +59 -34
  134. data/mod/carrierwave/spec/set/type/image_spec.rb +3 -3
  135. data/mod/core/chunk/link.rb +5 -0
  136. data/mod/core/chunk/{include.rb → nest.rb} +8 -29
  137. data/mod/core/chunk/reference.rb +5 -6
  138. data/mod/core/chunk/view_stub.rb +42 -0
  139. data/mod/core/format/html_format.rb +23 -26
  140. data/mod/core/set/abstract/code_file.rb +1 -1
  141. data/mod/core/set/all/actify.rb +1 -1
  142. data/mod/core/set/all/active_card.rb +0 -1
  143. data/mod/core/set/all/{tracked_attributes.rb → assign_attributes.rb} +55 -24
  144. data/mod/core/set/all/collection.rb +136 -122
  145. data/mod/core/set/all/content.rb +8 -0
  146. data/mod/core/set/all/event.rb +5 -2
  147. data/mod/core/set/all/export.rb +7 -7
  148. data/mod/core/set/all/fetch.rb +90 -26
  149. data/mod/core/set/all/initialize.rb +17 -6
  150. data/mod/core/set/all/name.rb +2 -3
  151. data/mod/core/set/all/permissions.rb +19 -11
  152. data/mod/core/set/all/states.rb +12 -2
  153. data/mod/core/set/all/trash.rb +1 -1
  154. data/mod/core/set/all/type.rb +2 -0
  155. data/mod/core/set/all/utils.rb +4 -3
  156. data/mod/core/spec/chunk/literal_spec.rb +2 -2
  157. data/mod/core/spec/chunk/uri_spec.rb +17 -17
  158. data/mod/core/spec/format/html_format_spec.rb +11 -13
  159. data/mod/core/spec/set/all/attribute_tracking_spec.rb +2 -2
  160. data/mod/core/spec/set/all/collection_spec.rb +21 -24
  161. data/mod/core/spec/set/all/content_spec.rb +1 -1
  162. data/mod/core/spec/set/all/export_spec.rb +3 -3
  163. data/mod/core/spec/set/all/fetch_spec.rb +5 -5
  164. data/mod/core/spec/set/all/initialize_spec.rb +4 -4
  165. data/mod/core/spec/set/all/name_spec.rb +6 -6
  166. data/mod/core/spec/set/all/permissions_spec.rb +10 -10
  167. data/mod/core/spec/set/all/references_spec.rb +1 -1
  168. data/mod/core/spec/set/all/rules2_spec.rb +24 -24
  169. data/mod/core/spec/set/all/rules_spec.rb +1 -1
  170. data/mod/core/spec/set/all/templating_spec.rb +8 -8
  171. data/mod/core/spec/set/all/tracked_attributes_spec.rb +6 -6
  172. data/mod/core/spec/set/all/type_spec.rb +5 -5
  173. data/mod/developer/spec/set/all/event_viz_spec.rb +1 -1
  174. data/mod/developer/spec/set/right/debug_spec.rb +1 -1
  175. data/mod/email/set/all/email_html.rb +2 -2
  176. data/mod/email/set/all/notify.rb +8 -3
  177. data/mod/email/set/right/bcc.rb +3 -3
  178. data/mod/email/set/right/follow.rb +5 -5
  179. data/mod/email/set/right/following.rb +1 -1
  180. data/mod/email/set/self/follow_defaults.rb +27 -16
  181. data/mod/email/set/type/email_template.rb +1 -1
  182. data/mod/email/set/type_plus_right/user/follow.rb +10 -9
  183. data/mod/history/lib/card/act.rb +4 -0
  184. data/mod/history/lib/card/act/act_renderer.rb +194 -0
  185. data/mod/history/lib/card/act/act_renderer/absolute_act_renderer.rb +25 -0
  186. data/mod/history/lib/card/act/act_renderer/relative_act_renderer.rb +41 -0
  187. data/mod/history/lib/card/action.rb +1 -0
  188. data/mod/history/lib/card/action/action_renderer.rb +92 -0
  189. data/mod/history/lib/card/action/differ.rb +6 -1
  190. data/mod/history/set/all/act_view.rb +64 -0
  191. data/mod/history/set/all/action_view.rb +65 -0
  192. data/mod/history/set/all/content_history.rb +44 -37
  193. data/mod/history/set/all/history.rb +49 -263
  194. data/mod/machines/lib/stylesheets/style_cards.scss +30 -115
  195. data/mod/machines/set/abstract/script.rb +42 -7
  196. data/mod/machines/set/right/machine_input.rb +4 -0
  197. data/mod/machines/set/type/coffee_script.rb +8 -22
  198. data/mod/machines/set/type/css.rb +2 -2
  199. data/mod/machines/set/type/java_script.rb +4 -24
  200. data/mod/machines/set/type/scss.rb +1 -1
  201. data/mod/machines/spec/set/type/css_spec.rb +1 -1
  202. data/mod/machines/spec/set/type/scss_spec.rb +3 -3
  203. data/mod/machines/spec/set/type/skin_spec.rb +7 -7
  204. data/mod/pointer/set/abstract/01_pointer.rb +44 -46
  205. data/mod/pointer/set/abstract/01_pointer/edit.rb +13 -13
  206. data/mod/pointer/set/right/options.rb +4 -0
  207. data/mod/pointer/spec/set/type/pointer_spec.rb +7 -7
  208. data/mod/prosemirror_editor/set/abstract/prosemirror_editor.rb +3 -3
  209. data/mod/settings/set/abstract/permission.rb +25 -18
  210. data/mod/settings/set/right/add_help.rb +3 -3
  211. data/mod/settings/set/right/structure.rb +10 -16
  212. data/mod/settings/spec/set/right/comment_spec.rb +3 -3
  213. data/mod/settings/spec/set/right/create_spec.rb +1 -1
  214. data/mod/settings/spec/set/right/style_spec.rb +1 -1
  215. data/mod/settings/spec/set/type/setting_spec.rb +1 -1
  216. data/mod/solid_cache/set/abstract/solid_cache.rb +4 -4
  217. data/mod/solid_cache/set/right/solid_cache.rb +9 -10
  218. data/mod/standard/set/abstract/01_search_params.rb +41 -0
  219. data/mod/standard/set/abstract/search.rb +132 -0
  220. data/mod/standard/set/abstract/search/paging.rb +81 -0
  221. data/mod/standard/set/abstract/search/paging/paging_links.rb +90 -0
  222. data/mod/standard/set/abstract/wql_search.rb +67 -0
  223. data/mod/standard/set/all/error.rb +89 -82
  224. data/mod/standard/set/all/links.rb +1 -1
  225. data/mod/standard/set/all/rich_html/content.rb +125 -141
  226. data/mod/standard/set/all/rich_html/editing.rb +115 -178
  227. data/mod/standard/set/all/rich_html/form.rb +111 -131
  228. data/mod/standard/set/all/rich_html/header.rb +57 -39
  229. data/mod/standard/set/all/rich_html/menu.rb +94 -94
  230. data/mod/standard/set/all/rich_html/modal.rb +5 -10
  231. data/mod/standard/set/all/rich_html/new.rb +103 -0
  232. data/mod/standard/set/all/rich_html/toolbar.rb +54 -74
  233. data/mod/standard/set/all/rich_html/wrapper.rb +111 -138
  234. data/mod/standard/set/rstar/rules.rb +27 -38
  235. data/mod/standard/set/rstar/rules_editor.rb +298 -277
  236. data/mod/standard/set/self/navbox.rb +20 -15
  237. data/mod/standard/set/self/recent.rb +25 -17
  238. data/mod/standard/set/self/search.rb +25 -4
  239. data/mod/standard/set/type/cardtype.rb +11 -9
  240. data/mod/standard/set/type/date.rb +1 -1
  241. data/mod/standard/set/type/number.rb +1 -1
  242. data/mod/standard/set/type/phrase.rb +1 -1
  243. data/mod/standard/set/type/search_type.rb +17 -282
  244. data/mod/standard/set/type/session.rb +1 -1
  245. data/mod/standard/set/type/set.rb +155 -131
  246. data/mod/standard/set/type/toggle.rb +1 -1
  247. data/mod/standard/set/type/uri.rb +4 -4
  248. data/mod/standard/spec/chunk/include_spec.rb +13 -31
  249. data/mod/standard/spec/chunk/link_spec.rb +1 -1
  250. data/mod/standard/spec/set/all/error_spec.rb +1 -1
  251. data/mod/standard/spec/set/all/history_spec.rb +2 -2
  252. data/mod/standard/spec/set/all/rich_html/form_spec.rb +4 -4
  253. data/mod/standard/spec/set/all/rich_html/toolbar_spec.rb +22 -0
  254. data/mod/standard/spec/set/all/rich_html/wrapper_spec.rb +3 -2
  255. data/mod/standard/spec/set/right/when_created_spec.rb +1 -1
  256. data/mod/standard/spec/set/right/when_last_edited_spec.rb +1 -1
  257. data/mod/standard/spec/set/rstar/rules_spec.rb +2 -3
  258. data/mod/standard/spec/set/self/head_spec.rb +2 -2
  259. data/mod/standard/spec/set/self/navbox_spec.rb +1 -1
  260. data/mod/standard/spec/set/self/now_spec.rb +1 -1
  261. data/mod/standard/spec/set/type/date_spec.rb +1 -1
  262. data/mod/standard/spec/set/type/email_template_spec.rb +1 -1
  263. data/mod/standard/spec/set/type/layout_type_spec.rb +1 -1
  264. data/mod/standard/spec/set/type/number_spec.rb +1 -1
  265. data/mod/standard/spec/set/type/phrase_spec.rb +1 -1
  266. data/mod/standard/spec/set/type/search_type_spec.rb +2 -2
  267. data/mod/standard/spec/set/type/set_spec.rb +2 -2
  268. data/mod/standard/spec/set/type/toggle_spec.rb +2 -2
  269. data/mod/standard/spec/set/type/uri_spec.rb +3 -1
  270. data/mod/tinymce_editor/set/abstract/tinymce_editor.rb +1 -1
  271. data/spec/config/initializers/core_extensions_spec.rb +40 -10
  272. data/spec/lib/card/auth_spec.rb +8 -8
  273. data/spec/lib/card/cache_spec.rb +3 -3
  274. data/spec/lib/card/chunk_spec.rb +4 -4
  275. data/spec/lib/card/codename_spec.rb +2 -2
  276. data/spec/lib/card/content_spec.rb +23 -23
  277. data/spec/lib/card/diff_spec.rb +1 -1
  278. data/spec/lib/card/format_spec.rb +19 -24
  279. data/spec/lib/card/loader_spec.rb +4 -4
  280. data/spec/lib/card/name_spec.rb +16 -16
  281. data/spec/lib/card/query_spec.rb +80 -80
  282. data/spec/lib/card/reference_spec.rb +5 -5
  283. data/spec/lib/card/set_spec.rb +6 -6
  284. data/spec/lib/card/subcards_spec.rb +14 -0
  285. data/spec/lib/card/view_cache_spec.rb +5 -5
  286. data/spec/models/card/cardtype_spec.rb +15 -15
  287. data/spec/models/card/create_spec.rb +2 -2
  288. data/spec/models/card/trash_spec.rb +24 -24
  289. data/spec/models/card/type_transition_spec.rb +8 -8
  290. data/spec/models/card/validation_spec.rb +5 -5
  291. data/spec/models/card_spec.rb +14 -14
  292. data/spec/spec_helper.rb +6 -2
  293. data/spec/support/card_spec_helper.rb +21 -11
  294. data/spec/support/helper/card_helper.rb +11 -4
  295. metadata +73 -15
  296. data/lib/card/cache/view_cache.rb +0 -103
  297. data/mod/bootstrap/set/all/bootstrap/layout.rb +0 -58
  298. data/mod/core/set/all/view_cache.rb +0 -9
@@ -39,15 +39,10 @@ class Card::Migration < ActiveRecord::Migration
39
39
  end
40
40
 
41
41
  def schema_mode mig_type=type
42
- new_suffix = schema_suffix mig_type
43
- original_suffix = ActiveRecord::Base.table_name_suffix
44
-
45
- ActiveRecord::Base.table_name_suffix = new_suffix
46
- ActiveRecord::SchemaMigration.reset_table_name
47
- paths = Cardio.migration_paths(type)
48
- yield(paths)
49
- ActiveRecord::Base.table_name_suffix = original_suffix
50
- ActiveRecord::SchemaMigration.reset_table_name
42
+ Cardio.with_suffix mig_type do
43
+ paths = Cardio.migration_paths(type)
44
+ yield(paths)
45
+ end
51
46
  end
52
47
 
53
48
  def assume_migrated_upto_version
@@ -99,10 +94,19 @@ class Card::Migration < ActiveRecord::Migration
99
94
  Card.merge_list full_data, merge_opts
100
95
  end
101
96
 
97
+ # uses the data in cards.yml and the card content in db/migrate_cards/data/cards
98
+ # to update or create the cards given by name or key in names_or_keys
99
+ def merge_cards names_or_keys
100
+ names_or_keys = Array(names_or_keys)
101
+ Card::Mailer.perform_deliveries = false
102
+
103
+ Card::Migration::Import.merge only: names_or_keys
104
+ end
105
+
102
106
  def read_json filename
103
107
  raw_json = File.read data_path(filename)
104
108
  json = JSON.parse raw_json
105
- json["card"]["value"]
109
+ json.is_a?(Hash) ? json["card"]["value"] : json
106
110
  end
107
111
 
108
112
  def data_path filename=nil
@@ -1,4 +1,5 @@
1
1
  require "import_data"
2
+ require "merger"
2
3
 
3
4
  class Card
4
5
  class Migration
@@ -14,25 +15,16 @@ class Card
14
15
  # To update other attributes change them in the yml file and either remove
15
16
  # the 'merged' value or touch the corresponding content file
16
17
  class Import
17
- OUTPUT_FILE = Card::Migration.data_path "unmerged"
18
18
  class << self
19
- # Merge the import data into the cards table
20
- # If 'all' is true all import data is merged.
21
- # Otherwise only the data that was changed or added since the last merge
22
- def merge all=false
23
- merge_data = all ? ImportData.all_cards : ImportData.changed_cards
24
- puts("nothing to merge") && return if merge_data.empty?
25
-
26
- Card::Mailer.perform_deliveries = false
27
- Card::Auth.as_bot do
28
- Card.merge_list merge_data, output_file: OUTPUT_FILE
29
- end
30
- update_time = Time.zone.now.to_s
31
- ImportData.update do |import_data|
32
- merge_data.each do |card_data|
33
- import_data.merged card_data, update_time
34
- end
35
- end
19
+ # Merge the import data into the cards table.
20
+ # Bu default it merges only the data that was changed or added
21
+ # since the last merge.
22
+ # @param [Hash] opts choose which cards to merge
23
+ # @option opts [Boolean] :all merge all available import data
24
+ # @option opts [Array] :only a key/name or list of keys/names to
25
+ # be merged
26
+ def merge opts={}
27
+ Merger.new(opts).merge
36
28
  end
37
29
 
38
30
  # Get import data from a deck
@@ -91,7 +83,7 @@ class Card
91
83
  json_url = "#{url}/#{name}.json"
92
84
  json_url += "?view=#{view}" if view
93
85
  json = open(json_url).read
94
- JSON.parse(json).deep_symbolize_keys
86
+ parse_and_symbolize json
95
87
  end
96
88
 
97
89
  def fetch_local_data name, view
@@ -99,6 +91,15 @@ class Card
99
91
  Card[name].format(format: :json).render(view || :content)
100
92
  end
101
93
  end
94
+
95
+ def parse_and_symbolize json
96
+ parsed = JSON.parse(json)
97
+ case parsed
98
+ when Hash then parsed.deep_symbolize_keys
99
+ when Array then parsed.map(&:deep_symbolize_keys)
100
+ else parsed
101
+ end
102
+ end
102
103
  end
103
104
  end
104
105
  end
@@ -4,13 +4,18 @@ class Card
4
4
  # Handles the card attributes and remotes for the import
5
5
  class ImportData
6
6
  DEFAULT_PATH = Card::Migration.data_path("cards.yml").freeze
7
- CARD_CONTENT_DIR = Card::Migration.data_path("cards").freeze
7
+
8
+ include CardContent
9
+ include CardAttributes
8
10
 
9
11
  class << self
12
+ # Takes a block to update import data
13
+ # use #add_card and #add_remote in the block to make
14
+ # changes
10
15
  def update
11
16
  data = ImportData.new
12
17
  yield(data)
13
- data.write
18
+ data.write_attributes
14
19
  end
15
20
 
16
21
  def all_cards
@@ -20,18 +25,28 @@ class Card
20
25
  def changed_cards
21
26
  ImportData.new.changed_cards
22
27
  end
28
+
29
+ def select_cards names_or_keys
30
+ ImportData.new.select_cards Array(names_or_keys)
31
+ end
23
32
  end
24
33
 
25
34
  def initialize path=nil
26
35
  @path = path || DEFAULT_PATH
27
- ensure_path
28
- @data = read
36
+ @data = read_attributes
29
37
  end
30
38
 
31
39
  def all_cards
32
40
  cards.map { |data| prepare_for_import data }
33
41
  end
34
42
 
43
+ def select_cards names_or_keys
44
+ cards.map do |attributes|
45
+ next unless name_or_key_match attributes, names_or_keys
46
+ prepare_for_import attributes
47
+ end.compact
48
+ end
49
+
35
50
  def changed_cards
36
51
  cards.map do |data|
37
52
  next unless changed?(data)
@@ -44,48 +59,45 @@ class Card
44
59
  update_attribute data["name"], :merged, time
45
60
  end
46
61
 
47
- def add_card new_attr
48
- card_data = {}
49
- [:name, :type, :codename].each do |key|
50
- card_data[key] = new_attr[key] if new_attr[key]
51
- end
52
- card_data[:key] = new_attr[:name].to_name.key
53
- card_entry = find_card card_data[:name]
62
+ # to be used in an update block
63
+ def add_card card_data
64
+ card_attr, card_content = split_attributes_and_content card_data
54
65
 
55
- if card_entry
56
- card_entry.replace card_data
57
- else
58
- cards << card_data
59
- end
60
- write_card_content card_data, new_attr[:content]
61
- card_data
66
+ update_card_attributes card_attr
67
+ write_card_content card_attr, card_content
68
+ card_attr
62
69
  end
63
70
 
71
+ # to be used in an update block
64
72
  def add_remote name, url
65
- @data[:remotes][name] = url
73
+ remotes[name] = url
66
74
  end
67
75
 
68
76
  def url remote_name
69
- @data[:remotes][remote_name.to_sym] ||
77
+ remotes[remote_name.to_sym] ||
70
78
  raise("unknown remote: #{remote_name}")
71
79
  end
72
80
 
73
- def read
74
- return { cards: [], remotes: {} } unless File.exist? @path
75
- YAML.load_file(@path).deep_symbolize_keys
76
- end
81
+ private
77
82
 
78
- def write
79
- File.write @path, @data.to_yaml
83
+ def split_attributes_and_content data
84
+ card_data = {}
85
+ [:name, :type, :codename].each do |key|
86
+ card_data[key] = data[key] if data[key]
87
+ end
88
+ card_data[:key] = data[:name].to_name.key
89
+ [card_data, data[:content]]
80
90
  end
81
91
 
82
- private
92
+ def name_or_key_match attributes, names_or_keys
93
+ names_or_keys.any? do |nk|
94
+ nk == attributes[:name] || nk == attributes[:name].to_name.key ||
95
+ nk == attributes[:key]
96
+ end
97
+ end
83
98
 
84
- def update_attribute name, attr_key, attr_value
85
- card = find_card name
86
- return unless card
87
- card[attr_key] = attr_value
88
- card
99
+ def remotes
100
+ @data[:remotes]
89
101
  end
90
102
 
91
103
  def cards
@@ -93,41 +105,20 @@ class Card
93
105
  end
94
106
 
95
107
  def prepare_for_import data
96
- card_attr = ::Set.new [:name, :type, :codename, :file, :image]
97
- hash = data.select { |k, v| v && card_attr.include?(k) }
98
- hash[:content] = File.read(content_path(data))
108
+ hash = card_attributes(data)
109
+ hash[:content] = card_content(data)
99
110
  [:file, :image].each do |attach|
100
- hash[attach] &&= Card::Migration.data_path "files/#{hash[attach]}"
111
+ hash[attach] &&= card_attachment(attach, data)
101
112
  end
102
113
  hash.with_indifferent_access
103
114
  end
104
115
 
105
116
  def changed? data
106
- !data[:merged] ||
107
- Time.parse(data[:merged]) < File.mtime(content_path(data))
108
- end
109
-
110
- def write_card_content data, content
111
- FileUtils.mkpath CARD_CONTENT_DIR unless Dir.exist? CARD_CONTENT_DIR
112
- File.write content_path(data), content.to_s
113
- end
114
-
115
- def content_path data
116
- filename = data[:key] || data[:name].to_name.key
117
- File.join CARD_CONTENT_DIR, filename
118
- end
119
-
120
- def find_card name
121
- key = name.to_name.key
122
- index = cards.find_index { |attr| attr[:key] == key } ||
123
- cards.find_index { |attr| attr[:name] == name }
124
- return unless index
125
- cards[index]
117
+ !data[:merged] || content_changed?(data)
126
118
  end
127
119
 
128
- def ensure_path
129
- dir = File.dirname(@path)
130
- FileUtils.mkpath dir unless Dir.exist? dir
120
+ def card_attachment attach_type, data
121
+ Card::Migration.data_path "files/#{data[attach_type]}"
131
122
  end
132
123
  end
133
124
  end
@@ -0,0 +1,56 @@
1
+ class Card
2
+ class Migration
3
+ class Import
4
+ class ImportData
5
+ # handles card attributes for import
6
+ module CardAttributes
7
+ def card_attributes data
8
+ card_attr = ::Set.new [:name, :type, :codename, :file, :image]
9
+ data.select { |k, v| v && card_attr.include?(k) }
10
+ end
11
+
12
+ def update_card_attributes card_data
13
+ card_entry = find_card_attributes card_data[:name]
14
+ if card_entry
15
+ card_entry.replace card_data
16
+ else
17
+ cards << card_data
18
+ end
19
+ end
20
+
21
+ def update_attribute name, attr_key, attr_value
22
+ card = find_card_attributes name
23
+ return unless card
24
+ card[attr_key] = attr_value
25
+ card
26
+ end
27
+
28
+ def write_attributes
29
+ File.write @path, @data.to_yaml
30
+ end
31
+
32
+ def read_attributes
33
+ ensure_path
34
+ return { cards: [], remotes: {} } unless File.exist? @path
35
+ YAML.load_file(@path).deep_symbolize_keys
36
+ end
37
+
38
+ def find_card_attributes name
39
+ key = name.to_name.key
40
+ index = cards.find_index { |attr| attr[:key] == key } ||
41
+ cards.find_index { |attr| attr[:name] == name }
42
+ return unless index
43
+ cards[index]
44
+ end
45
+
46
+ private
47
+
48
+ def ensure_path
49
+ dir = File.dirname(@path)
50
+ FileUtils.mkpath dir unless Dir.exist? dir
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,33 @@
1
+ class Card
2
+ class Migration
3
+ class Import
4
+ class ImportData
5
+ # handles card content for import
6
+ module CardContent
7
+ CARD_CONTENT_DIR = Card::Migration.data_path("cards").freeze
8
+
9
+ def card_content data
10
+ File.read(content_path(data))
11
+ end
12
+
13
+ def content_changed? data
14
+ Time.parse(data[:merged]) < File.mtime(content_path(data))
15
+ end
16
+
17
+ private
18
+
19
+ def write_card_content data, content
20
+ FileUtils.mkpath CARD_CONTENT_DIR unless Dir.exist? CARD_CONTENT_DIR
21
+ File.write content_path(data), content.to_s
22
+ end
23
+
24
+ def content_path data
25
+ filename = data[:key] || data[:name].to_name.key
26
+ File.join CARD_CONTENT_DIR, filename
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,47 @@
1
+ class Card
2
+ class Migration
3
+ class Import
4
+ # executes the card import
5
+ class Merger
6
+ OUTPUT_FILE = Card::Migration.data_path "unmerged"
7
+
8
+ def initialize opts={}
9
+ load_data opts
10
+ end
11
+
12
+ def merge
13
+ puts("nothing to merge") && return if @data.empty?
14
+
15
+ Card::Mailer.perform_deliveries = false
16
+ Card::Auth.as_bot do
17
+ Card.merge_list @data, output_file: OUTPUT_FILE
18
+ end
19
+
20
+ update_import_data
21
+ end
22
+
23
+ private
24
+
25
+ def load_data opts
26
+ @data =
27
+ if opts[:all]
28
+ ImportData.all_cards
29
+ elsif opts[:only]
30
+ ImportData.select_cards opts[:only]
31
+ else
32
+ ImportData.changed_cards
33
+ end
34
+ end
35
+
36
+ def update_import_data
37
+ update_time = Time.zone.now.to_s
38
+ ImportData.update do |import_data|
39
+ @data.each do |card_data|
40
+ import_data.merged card_data, update_time
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -155,11 +155,11 @@ class Card
155
155
  end
156
156
 
157
157
  def rewrite_tmp_files?
158
- if defined?(@@rewrite)
159
- @@rewrite
158
+ if defined?(@rewrite)
159
+ @rewrite
160
160
  else
161
- @@rewrite = !(Rails.env.production? &&
162
- Card.paths["tmp/set"].existent.first)
161
+ @rewrite = !(Rails.env.production? &&
162
+ Card.paths["tmp/set"].existent.first)
163
163
  end
164
164
  end
165
165
 
@@ -16,16 +16,19 @@ class Card
16
16
  end
17
17
 
18
18
  def update_card name, content_or_args
19
- args = standardize_update_args content_or_args
19
+ args = standardize_update_args name, content_or_args
20
20
  resolve_name_conflict args
21
21
  Card[name].update_attributes! args
22
22
  end
23
23
 
24
24
  def create_or_update_card name_or_args, content_or_args=nil
25
- args = standardize_args name_or_args, content_or_args
26
- if Card[args[:name]]
27
- update_card(args.delete(:name), args)
25
+ name = name_from_args name_or_args
26
+
27
+ if Card[name]
28
+ args = standardize_update_args name_or_args, content_or_args
29
+ update_card(name, args)
28
30
  else
31
+ args = standardize_args name_or_args, content_or_args
29
32
  create_card(args)
30
33
  end
31
34
  end
@@ -43,13 +46,16 @@ class Card
43
46
  # create if card doesn't exist
44
47
  # updates existing card only if given attributes are different except the
45
48
  # name
46
- # For example if a card with name "under_score" exists
47
- # then `ensure_card "Under Score"` doesn't change anything
49
+ # @example if a card with name "under_score" exists
50
+ # ensure_card "Under Score" # => no change
51
+ # ensure_card "Under Score", type: :pointer # => changes the type to pointer
52
+ # # but not the name
48
53
  def ensure_card name_or_args, content_or_args=nil
49
54
  args = standardize_args name_or_args, content_or_args
50
55
  name = args.delete(:name)
51
56
  if (card = Card[name])
52
57
  ensure_attributes card, args
58
+ card
53
59
  else
54
60
  Card.create! args.merge(name: name)
55
61
  end
@@ -76,7 +82,7 @@ class Card
76
82
  end
77
83
 
78
84
  def update_card! name, content_or_args
79
- args = standardize_update_args content_or_args
85
+ args = standardize_update_args name, content_or_args
80
86
  update_card name, args.reverse_merge(rename_if_conflict: :new)
81
87
  end
82
88
 
@@ -94,7 +100,8 @@ class Card
94
100
  end
95
101
  end
96
102
 
97
- def standardize_update_args content_or_args
103
+ def standardize_update_args name_or_args, content_or_args
104
+ return name_or_args if name_or_args.is_a?(Hash)
98
105
  if content_or_args.is_a?(String)
99
106
  { content: content_or_args }
100
107
  else
@@ -102,17 +109,21 @@ class Card
102
109
  end
103
110
  end
104
111
 
112
+ def name_from_args name_or_args
113
+ name_or_args.is_a?(Hash) ? name_or_args[:name] : name_or_args
114
+ end
115
+
105
116
  def add_name name, content_or_args
106
117
  if content_or_args.is_a?(String)
107
118
  { content: content_or_args, name: name }
108
119
  else
109
- content_or_args.merge name: name
120
+ content_or_args.reverse_merge name: name
110
121
  end
111
122
  end
112
123
 
113
124
  def resolve_name_conflict args
114
125
  rename = args.delete :rename_if_conflict
115
- return unless rename
126
+ return unless args[:name] && rename
116
127
  args[:name] = Card.uniquify_name args[:name], rename
117
128
  end
118
129
 
@@ -122,6 +133,34 @@ class Card
122
133
  card.update_attributes! update_args
123
134
  end
124
135
 
136
+ def add_style name, opts={}
137
+ name.sub!(/^style\:?\s?/, '') # in case name is given with prefix
138
+ # remove it so that we don't double it
139
+
140
+ add_coderule_item name, "style",
141
+ opts[:type_id] || Card::ScssID,
142
+ opts[:to] || "*all+*style"
143
+ end
144
+
145
+ def add_script name, opts={}
146
+ name.sub!(/^script\:?\s?/, '') # in case name is given with prefix
147
+ # remove it so that we don't double it
148
+
149
+ add_coderule_item name, "script",
150
+ opts[:type_id] || Card::CoffeeScriptID,
151
+ opts[:to] || "*all+*script"
152
+ end
153
+
154
+
155
+ def add_coderule_item name, prefix, type_id, to
156
+ codename = "#{prefix}_#{name.tr(' ', '_').underscore}"
157
+ name = "#{prefix}: #{name}"
158
+
159
+ ensure_card name, type_id: type_id,
160
+ codename: codename
161
+ Card[to].add_item! name
162
+ end
163
+
125
164
  alias_method :create, :create_card
126
165
  alias_method :update, :update_card
127
166
  alias_method :create_or_update, :create_or_update_card