card 1.17.1 → 1.17.2

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/config/initializers/recaptcha.rb +27 -19
  4. data/db/migrate/20160122153608_new_indeces.rb +10 -0
  5. data/db/migrate_core_cards/20130411191151_renaming_for_menu.rb +2 -2
  6. data/db/migrate_core_cards/20140317035504_account_requests_to_signups.rb +2 -2
  7. data/db/migrate_core_cards/20150202143810_import_bootstrap_layout.rb +2 -2
  8. data/db/migrate_core_cards/20150807205221_create_references_for_search_cards.rb +4 -2
  9. data/db/schema.rb +5 -1
  10. data/db/version.txt +1 -1
  11. data/lib/card.rb +3 -3
  12. data/lib/card/reference.rb +68 -52
  13. data/mod/01_core/chunk/query_reference.rb +1 -1
  14. data/mod/01_core/set/all/collection.rb +1 -1
  15. data/mod/01_core/set/all/name.rb +27 -65
  16. data/mod/01_core/set/all/pattern.rb +6 -3
  17. data/mod/01_core/set/all/references.rb +135 -62
  18. data/mod/01_core/set/all/tracked_attributes.rb +1 -1
  19. data/mod/01_core/set/all/utils.rb +2 -2
  20. data/mod/01_core/spec/set/all/references_spec.rb +4 -3
  21. data/mod/01_core/spec/set/all/tracked_attributes_spec.rb +16 -22
  22. data/mod/01_history/lib/card/act.rb +32 -30
  23. data/mod/01_history/lib/card/change.rb +26 -18
  24. data/mod/01_history/set/all/history.rb +1 -1
  25. data/mod/04_settings/set/right/structure.rb +1 -1
  26. data/mod/05_email/set/all/notify.rb +1 -1
  27. data/mod/05_email/spec/set/right/followers_spec.rb +1 -1
  28. data/mod/05_standard/set/all/rich_html/editing.rb +42 -45
  29. data/mod/05_standard/set/type/list.rb +2 -2
  30. data/mod/05_standard/spec/set/self/all_spec.rb +3 -3
  31. data/mod/05_standard/spec/set/type/list_spec.rb +3 -3
  32. data/mod/05_standard/spec/set/type/listed_by_spec.rb +2 -2
  33. data/mod/05_standard/spec/set/type/search_type_spec.rb +1 -1
  34. data/spec/lib/card/reference_spec.rb +30 -28
  35. data/spec/models/card/trash_spec.rb +63 -63
  36. data/spec/models/card/type_transition_spec.rb +34 -35
  37. metadata +3 -2
@@ -1,6 +1,6 @@
1
1
 
2
2
  def patterns
3
- @patterns ||= set_patterns.map { |sub| sub.new(self) }.compact
3
+ @patterns ||= set_patterns.map { |sub| sub.new self }.compact
4
4
  end
5
5
 
6
6
  def patterns_with_new
@@ -9,7 +9,10 @@ end
9
9
  alias_method_chain :patterns, :new
10
10
 
11
11
  def reset_patterns
12
- @set_mods_loaded = @patterns = @set_modules = @junction_only = @set_names = @template = @rule_set_keys = @virtual = nil
12
+ @patterns = nil
13
+ @template = @virtual = nil
14
+ @set_mods_loaded = @set_modules = @set_names = @rule_set_keys = nil
15
+ @junction_only = nil # only applies to set cards
13
16
  true
14
17
  end
15
18
 
@@ -45,7 +48,7 @@ end
45
48
 
46
49
  def set_names
47
50
  if @set_names.nil?
48
- @set_names = patterns.map &:to_s
51
+ @set_names = patterns.map(&:to_s)
49
52
  Card.set_members @set_names, key
50
53
  end
51
54
  @set_names
@@ -1,99 +1,172 @@
1
+ # frozen_string_literal: true
1
2
 
2
- PARTIAL_REF_CODE = 'P'
3
+ # Cards can refer to other cards in their content, eg via links and nests.
4
+ # The card that refers is the "referer", the card that is referred to is
5
+ # the "referee". The reference itself has its own class (Card::Reference),
6
+ # which handles id-based reference tracking.
3
7
 
4
- def name_referencers link_name=nil
5
- link_name = link_name.nil? ? key : link_name.to_name.key
6
- Card.joins(:references_to).where card_references: { referee_key: link_name }
8
+ PARTIAL_REF_CODE = 'P'.freeze
9
+
10
+ # cards that refer to self
11
+ def referers
12
+ references_in.map(&:referer_id).map(&Card.method(:fetch)).compact
13
+ end
14
+
15
+ # cards that include self
16
+ def includers
17
+ refs = references_in.where(ref_type: 'I')
18
+ refs.map(&:referer_id).map(&Card.method(:fetch)).compact
19
+ end
20
+
21
+ # cards that self refers to
22
+ def referees
23
+ references_out.map { |ref| Card.fetch ref.referee_key, new: {} }
7
24
  end
8
25
 
9
- def extended_referencers
10
- # FIXME: .. we really just need a number here.
11
- (descendants + [self]).map(&:referencers).flatten.uniq
26
+ # cards that self includes
27
+ def includees
28
+ refs = references_out.where(ref_type: 'I')
29
+ refs.map { |ref| Card.fetch ref.referee_key, new: {} }
30
+ end
31
+
32
+ # cards that refer to self by name
33
+ # (finds cards not yet linked by id)
34
+ def name_referers
35
+ Card.joins(:references_out).where card_references: { referee_key: key }
36
+ end
37
+
38
+ # cards that refer to self or any descendant
39
+ def family_referers
40
+ @family_referers ||= ([self] + descendants).map(&:referers).flatten.uniq
41
+ # FIXME: could be much more efficient!
12
42
  end
13
43
 
14
44
  # replace references in card content
15
- def replace_references old_name, new_name
45
+ def replace_reference_syntax old_name, new_name
16
46
  obj_content = Card::Content.new raw_content, self
17
47
  obj_content.find_chunks(Card::Chunk::Reference).select do |chunk|
18
48
  next unless (old_ref_name = chunk.referee_name)
19
49
  next unless (new_ref_name = old_ref_name.replace_part old_name, new_name)
20
50
  chunk.referee_name = chunk.replace_reference old_name, new_name
21
- old_references = Card::Reference.where(referee_key: old_ref_name.key)
22
- old_references.update_all referee_key: new_ref_name.key
51
+ refs = Card::Reference.where referee_key: old_ref_name.key
52
+ refs.update_all referee_key: new_ref_name.key
23
53
  end
24
54
 
25
55
  obj_content.to_s
26
56
  end
27
57
 
28
- # update entries in reference table
29
- def update_references rendered_content=nil
30
- raise 'update references should not be called on new cards' if id.nil?
31
-
32
- Card::Reference.delete_all_from self unless self.new_card?
33
-
34
- rendered_content ||= Card::Content.new raw_content, self
35
- rendered_content.find_chunks(Card::Chunk::Reference).each do |chunk|
36
- create_reference_to chunk
37
- end
58
+ # delete old references from this card's content, create new ones
59
+ def update_references_out
60
+ delete_references_out
61
+ create_references_out
38
62
  end
39
63
 
40
- def create_reference_to chunk
41
- referee_name = chunk.referee_name
42
- return false unless referee_name # eg no commented nest
43
-
44
- referee_name.piece_names.each do |name|
45
- next if name.key == key # don't create self reference
46
-
47
- # reference types:
48
- # L = link
49
- # I = inclusion
50
- # P = partial (i.e. the name is part of a compound name that is
51
- # referenced by a link or inclusion)
52
-
53
- # The partial type is needed to keep track of references of virtual cards.
54
- # For example a link [[A+*self]] won't make it to the reference table
55
- # because A+*self is virtual and doesn't have an id but when A's name is
56
- # changed we have to find and update that link.
57
- ref_type = name != referee_name ? PARTIAL_REF_CODE : chunk.reference_code
58
- Card::Reference.create!(
59
- referer_id: id,
60
- referee_id: Card.fetch_id(name),
61
- referee_key: name.key,
62
- ref_type: ref_type,
63
- present: 1
64
- )
64
+ # interpret references from this card's content and
65
+ # insert entries in reference table
66
+ def create_references_out
67
+ ref_hash = {}
68
+ content_obj = Card::Content.new raw_content, self
69
+ content_obj.find_chunks(Card::Chunk::Reference).each do |chunk|
70
+ interpret_reference ref_hash, chunk.referee_name, chunk.reference_code
65
71
  end
72
+ return if ref_hash.empty?
73
+ Card::Reference.mass_insert reference_values_array(ref_hash)
66
74
  end
67
75
 
68
- def referencers
69
- references_from.map(&:referer_id).map(&Card.method(:fetch)).compact
76
+ # delete references from this card
77
+ def delete_references_out
78
+ fail 'id required to delete references' if id.nil?
79
+ Card::Reference.delete_all referer_id: id
70
80
  end
71
81
 
72
- def includers
73
- references_from.where(ref_type: 'I')
74
- .map(&:referer_id).map(&Card.method(:fetch)).compact
82
+ # interpretation phase helps to prevent duplicate references
83
+ # results in hash like:
84
+ # { referee1_key: [referee1_id, referee1_type1, referee1_type2],
85
+ # referee2_key...
86
+ # }
87
+ def interpret_reference ref_hash, referee_name, ref_type
88
+ return unless referee_name # eg commented nest has no referee_name
89
+ referee_key = (referee_name = referee_name.to_name).key
90
+ return if referee_key == key # don't create self reference
91
+
92
+ referee_id = Card.fetch_id(referee_name)
93
+ ref_hash[referee_key] ||= [referee_id]
94
+ ref_hash[referee_key] << ref_type
95
+
96
+ interpret_partial_references ref_hash, referee_name unless referee_id
75
97
  end
76
98
 
77
- def referees
78
- references_to.map { |ref| Card.fetch ref.referee_key, new: {} }
99
+ # Partial references are needed to track references to virtual cards.
100
+ # For example a link to virual card [[A+*self]] won't have a referee_id,
101
+ # but when A's name is changed we have to find and update that link.
102
+ def interpret_partial_references ref_hash, referee_name
103
+ [referee_name.left, referee_name.right].each do |sidename|
104
+ interpret_reference ref_hash, sidename, PARTIAL_REF_CODE
105
+ end
79
106
  end
80
107
 
81
- def includees
82
- references_to.where(ref_type: 'I')
83
- .map { |ref| Card.fetch ref.referee_key, new: {} }
108
+ # translate interpreted reference hash into values array,
109
+ # removing duplicate and unnecessary ref_types
110
+ def reference_values_array ref_hash
111
+ values = []
112
+ ref_hash.each do |referee_key, hash_val|
113
+ referee_id = hash_val.shift || 'null'
114
+ ref_types = hash_val.uniq
115
+ ref_types.delete PARTIAL_REF_CODE if ref_types.size > 1
116
+ # partial references are not necessary if there are explicit references
117
+ ref_types.each do |ref_type|
118
+ values << [id, referee_id, "'#{referee_key}'", "'#{ref_type}'"]
119
+ end
120
+ end
121
+ values
84
122
  end
85
123
 
86
124
  protected
87
125
 
88
- event :refresh_references, after: :store, on: :save, changed: :content do
89
- update_references
126
+ # test for updating referer content & preload referer list
127
+ event :prepare_referer_update, before: :approve, on: :update, changed: :name do
128
+ self.update_referers = ![nil, false, 'false'].member?(update_referers)
129
+ family_referers
90
130
  end
91
131
 
92
- event :refresh_references_on_create, before: :refresh_references, on: :create do
93
- Card::Reference.update_existing_key self
94
- # FIXME: bogus blank default content is set on structured cards...
132
+ # when name changes, update references to card
133
+ event :refresh_references_in, after: :store, on: :save, changed: :name do
134
+ Card::Reference.unmap_referees id if @action == :update && !update_referers
135
+ Card::Reference.map_referees key, id
136
+ end
137
+
138
+ # when content changes, update references to other cards
139
+ event :refresh_references_out, after: :store, on: :save, changed: :content do
140
+ update_references_out
141
+ end
142
+
143
+ # clean up reference table when card is deleted
144
+ event :clear_references, after: :store, on: :delete do
145
+ delete_references_out
146
+ Card::Reference.unmap_referees id
147
+ end
148
+
149
+ # on rename, update names in cards that refer to self by name (as directed)
150
+ event :update_referer_content,
151
+ after: :store, on: :update, changed: :name,
152
+ when: proc { |c| c.update_referers } do
153
+ # FIXME: break into correct stages
154
+ Auth.as_bot do
155
+ family_referers.each do |card|
156
+ next if card == self || card.structure
157
+ card = card.refresh
158
+ card.db_content = card.replace_reference_syntax name_was, name
159
+ card.save!
160
+ end
161
+ end
95
162
  end
96
163
 
97
- event :refresh_references_on_delete, after: :store, on: :delete do
98
- Card::Reference.update_on_delete self
164
+ # on rename, when NOT updating referer content, update references to ensure
165
+ # that partial references are correctly tracked
166
+ # eg. A links to X+Y. if X+Y is renamed and we're not updating the link in A,
167
+ # then we need to be sure that A has a partial reference
168
+ event :update_referer_references_out,
169
+ after: :store, on: :update, changed: :name,
170
+ when: proc { |c| !c.update_referers } do
171
+ family_referers.map(&:update_references_out)
99
172
  end
@@ -141,5 +141,5 @@ end
141
141
  event :expire_related_names, before: :expire_related, changed: :name do
142
142
  # FIXME: look for opportunities to avoid instantiating the following
143
143
  descendants.each { |c| c.expire(true) }
144
- name_referencers.each { |c| c.expire(true) }
144
+ name_referers.each { |c| c.expire(true) }
145
145
  end
@@ -4,8 +4,8 @@ module ClassMethods
4
4
  Card.delete_trashed_files
5
5
  Card.where(trash: true).delete_all
6
6
  Card::Action.delete_cardless
7
- Card::Reference.repair_missing_referees
8
- Card::Reference.delete_missing_referers
7
+ Card::Reference.unmap_if_referee_missing
8
+ Card::Reference.delete_if_referer_missing
9
9
  Card.delete_tmp_files_of_cached_uploads
10
10
  end
11
11
 
@@ -1,8 +1,9 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  describe Card::Set::All::References do
4
- it "should replace references should work on inclusions inside links" do
5
- card = Card.create!(name: "ref test", content: "[[test_card|test{{test}}]]" )
6
- assert_equal "[[test_card|test{{best}}]]", card.replace_references("test", "best" )
4
+ it 'should replace references should work on inclusions inside links' do
5
+ card = Card.create! name: 'ref test', content: '[[test_card|test{{test}}]]'
6
+ assert_equal '[[test_card|test{{best}}]]',
7
+ card.replace_reference_syntax('test', 'best')
7
8
  end
8
9
  end
@@ -6,7 +6,7 @@ module RenameMethods
6
6
  content: card.content,
7
7
  # updater_id: card.updater_id,
8
8
  # revisions: card.actions.count,
9
- referencers: card.referencers.map(&:name).sort,
9
+ referers: card.referers.map(&:name).sort,
10
10
  referees: card.referees.map(&:name).sort,
11
11
  descendants: card.descendants.map(&:id).sort
12
12
  }
@@ -16,7 +16,7 @@ module RenameMethods
16
16
  attrs_before = name_invariant_attributes(card)
17
17
  actions_count_before = card.actions.count
18
18
  card.name = new_name
19
- card.update_referencers = true
19
+ card.update_referers = true
20
20
  card.save!
21
21
  expect(card.actions.count).to eq(actions_count_before + 1)
22
22
  assert_equal attrs_before, name_invariant_attributes(card)
@@ -119,13 +119,13 @@ describe Card::Set::All::TrackedAttributes do
119
119
  c = Card['Menu']
120
120
  c.name = 'manure'
121
121
  c.save!
122
- expect(Card['manure'].references_from.size).to eq(0)
122
+ expect(Card['manure'].references_in.size).to eq(0)
123
123
  end
124
124
 
125
125
  it 'picks up new references' do
126
126
  Card.create name: 'kinds of poop', content: '[[manure]]'
127
127
  assert_rename Card['Menu'], 'manure'
128
- expect(Card['manure'].references_from.size).to eq(2)
128
+ expect(Card['manure'].references_in.size).to eq(2)
129
129
  end
130
130
 
131
131
  it 'handles name variants' do
@@ -155,15 +155,9 @@ describe Card::Set::All::TrackedAttributes do
155
155
  end
156
156
 
157
157
  it 'test_update_descendants' do
158
- card_list = [
159
- Card['One+Two'],
160
- Card['One+Two+Three'],
161
- Card['Four+One'],
162
- Card['Four+One+Five']
163
- ]
164
-
165
- old_names = %w{ One+Two One+Two+Three Four+One Four+One+Five }
166
- new_names = %w{ Uno+Two Uno+Two+Three Four+Uno Four+Uno+Five }
158
+ old_names = %w( One+Two One+Two+Three Four+One Four+One+Five )
159
+ new_names = %w( Uno+Two Uno+Two+Three Four+Uno Four+Uno+Five )
160
+ card_list = old_names.map { |name| Card[name] }
167
161
 
168
162
  assert_equal old_names, card_list.map(&:name)
169
163
  Card['One'].update_attributes! name: 'Uno'
@@ -193,24 +187,24 @@ describe Card::Set::All::TrackedAttributes do
193
187
  expect(Card['Banana Card']).not_to be_nil
194
188
  end
195
189
 
196
- it 'test_rename_should_not_fail_when_updating_inaccessible_referencer' do
190
+ it 'test_rename_should_not_fail_when_updating_inaccessible_referer' do
197
191
  Card.create! name: 'Joe Card', content: 'Whattup'
198
192
  Card::Auth.as 'joe_admin' do
199
193
  Card.create! name: 'Admin Card', content: '[[Joe Card]]'
200
194
  end
201
195
  c = Card['Joe Card']
202
- c.update_attributes! name: 'Card of Joe', update_referencers: true
196
+ c.update_attributes! name: 'Card of Joe', update_referers: true
203
197
  assert_equal '[[Card of Joe]]', Card['Admin Card'].content
204
198
  end
205
199
 
206
- it 'test_rename_should_update_structured_referencer' do
200
+ it 'test_rename_should_update_structured_referer' do
207
201
  Card::Auth.as_bot do
208
202
  c = Card.create! name: 'Pit'
209
203
  Card.create! name: 'Orange', type: 'Fruit', content: '[[Pit]]'
210
204
  Card.create! name: 'Fruit+*type+*structure', content: 'this [[Pit]]'
211
205
 
212
206
  assert_equal 'this [[Pit]]', Card['Orange'].raw_content
213
- c.update_attributes! name: 'Seed', update_referencers: true
207
+ c.update_attributes! name: 'Seed', update_referers: true
214
208
  assert_equal 'this [[Seed]]', Card['Orange'].raw_content
215
209
  end
216
210
  end
@@ -260,14 +254,14 @@ describe Card::Set::All::TrackedAttributes do
260
254
  it 'test_renaming_card_with_self_link_should_not_hang' do
261
255
  c = Card['Dairy']
262
256
  c.name = 'Buttah'
263
- c.update_referencers = true
257
+ c.update_referers = true
264
258
  c.save!
265
259
  assert_equal '[[/new/{{_self|name}}|new]]', Card['Buttah'].content
266
260
  end
267
261
 
268
262
  it 'should rename card without updating references' do
269
263
  c = Card['Dairy']
270
- c.update_attributes name: 'Newt', update_referencers: false
264
+ c.update_attributes name: 'Newt', update_referers: false
271
265
  assert_equal '[[/new/{{_self|name}}|new]]', Card['Newt'].content
272
266
  end
273
267
  end
@@ -291,7 +285,7 @@ describe Card::Set::All::TrackedAttributes do
291
285
  c1 = Card['Blue']
292
286
  c2 = Card['blue includer 1']
293
287
  c3 = Card['blue includer 2']
294
- c1.update_attributes name: 'Red', update_referencers: true
288
+ c1.update_attributes name: 'Red', update_referers: true
295
289
  assert_equal '{{Red}}', Card.find(c2.id).content
296
290
  # NOTE these attrs pass through a hash stage that may not preserve order
297
291
  assert_equal '{{Red|closed;other:stuff}}', Card.find(c3.id).content
@@ -301,7 +295,7 @@ describe Card::Set::All::TrackedAttributes do
301
295
  c1 = Card['Blue']
302
296
  c2 = Card['blue includer 1']
303
297
  c1.update_attributes name: 'blue includer 1+color',
304
- update_referencers: true
298
+ update_referers: true
305
299
  assert_equal '{{blue includer 1+color}}', Card.find(c2.id).content
306
300
  end
307
301
 
@@ -310,7 +304,7 @@ describe Card::Set::All::TrackedAttributes do
310
304
  c2 = Card['blue linker 1']
311
305
  c3 = Card['blue linker 2']
312
306
  c1.reload.name = 'Red'
313
- c1.update_referencers = true
307
+ c1.update_referers = true
314
308
  c1.save!
315
309
  assert_equal '[[Red]]', Card.find(c2.id).content
316
310
  assert_equal '[[Red]]', Card.find(c3.id).content
@@ -2,39 +2,39 @@
2
2
  class Card
3
3
  class Act < ActiveRecord::Base
4
4
  before_save :set_actor
5
- has_many :actions, -> { order :id },
6
- { foreign_key: :card_act_id, inverse_of: :act, class_name: "Card::Action" }
5
+ has_many :actions,
6
+ -> { order :id },
7
+ foreign_key: :card_act_id,
8
+ inverse_of: :act,
9
+ class_name: 'Card::Action'
7
10
 
8
- belongs_to :actor, class_name: "Card"
11
+ belongs_to :actor, class_name: 'Card'
9
12
  belongs_to :card
10
- def set_actor
11
- self.actor_id ||= Auth.current_id
12
- end
13
13
 
14
- def self.delete_actionless
15
- Card::Act.where(
16
- "id NOT IN (?)",
17
- Card::Action.pluck("card_act_id"),
18
- ).delete_all
19
- end
14
+ class << self
15
+ def delete_actionless
16
+ joins(
17
+ 'LEFT JOIN card_actions '\
18
+ 'ON card_acts.id = card_actions.card_act_id'
19
+ ).where(
20
+ 'card_actions.id is null'
21
+ ).delete_all
22
+ end
20
23
 
21
- def self.find_all_with_actions_on card_ids, args={}
22
- sql = 'card_actions.card_id IN (:card_ids) AND ( (draft is not true) '
23
- sql << ( args[:with_drafts] ? 'OR actor_id = :current_user_id)' : ')' )
24
- vars = {card_ids: card_ids, current_user_id: Card::Auth.current_id }
25
- Card::Act.joins(:actions).where( sql, vars ).uniq.order(:id).reverse_order
24
+ def find_all_with_actions_on card_ids, args={}
25
+ sql = 'card_actions.card_id IN (:card_ids) AND ( (draft is not true) '
26
+ sql << (args[:with_drafts] ? 'OR actor_id = :current_user_id)' : ')')
27
+ vars = { card_ids: card_ids, current_user_id: Card::Auth.current_id }
28
+ joins(:actions).where(sql, vars).uniq.order(:id).reverse_order
29
+ end
26
30
  end
27
31
 
28
- # def actor
29
- # Card[ actor_id ]
30
- # end
31
-
32
- # def card
33
- # Card[ card_id ]
34
- # end
32
+ def set_actor
33
+ self.actor_id ||= Auth.current_id
34
+ end
35
35
 
36
36
  def action_on card_id
37
- actions.where( "card_id = #{card_id} and draft is not true" ).first
37
+ actions.where("card_id = #{card_id} and draft is not true").first
38
38
  end
39
39
 
40
40
  def main_action
@@ -47,20 +47,22 @@ class Card
47
47
 
48
48
  def relevant_drafts_for card
49
49
  drafts.select do |action|
50
- card.included_card_ids.include?(action.card_id) || (card.id == action.card_id)
50
+ card.included_card_ids.include?(action.card_id) ||
51
+ (card.id == action.card_id)
51
52
  end
52
53
  end
53
54
 
54
- def relevant_actions_for card, with_drafts=false
55
+ def relevant_actions_for card
55
56
  actions.select do |action|
56
- card.included_card_ids.include?(action.card_id) || (card.id == action.card_id)
57
+ card.included_card_ids.include?(action.card_id) ||
58
+ (card.id == action.card_id)
57
59
  end
58
60
  end
59
61
 
60
- private
62
+ private
63
+
61
64
  def timestamp_attributes_for_create
62
65
  super << :acted_at
63
66
  end
64
-
65
67
  end
66
68
  end