card 1.101.3 → 1.101.4

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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/config/initializers/02_patches/active_record.rb +1 -1
  4. data/config/locales/en.yml +155 -378
  5. data/db/migrate_core_cards/20150202143810_import_bootstrap_layout.rb +1 -1
  6. data/lib/card.rb +15 -2
  7. data/lib/card/auth.rb +5 -2
  8. data/lib/card/auth/current.rb +39 -100
  9. data/lib/card/auth/proxy.rb +36 -16
  10. data/lib/card/auth/token.rb +6 -0
  11. data/lib/card/cache/all.rb +83 -0
  12. data/lib/card/cache/card_class.rb +41 -0
  13. data/lib/card/cache/persistent.rb +3 -34
  14. data/lib/card/cache/persistent_class.rb +28 -0
  15. data/lib/card/codename.rb +1 -1
  16. data/lib/card/content.rb +16 -2
  17. data/lib/card/content/all.rb +59 -0
  18. data/lib/card/director/act_direction.rb +4 -0
  19. data/lib/card/director/all.rb +61 -0
  20. data/lib/card/director/card_class.rb +18 -0
  21. data/lib/card/director/phases.rb +0 -1
  22. data/lib/card/dirty.rb +13 -3
  23. data/lib/card/env/success.rb +14 -14
  24. data/lib/card/env/success/target.rb +9 -11
  25. data/lib/card/error.rb +1 -1
  26. data/lib/card/fetch/all.rb +32 -0
  27. data/lib/card/fetch/card_class.rb +147 -0
  28. data/lib/card/format.rb +1 -1
  29. data/lib/card/format/error.rb +3 -3
  30. data/lib/card/format/nest.rb +1 -1
  31. data/lib/card/format/nest/fetch.rb +1 -1
  32. data/lib/card/lexicon.rb +2 -2
  33. data/lib/card/name/all.rb +8 -0
  34. data/lib/card/name/all/descendants.rb +6 -3
  35. data/lib/card/name/card_class.rb +26 -0
  36. data/lib/card/reference/all.rb +131 -0
  37. data/lib/card/rule/all.rb +75 -0
  38. data/lib/card/set/event/all.rb +95 -0
  39. data/lib/card/set/event/skip_and_trigger.rb +89 -0
  40. data/lib/card/set/pattern/all.rb +63 -0
  41. data/lib/card/subcards/all.rb +103 -0
  42. data/lib/cardio/migration/import.rb +1 -1
  43. data/lib/cardio/utils.rb +5 -3
  44. data/mod/admin/set/self/admin_info.rb +3 -5
  45. data/mod/admin/set/self/trash.rb +2 -2
  46. data/mod/core/set/all/autoname.rb +17 -0
  47. data/mod/core/set/all/codename.rb +2 -2
  48. data/mod/core/set/all/content.rb +52 -97
  49. data/mod/core/set/all/name_events.rb +69 -58
  50. data/mod/core/set/all/reference_events.rb +67 -0
  51. data/mod/core/set/all/states.rb +2 -2
  52. data/mod/core/set/all/subcards.rb +0 -100
  53. data/mod/core/set/all/trash.rb +11 -13
  54. data/mod/core/set/all/type.rb +7 -9
  55. data/mod/core/set/all/utils.rb +3 -0
  56. data/mod/core/set/type/cardtype.rb +3 -3
  57. data/mod/core/set_pattern/06_rule.rb +1 -1
  58. data/mod/core/spec/set/all/{rules2_spec.rb → clean_me_spec.rb} +0 -0
  59. data/mod/core/spec/set/all/name_events_spec.rb +204 -0
  60. metadata +30 -37
  61. data/lib/card/mod_inflector.rb +0 -16
  62. data/lib/card/name/all/class_methods.rb +0 -28
  63. data/mod/core/set/all/actify.rb +0 -68
  64. data/mod/core/set/all/cache.rb +0 -109
  65. data/mod/core/set/all/event_conditions.rb +0 -172
  66. data/mod/core/set/all/fetch.rb +0 -122
  67. data/mod/core/set/all/fetch_helper.rb +0 -35
  68. data/mod/core/set/all/i18n.rb +0 -9
  69. data/mod/core/set/all/pattern.rb +0 -54
  70. data/mod/core/set/all/references.rb +0 -191
  71. data/mod/core/set/all/rename.rb +0 -33
  72. data/mod/core/set/all/rules.rb +0 -81
  73. data/mod/core/spec/set/all/actify_spec.rb +0 -58
  74. data/mod/core/spec/set/all/content_spec.rb +0 -15
  75. data/mod/core/spec/set/all/event_conditions_spec.rb +0 -217
  76. data/mod/core/spec/set/all/fetch_helper_spec.rb +0 -65
  77. data/mod/core/spec/set/all/fetch_spec.rb +0 -338
  78. data/mod/core/spec/set/all/i18n_spec.rb +0 -17
  79. data/mod/core/spec/set/all/pattern_spec.rb +0 -101
  80. data/mod/core/spec/set/all/permissions/reader_rules_spec.rb +0 -166
  81. data/mod/core/spec/set/all/references_spec.rb +0 -62
  82. data/mod/core/spec/set/all/rename_spec.rb +0 -189
  83. data/mod/core/spec/set/all/rules_spec.rb +0 -100
  84. data/mod/core/spec/set/all/subcards_spec.rb +0 -102
@@ -19,11 +19,11 @@ private
19
19
  def validate_codename_permission
20
20
  return if Auth.always_ok? || Auth.as_id == creator_id
21
21
 
22
- errors.add :codename, tr(:only_admins_codename)
22
+ errors.add :codename, t(:core_only_admins_codename)
23
23
  end
24
24
 
25
25
  def validate_codename_uniqueness
26
26
  return (self.codename = nil) if codename.blank?
27
27
  return if errors.present? || !Card.find_by_codename(codename)
28
- errors.add :codename, tr(:error_code_in_use, codename: codename)
28
+ errors.add :codename, t(:core_error_code_in_use, codename: codename)
29
29
  end
@@ -1,30 +1,67 @@
1
- def content= value
2
- self.db_content = standardize_content(value)
1
+ event :set_content, :store, on: :save do
2
+ self.db_content = prepare_db_content
3
+ @selected_action_id = @selected_content = nil
4
+ clear_drafts
5
+ end
6
+
7
+ event :save_draft, :store, on: :update, when: :draft? do
8
+ save_content_draft content
9
+ abort :success
10
+ end
11
+
12
+ event :set_default_content,
13
+ :prepare_to_validate,
14
+ on: :create, when: :use_default_content? do
15
+ self.db_content = template.db_content
16
+ end
17
+
18
+ def draft?
19
+ Env.params["draft"] == "true"
20
+ end
21
+
22
+ def clean_html?
23
+ true
24
+ end
25
+
26
+ def use_default_content?
27
+ !db_content_changed? && template && template.db_content.present?
28
+ end
29
+
30
+ def unfilled?
31
+ blank_content? && blank_comment? && !subcards?
3
32
  end
4
33
 
5
- def content
6
- structured_content || standard_content
34
+ def blank_comment?
35
+ comment.blank? || comment.strip.blank?
7
36
  end
8
- alias raw_content content #DEPRECATED!
9
37
 
10
- def content?
11
- content.present?
38
+ def prepare_db_content
39
+ cont = standard_db_content || "" # necessary?
40
+ clean_html? ? Card::Content.clean!(cont) : cont
12
41
  end
13
42
 
14
- def standard_content
15
- db_content || (new_card? && template.db_content)
43
+ def standard_db_content
44
+ if structure
45
+ # do not override db_content with content from structure
46
+ db_content
47
+ else
48
+ standard_content
49
+ end
16
50
  end
17
51
 
18
- def standardize_content value
19
- value.is_a?(Array) ? value.join("\n") : value
52
+ # seems like this should be moved to format so we can fall back on title
53
+ # rather than name. (In fact, name, title, AND label is a bit much.
54
+ # Trim to 2?)
55
+ def label
56
+ name
20
57
  end
21
58
 
22
- def structured_content
23
- structure && template.db_content
59
+ def creator
60
+ Card[creator_id]
24
61
  end
25
62
 
26
- def refresh_content
27
- self.content = Card.find(id)&.db_content
63
+ def updater
64
+ Card[updater_id]
28
65
  end
29
66
 
30
67
  format do
@@ -94,85 +131,3 @@ format :html do
94
131
  hidden_field :content, class: "d0-card-content"
95
132
  end
96
133
  end
97
-
98
- # seems like this should be moved to format so we can fall back on title
99
- # rather than name. (In fact, name, title, AND label is a bit much.
100
- # Trim to 2?)
101
- def label
102
- name
103
- end
104
-
105
- def creator
106
- Card[creator_id]
107
- end
108
-
109
- def updater
110
- Card[updater_id]
111
- end
112
-
113
- def save_content_draft _content
114
- clear_drafts
115
- end
116
-
117
- def clear_drafts
118
- drafts.created_by(Card::Auth.current_id).each(&:delete)
119
- end
120
-
121
- def last_draft_content
122
- drafts.last.card_changes.last.value
123
- end
124
-
125
- event :set_content, :store, on: :save do
126
- self.db_content = prepare_db_content
127
- @selected_action_id = @selected_content = nil
128
- clear_drafts
129
- end
130
-
131
- event :save_draft, :store, on: :update, when: :draft? do
132
- save_content_draft content
133
- abort :success
134
- end
135
-
136
- event :set_default_content,
137
- :prepare_to_validate,
138
- on: :create, when: :use_default_content? do
139
- self.db_content = template.db_content
140
- end
141
-
142
- def draft?
143
- Env.params["draft"] == "true"
144
- end
145
-
146
- def prepare_db_content
147
- cont = standard_db_content || "" # necessary?
148
- clean_html? ? Card::Content.clean!(cont) : cont
149
- end
150
-
151
- def standard_db_content
152
- if structure
153
- # do not override db_content with content from structure
154
- db_content
155
- else
156
- standard_content
157
- end
158
- end
159
-
160
- def clean_html?
161
- true
162
- end
163
-
164
- def use_default_content?
165
- !db_content_changed? && template && template.db_content.present?
166
- end
167
-
168
- def unfilled?
169
- blank_content? && blank_comment? && !subcards?
170
- end
171
-
172
- def blank_content?
173
- content.blank? || content.strip.blank?
174
- end
175
-
176
- def blank_comment?
177
- comment.blank? || comment.strip.blank?
178
- end
@@ -7,73 +7,58 @@ event :validate_name, :validate, on: :save, changed: :name, when: :no_autoname?
7
7
  validate_uniqueness_of_name
8
8
  end
9
9
 
10
+ # called by validate_name
10
11
  event :validate_uniqueness_of_name, skip: :allowed do
11
- # validate uniqueness of name
12
-
13
12
  return unless (existing_id = Card::Lexicon.id key) && existing_id != id
14
13
  # The above is a fast check but cannot detect if card is in trash
15
14
 
16
15
  # TODO: perform the following as a remote-only fetch (not yet supported)
17
16
  return unless (existing_card = Card.where(id: existing_id, trash: false).take)
18
17
 
19
- errors.add :name, tr(:error_name_exists, name: existing_card.name)
18
+ errors.add :name, t(:core_error_name_exists, name: existing_card.name)
20
19
  end
21
20
 
21
+ # called by validate_name
22
22
  event :validate_legality_of_name do
23
23
  if name.length > 255
24
- errors.add :name, tr(:error_too_long, length: name.length)
24
+ errors.add :name, t(:core_error_too_long, length: name.length)
25
25
  elsif name.blank?
26
- errors.add :name, tr(:error_blank_name)
26
+ errors.add :name, t(:core_error_blank_name)
27
27
  elsif name_incomplete?
28
- errors.add :name, tr(:is_incomplete)
28
+ errors.add :name, t(:core_is_incomplete)
29
29
  elsif !name.valid?
30
- errors.add :name, tr(:error_banned_characters, banned: Card::Name.banned_array * " ")
30
+ errors.add :name, t(:core_error_banned_characters,
31
+ banned: Card::Name.banned_array * " ")
31
32
  elsif changing_existing_tag_to_junction?
32
- errors.add :name, tr(:error_name_tag, name: name)
33
+ errors.add :name, t(:core_error_name_tag, name: name)
33
34
  end
34
35
  end
35
36
 
36
37
  event :validate_key, after: :validate_name, on: :save, when: :no_autoname? do
37
38
  if key.empty?
38
- errors.add :key, tr(:error_blank_key) if errors.empty?
39
+ errors.add :key, t(:core_error_blank_key) if errors.empty?
39
40
  elsif key != name.key
40
- errors.add :key, tr(:error_wrong_key, key: key, name: name)
41
+ errors.add :key, t(:core_error_wrong_key, key: key, name: name)
41
42
  end
42
43
  end
43
44
 
44
- # STAGE: store
45
-
46
- event :set_autoname, :prepare_to_store, on: :create, when: :autoname? do
47
- self.name = autoname rule(:autoname)
48
- autoname_card = rule_card :autoname
49
- autoname_card.update_column :db_content, name
50
- autoname_card.expire
51
- pull_from_trash!
52
- Card.write_to_soft_cache self
45
+ event :validate_renaming, :validate, on: :update, changed: :name, skip: :allowed do
46
+ return if name_before_act&.to_name == name # just changing to new variant
47
+ errors.add :content, t(:core_cannot_change_content) if content_is_changing?
48
+ errors.add :type, t(:core_cannot_change_type) if type_is_changing?
49
+ detect_illegal_compound_names
53
50
  end
54
51
 
52
+ # STAGE: store
53
+
55
54
  event :expire_old_name, :store, changed: :name, on: :update do
56
55
  Director.expirees << name_before_act
57
56
  end
58
57
 
59
- event :update_lexicon_on_create, :finalize, changed: :name, on: :create do
60
- Card::Lexicon.add self
61
- end
62
-
63
- event :update_lexicon_on_rename, :finalize, changed: :name, on: :update do
64
- Card::Lexicon.update self
65
- end
66
-
67
- def lex
68
- simple? ? name : [left_id, right_id]
69
- end
70
-
71
- def old_lex
72
- if (old_left_id = left_id_before_act)
73
- [old_left_id, right_id_before_act]
74
- else
75
- name_before_act
76
- end
58
+ event :rename_in_trash, after: :expire_old_name, on: :update do
59
+ existing_card = Card.find_by_key_and_trash name.key, true
60
+ return if !existing_card || existing_card == self
61
+ existing_card.rename_as_trash_obstacle
77
62
  end
78
63
 
79
64
  event :prepare_left_and_right, :store, changed: :name, on: :save do
@@ -82,42 +67,47 @@ event :prepare_left_and_right, :store, changed: :name, on: :save do
82
67
  prepare_side :right
83
68
  end
84
69
 
85
- def prepare_side side
86
- side_id = send "#{side}_id"
87
- sidename = name.send "#{side}_name"
88
- prepare_obstructed_side(side, side_id, sidename) ||
89
- prepare_new_side(side, side_id, sidename)
70
+ event :update_lexicon, :finalize, changed: :name, on: :save do
71
+ lexicon_action = @action == :create ? :add : :update
72
+ Card::Lexicon.send lexicon_action, self
90
73
  end
91
74
 
92
- def prepare_new_side side, side_id, sidename
93
- return unless side_id == -1 || !Card[side_id]&.real?
75
+ event :cascade_name_changes, :finalize, on: :update, changed: :name do
76
+ each_descendant { |d| d.rename_as_descendant update_referers }
77
+ end
94
78
 
95
- sidecard = Director.card(sidename) || add_subcard(sidename)
96
- send "#{side}_id=", sidecard
79
+ protected
80
+
81
+ def rename_as_trash_obstacle
82
+ self.name = name + "*trash"
83
+ rename_in_trash_without_callbacks
84
+ save!
97
85
  end
98
86
 
99
- def prepare_obstructed_side side, side_id, sidename
100
- return unless side_id && side_id == id
101
- clear_name sidename
102
- send "#{side}_id=", add_subcard(sidename)
103
- true
87
+ def rename_as_descendant referers=true
88
+ self.action = :update
89
+ referers ? update_referers : update_referer_references_out
90
+ refresh_references_in
91
+ refresh_references_out
92
+ expire
93
+ Card::Lexicon.update self
104
94
  end
105
95
 
96
+ private
97
+
106
98
  def name_incomplete?
107
99
  name.parts.include?("") && !superleft&.autoname?
108
100
  end
109
101
 
110
- def no_autoname?
111
- !autoname?
102
+ def changed_from_simple_to_compound?
103
+ name.compound? && name_before_act.to_name.simple?
112
104
  end
113
105
 
114
- def autoname?
115
- name.blank? &&
116
- (@autoname_rule.nil? ? (@autoname_rule = rule(:autoname).present?) : @autoname_rule)
106
+ def detect_illegal_compound_names
107
+ return unless changed_from_simple_to_compound? && child_ids(:right).present?
108
+ errors.add :name, "illegal name change; existing names end in +#{name_before_act}"
117
109
  end
118
110
 
119
- private
120
-
121
111
  def changing_existing_tag_to_junction?
122
112
  return false unless changing_name_to_junction?
123
113
  name_in_use_as_tag?
@@ -143,3 +133,24 @@ def clear_name name
143
133
  Card::Lexicon.cache.reset # probably overkill, but this for an edge case...
144
134
  # Card::Lexicon.delete id, key
145
135
  end
136
+
137
+ def prepare_side side
138
+ side_id = send "#{side}_id"
139
+ sidename = name.send "#{side}_name"
140
+ prepare_obstructed_side(side, side_id, sidename) ||
141
+ prepare_new_side(side, side_id, sidename)
142
+ end
143
+
144
+ def prepare_new_side side, side_id, sidename
145
+ return unless side_id == -1 || !Card[side_id]&.real?
146
+
147
+ sidecard = Director.card(sidename) || add_subcard(sidename)
148
+ send "#{side}_id=", sidecard
149
+ end
150
+
151
+ def prepare_obstructed_side side, side_id, sidename
152
+ return unless side_id && side_id == id
153
+ clear_name sidename
154
+ send "#{side}_id=", add_subcard(sidename)
155
+ true
156
+ end
@@ -0,0 +1,67 @@
1
+ # test for updating referer content
2
+ event :prepare_referer_update, :validate, on: :update, changed: :name do
3
+ self.update_referers = ![nil, false, "false"].member?(update_referers)
4
+ end
5
+
6
+ # on rename, update names in cards that refer to self by name (as directed)
7
+ event :update_referer_content, :finalize, on: :update, when: :update_referers do
8
+ referers.each do |card|
9
+ next if card.structure
10
+ card.skip_event! :validate_renaming, :check_permissions
11
+ card.content = card.replace_references name_before_act, name
12
+ attach_subcard card
13
+ end
14
+ end
15
+
16
+ # on rename, when NOT updating referer content, update references to ensure
17
+ # that partial references are correctly tracked
18
+ # eg. A links to X+Y. if X+Y is renamed and we're not updating the link in A,
19
+ # then we need to be sure that A has a partial reference
20
+ event :update_referer_references_out, :finalize,
21
+ changed: :name, on: :update, when: :not_update_referers do
22
+ referers.map(&:update_references_out)
23
+ end
24
+
25
+ # when name changes, update references to card
26
+ event :refresh_references_in, :finalize, changed: :name, on: :save do
27
+ Reference.unmap_referees id if action == :update && !update_referers
28
+ Reference.map_referees key, id
29
+ end
30
+
31
+ # when content changes, update references to other cards
32
+ event :refresh_references_out, :finalize, on: :save, changed: :content do
33
+ update_references_out
34
+ end
35
+
36
+ # clean up reference table when card is deleted
37
+ event :clear_references, :finalize, on: :delete do
38
+ delete_references_out
39
+ Reference.unmap_referees id
40
+ end
41
+
42
+ # replace references in card content
43
+ def replace_references old_name, new_name
44
+ cont = content_object
45
+ cont.find_chunks(:Reference).each do |chunk|
46
+ next unless replace_reference chunk, old_name, new_name
47
+ end
48
+ cont.to_s
49
+ end
50
+
51
+ protected
52
+
53
+ def not_update_referers
54
+ !update_referers
55
+ end
56
+
57
+ private
58
+
59
+ def replace_reference chunk, old_name, new_name
60
+ return unless (old = chunk.referee_name) && (new = old.swap old_name, new_name)
61
+ chunk.referee_name = chunk.replace_reference old_name, new_name
62
+ update_reference old.key, new.key
63
+ end
64
+
65
+ def update_reference old_key, new_key
66
+ Reference.where(referee_key: old_key).update_all referee_key: new_key
67
+ end
@@ -71,8 +71,8 @@ def new?
71
71
  new_record? || # not yet in db (from ActiveRecord)
72
72
  !@from_trash.nil? # in process of restoration from trash
73
73
  end
74
- alias new_card? new?
75
- alias unreal? new?
74
+ alias_method :new_card?, :new?
75
+ alias_method :unreal?, :new?
76
76
 
77
77
  # has not been edited directly by human users. bleep blorp.
78
78
  def pristine?