card 1.16.15 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/config/initializers/recaptcha.rb +21 -4
  4. data/db/migrate_core_cards/20130823192433_add_style_cards.rb +1 -1
  5. data/db/migrate_core_cards/20140512155840_add_script_cards.rb +1 -1
  6. data/db/migrate_core_cards/20140629222005_add_email_cards.rb +2 -2
  7. data/db/migrate_core_cards/20150202143810_import_bootstrap_layout.rb +1 -1
  8. data/db/migrate_core_cards/20150528084659_add_session_cardtype.rb +1 -1
  9. data/db/migrate_core_cards/20150610180019_add_recaptcha_key_and_admin_info_cards.rb +63 -0
  10. data/db/migrate_core_cards/20150724123438_update_file_and_image_cards.rb +1 -1
  11. data/db/migrate_core_cards/20150903130006_attachment_upload_cards.rb +1 -1
  12. data/db/schema.rb +1 -1
  13. data/db/seed/new/card_actions.yml +602 -394
  14. data/db/seed/new/card_acts.yml +595 -1
  15. data/db/seed/new/card_changes.yml +26282 -10262
  16. data/db/seed/new/card_references.yml +1252 -1084
  17. data/db/seed/new/cards.yml +1899 -1423
  18. data/db/seed/test/fixtures/card_actions.yml +1653 -1413
  19. data/db/seed/test/fixtures/card_acts.yml +1063 -445
  20. data/db/seed/test/fixtures/card_changes.yml +29674 -13637
  21. data/db/seed/test/fixtures/card_references.yml +1976 -1815
  22. data/db/seed/test/fixtures/cards.yml +3194 -2719
  23. data/lib/card.rb +14 -13
  24. data/lib/card/auth.rb +10 -6
  25. data/lib/card/cache.rb +58 -120
  26. data/lib/card/cache/persistent.rb +50 -0
  27. data/lib/card/cache/temporary.rb +38 -0
  28. data/lib/card/chunk.rb +34 -25
  29. data/lib/card/content.rb +3 -3
  30. data/lib/card/env.rb +3 -0
  31. data/lib/card/format.rb +56 -53
  32. data/lib/card/migration.rb +6 -2
  33. data/lib/card/name.rb +9 -1
  34. data/lib/card/query.rb +1 -1
  35. data/lib/card/reference.rb +17 -11
  36. data/lib/card/set.rb +1 -1
  37. data/lib/card/subcards.rb +6 -6
  38. data/lib/card/view_cache.rb +45 -28
  39. data/lib/generators/card/migration/templates/card_migration.erb +1 -2
  40. data/mod/01_core/chunk/include.rb +71 -48
  41. data/mod/01_core/chunk/link.rb +6 -3
  42. data/mod/01_core/chunk/query_reference.rb +38 -29
  43. data/mod/01_core/chunk/reference.rb +23 -24
  44. data/mod/01_core/set/all/collection.rb +1 -1
  45. data/mod/01_core/set/all/fetch.rb +39 -12
  46. data/mod/01_core/set/all/permissions.rb +2 -4
  47. data/mod/01_core/set/all/references.rb +50 -75
  48. data/mod/01_core/set/all/rules.rb +19 -18
  49. data/mod/01_core/set/all/subcards.rb +1 -1
  50. data/mod/01_core/set/all/templating.rb +31 -88
  51. data/mod/01_core/set/all/tracked_attributes.rb +7 -14
  52. data/mod/01_core/set/all/utils.rb +77 -66
  53. data/mod/01_core/set_pattern/07_type_plus_right.rb +6 -3
  54. data/mod/01_core/spec/set/all/fetch_spec.rb +148 -96
  55. data/mod/01_core/spec/set/all/templating_spec.rb +49 -40
  56. data/mod/01_core/spec/set/all/trash_spec.rb +1 -1
  57. data/mod/01_history/set/all/actions.rb +1 -1
  58. data/mod/02_basic_types/set/all/base.rb +13 -7
  59. data/mod/02_basic_types/set/all/rss.rb +17 -22
  60. data/mod/02_basic_types/set/type/plain_text.rb +5 -2
  61. data/mod/02_basic_types/spec/set/all/base_spec.rb +1 -0
  62. data/mod/02_basic_types/spec/set/all/rss_spec.rb +7 -6
  63. data/mod/03_machines/lib/javascript/wagn.js.coffee +22 -9
  64. data/mod/03_machines/set/right/machine_output.rb +1 -1
  65. data/mod/04_settings/lib/card/setting.rb +45 -31
  66. data/mod/04_settings/set/right/structure.rb +47 -1
  67. data/mod/04_settings/set/self/default_html_view.rb +2 -0
  68. data/mod/04_settings/set/self/follow_fields.rb +2 -0
  69. data/mod/04_settings/set/self/recent_settings.rb +1 -1
  70. data/mod/05_standard/file/favicon/image-icon.png +0 -0
  71. data/mod/05_standard/file/favicon/image-large.png +0 -0
  72. data/mod/05_standard/file/favicon/image-medium.png +0 -0
  73. data/mod/05_standard/file/favicon/image-original.png +0 -0
  74. data/mod/05_standard/file/favicon/image-small.png +0 -0
  75. data/mod/05_standard/set/all/links.rb +27 -26
  76. data/mod/05_standard/set/all/rich_html/editing.rb +1 -1
  77. data/mod/05_standard/set/all/rich_html/toolbar.rb +1 -1
  78. data/mod/05_standard/set/rstar/rules.rb +20 -325
  79. data/mod/05_standard/set/rstar/rules_editor.rb +362 -0
  80. data/mod/05_standard/set/self/admin_info.rb +82 -0
  81. data/mod/05_standard/set/self/all.rb +16 -10
  82. data/mod/05_standard/set/self/head.rb +20 -19
  83. data/mod/05_standard/set/type/signup.rb +0 -1
  84. data/mod/05_standard/spec/set/all/account_spec.rb +44 -43
  85. data/mod/05_standard/spec/set/right/account_spec.rb +4 -2
  86. data/mod/05_standard/spec/set/type/search_type_spec.rb +8 -0
  87. data/mod/05_standard/spec/set/type/signup_spec.rb +24 -17
  88. data/mod/06_bootstrap/set/all/bootstrap/helper.rb +1 -1
  89. data/spec/lib/card/cache_spec.rb +64 -70
  90. data/spec/lib/card/content_spec.rb +236 -150
  91. data/spec/lib/card/reference_spec.rb +22 -38
  92. data/spec/lib/card/subcards_spec.rb +38 -0
  93. data/spec/lib/card/view_cache_spec.rb +8 -0
  94. data/spec/spec_helper.rb +1 -1
  95. data/tmpsets/set/mod001-01_core/all/collection.rb +77 -74
  96. data/tmpsets/set/mod001-01_core/all/content.rb +14 -16
  97. data/tmpsets/set/mod001-01_core/all/fetch.rb +137 -110
  98. data/tmpsets/set/mod001-01_core/all/name.rb +58 -40
  99. data/tmpsets/set/mod001-01_core/all/pattern.rb +12 -11
  100. data/tmpsets/set/mod001-01_core/all/permissions.rb +125 -117
  101. data/tmpsets/set/mod001-01_core/all/phases.rb +2 -1
  102. data/tmpsets/set/mod001-01_core/all/references.rb +52 -77
  103. data/tmpsets/set/mod001-01_core/all/rules.rb +47 -53
  104. data/tmpsets/set/mod001-01_core/all/templating.rb +31 -87
  105. data/tmpsets/set/mod001-01_core/all/tracked_attributes.rb +12 -21
  106. data/tmpsets/set/mod001-01_core/all/trash.rb +4 -1
  107. data/tmpsets/set/mod001-01_core/all/type.rb +23 -21
  108. data/tmpsets/set/mod001-01_core/all/utils.rb +80 -64
  109. data/tmpsets/set/mod002-01_history/all/actions.rb +20 -16
  110. data/tmpsets/set/mod002-01_history/all/history.rb +18 -13
  111. data/tmpsets/set/mod003-02_basic_types/all/base.rb +37 -10
  112. data/tmpsets/set/mod003-02_basic_types/all/rss.rb +17 -22
  113. data/tmpsets/set/mod003-02_basic_types/type/plain_text.rb +5 -2
  114. data/tmpsets/set/mod003-02_basic_types/type/pointer.rb +51 -39
  115. data/tmpsets/set/mod004-03_machines/right/machine_output.rb +10 -6
  116. data/tmpsets/set/mod005-04_settings/abstract/permission.rb +10 -5
  117. data/tmpsets/set/mod005-04_settings/right/structure.rb +47 -1
  118. data/tmpsets/set/mod005-04_settings/self/recent_settings.rb +1 -0
  119. data/tmpsets/set/mod005-04_settings/type/setting.rb +4 -1
  120. data/tmpsets/set/mod006-05_email/all/follow.rb +45 -54
  121. data/tmpsets/set/mod006-05_email/all/notify.rb +88 -73
  122. data/tmpsets/set/mod006-05_email/right/followers.rb +17 -14
  123. data/tmpsets/set/mod006-05_email/self/follow_defaults.rb +22 -18
  124. data/tmpsets/set/mod006-05_email/type/email_template.rb +1 -1
  125. data/tmpsets/set/mod007-05_standard/abstract/attachment.rb +94 -67
  126. data/tmpsets/set/mod007-05_standard/all/account.rb +18 -20
  127. data/tmpsets/set/mod007-05_standard/all/comment.rb +51 -29
  128. data/tmpsets/set/mod007-05_standard/all/error.rb +129 -99
  129. data/tmpsets/set/mod007-05_standard/all/links.rb +27 -26
  130. data/tmpsets/set/mod007-05_standard/all/rich_html/content.rb +115 -103
  131. data/tmpsets/set/mod007-05_standard/all/rich_html/editing.rb +112 -78
  132. data/tmpsets/set/mod007-05_standard/all/rich_html/form.rb +123 -81
  133. data/tmpsets/set/mod007-05_standard/all/rich_html/modal.rb +15 -58
  134. data/tmpsets/set/mod007-05_standard/all/rich_html/toolbar.rb +2 -2
  135. data/tmpsets/set/mod007-05_standard/right/account.rb +71 -75
  136. data/tmpsets/set/mod007-05_standard/right/email.rb +16 -13
  137. data/tmpsets/set/mod007-05_standard/right/password.rb +20 -12
  138. data/tmpsets/set/mod007-05_standard/right/status.rb +2 -2
  139. data/tmpsets/set/mod007-05_standard/right/token.rb +49 -2
  140. data/tmpsets/set/mod007-05_standard/rstar/rules.rb +20 -325
  141. data/tmpsets/set/mod007-05_standard/self/all.rb +16 -10
  142. data/tmpsets/set/mod007-05_standard/self/head.rb +76 -62
  143. data/tmpsets/set/mod007-05_standard/self/search.rb +45 -22
  144. data/tmpsets/set/mod007-05_standard/self/signin.rb +14 -12
  145. data/tmpsets/set/mod007-05_standard/type/cardtype.rb +13 -11
  146. data/tmpsets/set/mod007-05_standard/type/file.rb +1 -1
  147. data/tmpsets/set/mod007-05_standard/type/search_type.rb +3 -2
  148. data/tmpsets/set/mod007-05_standard/type/set.rb +20 -16
  149. data/tmpsets/set/mod007-05_standard/type/signup.rb +19 -25
  150. data/tmpsets/set/mod007-05_standard/type/user.rb +1 -1
  151. data/tmpsets/set/mod008-06_bootstrap/all/bootstrap/helper.rb +1 -1
  152. data/tmpsets/set_pattern/106-type_plus_right.rb +6 -3
  153. metadata +11 -2
@@ -4,10 +4,10 @@ class Card; module Set; module All; module Content; extend Card::Set
4
4
  ::Card.error_codes[:conflict] = [:conflict, 409]
5
5
 
6
6
  def content
7
- db_content or (new_card? && template.db_content)
7
+ db_content || (new_card? && template.db_content)
8
8
  end
9
9
 
10
- def content=(value)
10
+ def content= value
11
11
  self.db_content = value
12
12
  end
13
13
 
@@ -16,7 +16,7 @@ def raw_content
16
16
  end
17
17
 
18
18
  format do
19
- def chunk_list #override to customize by set
19
+ def chunk_list # override to customize by set
20
20
  :default
21
21
  end
22
22
  end
@@ -26,37 +26,36 @@ def label
26
26
  end
27
27
 
28
28
  def creator
29
- Card[ creator_id ]
29
+ Card[creator_id]
30
30
  end
31
31
 
32
32
  def updater
33
- Card[ updater_id ]
33
+ Card[updater_id]
34
34
  end
35
35
 
36
36
  def clean_html?
37
37
  true
38
38
  end
39
39
 
40
- def history?
41
- false
42
- end
43
-
44
- def save_content_draft content
40
+ def save_content_draft _content
45
41
  clear_drafts
46
42
  end
47
43
 
48
44
  def clear_drafts
49
- drafts.created_by(Card::Auth.current_id).each do |draft|
50
- draft.delete
51
- end
45
+ drafts.created_by(Card::Auth.current_id).each(&:delete)
52
46
  end
53
47
 
54
- event :save_draft, before: :store, on: :update, when: proc{ |c| Env.params['draft'] == 'true' } do
48
+ def last_draft_content
49
+ drafts.last.card_changes.last.value
50
+ end
51
+
52
+ event :save_draft,
53
+ before: :store, on: :update,
54
+ when: proc { Env.params['draft'] == 'true' } do
55
55
  save_content_draft content
56
56
  abort :success
57
57
  end
58
58
 
59
-
60
59
  event :set_default_content, on: :create, before: :approve do
61
60
  if !db_content_changed? && template && template.db_content.present?
62
61
  self.db_content = template.db_content
@@ -64,6 +63,5 @@ event :set_default_content, on: :create, before: :approve do
64
63
  end
65
64
 
66
65
 
67
-
68
66
  # ~~~~~~~~~~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/01_core/set/all/content.rb ~~~~~~~~~~~
69
67
  end;end;end;end;
@@ -3,10 +3,9 @@ class Card; module Set; module All; module Fetch; extend Card::Set
3
3
  # ~~~~~~~~~~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/01_core/set/all/fetch.rb ~~~~~~~~~~~
4
4
  # = Card#fetch
5
5
  #
6
- # A multipurpose retrieval operator that incorporates caching, "virtual" card retrieval
7
-
6
+ # A multipurpose retrieval operator that integrates caching, database lookups,
7
+ # and "virtual" card construction
8
8
  module ClassMethods
9
-
10
9
  # === fetch
11
10
  #
12
11
  # looks for cards in
@@ -26,49 +25,44 @@ module ClassMethods
26
25
  # :local_only Use only local cache for lookup and storing
27
26
  # new: { card opts } Return a new card when not found
28
27
  #
29
- def fetch mark, opts = {}
28
+ def fetch mark, opts={}
30
29
  validate_fetch_opts! opts
31
- mark = normalize_mark mark
30
+ mark = normalize_mark mark, opts
32
31
 
33
- if mark.present?
34
- card, mark, needs_caching = fetch_from_cache_or_db mark, opts
35
- else
36
- return unless opts[:new]
37
- end
32
+ card, needs_caching = fetch_existing mark, opts
38
33
 
39
- if mark.is_a?(Integer)
40
- return if card.nil?
41
- elsif card && card.new_card? && opts[:new].present?
42
- return card.renew(opts)
43
- elsif !card || (card.type_unknown? && !skip_type_lookup?(opts))
34
+ if (new_card = new_for_cache card, mark, opts)
35
+ card = new_card
44
36
  needs_caching = true
45
- card = new_for_cache mark, opts # new (or improved) card for cache
46
37
  end
47
38
 
39
+ return if card.nil?
48
40
  write_to_cache card, opts if needs_caching
41
+ standard_fetch_results card, mark, opts
42
+ end
49
43
 
44
+ def standard_fetch_results card, mark, opts
50
45
  if card.new_card?
51
46
  case
52
47
  when opts[:new].present? then return card.renew(opts)
53
48
  when opts[:new] # noop for empty hash
54
49
  when opts[:skip_virtual] then return nil
55
50
  end
56
- card.rename_from_mark mark unless opts[:local_only]
51
+ card.name_from_mark! mark, opts
57
52
  end
58
53
  # need to load modules here to call the right virtual? method
59
54
  card.include_set_modules unless opts[:skip_modules]
60
55
  card if opts[:new] || card.known?
61
56
  end
62
57
 
63
- def fetch_local mark, opts = {}
64
- fetch mark, opts.merge(:local_only=>true)
58
+ def fetch_soft mark, opts={}
59
+ fetch mark, opts.merge(local_only: true)
65
60
  end
66
61
 
67
- def fetch_id mark
62
+ def fetch_id mark, opts={}
63
+ mark = normalize_mark mark, opts
68
64
  if mark.is_a?(Integer)
69
65
  mark
70
- elsif mark.is_a?(Symbol) && Card::Codename[mark]
71
- Card::Codename[mark]
72
66
  else
73
67
  card = quick_fetch mark.to_s
74
68
  card && card.id
@@ -79,7 +73,7 @@ module ClassMethods
79
73
  fetch mark, skip_virtual: true, skip_modules: true
80
74
  end
81
75
 
82
- def assign_or_initialize_by name, attributes, fetch_opts = {}
76
+ def assign_or_initialize_by name, attributes, fetch_opts={}
83
77
  if (known_card = Card.fetch(name, fetch_opts))
84
78
  known_card.refresh.assign_attributes attributes
85
79
  known_card
@@ -102,24 +96,31 @@ module ClassMethods
102
96
  card.present?
103
97
  end
104
98
 
105
- def expire name, subcards = false
99
+ def expire_hard name
100
+ return unless Card.cache.hard
101
+ key = name.to_name.key
102
+ Card.cache.hard.delete key
103
+ Card.cache.hard.delete "~#{card.id}" if card.id
104
+ end
105
+
106
+ def expire name, subcards=false
106
107
  # note: calling instance method breaks on dirty names
107
108
  key = name.to_name.key
108
- if card = Card.cache.read(key)
109
- if subcards
110
- card.expire_subcards
111
- else
112
- card.preserve_subcards
113
- end
114
- Card.cache.delete key
115
- Card.cache.delete "~#{card.id}" if card.id
109
+ return unless (card = Card.cache.read key)
110
+ if subcards
111
+ card.expire_subcards
112
+ else
113
+ card.preserve_subcards
116
114
  end
117
- # Rails.logger.warn "expiring #{name}, #{card.inspect}"
115
+ Card.cache.delete key
116
+ Card.cache.delete "~#{card.id}" if card.id
118
117
  end
119
118
 
120
119
  # set_names reverse map (cached)
121
- def members key
122
- (v=Card.cache.read "$#{key}").nil? ? [] : v.keys
120
+ # FIXME: move to set handling
121
+ def cached_set_members key
122
+ set_cache_list = Card.cache.read "$#{key}"
123
+ set_cache_list.nil? ? [] : set_cache_list.keys
123
124
  end
124
125
 
125
126
  def set_members set_names, key
@@ -138,9 +139,8 @@ module ClassMethods
138
139
  end
139
140
 
140
141
  def validate_fetch_opts! opts
141
- if opts[:new] && opts[:skip_virtual]
142
- fail Card::Error, 'fetch called with new args and skip_virtual'
143
- end
142
+ return unless opts[:new] && opts[:skip_virtual]
143
+ fail Card::Error, 'fetch called with new args and skip_virtual'
144
144
  end
145
145
 
146
146
  def cache
@@ -148,48 +148,65 @@ module ClassMethods
148
148
  end
149
149
 
150
150
  def fetch_from_cache cache_key, local_only=false
151
- if Card.cache
152
- if local_only
153
- Card.cache.read_local cache_key
154
- else
155
- Card.cache.read cache_key
156
- end
151
+ return unless Card.cache
152
+ if local_only
153
+ Card.cache.soft.read cache_key
154
+ else
155
+ Card.cache.read cache_key
156
+ end
157
+ end
158
+
159
+ def parse_mark! mark
160
+ # return mark_type, mark_value, and absolutized mark
161
+ if mark.is_a? Integer
162
+ [:id, mark]
163
+ else
164
+ [:key, mark.key]
157
165
  end
158
166
  end
159
167
 
160
- def fetch_from_cache_or_db mark, opts
161
- needs_caching = false
162
- mark_type = mark.is_a?(Integer) ? :id : :key
163
- expanded_mark = expand_mark mark, opts
164
- card = send("fetch_from_cache_by_#{mark_type}",
165
- expanded_mark, opts[:local_only])
168
+ def fetch_existing mark, opts
169
+ return [nil, false] unless mark.present?
170
+ mark_type, mark_key = parse_mark! mark
171
+ needs_caching = false # until proven true :)
166
172
 
167
- if card.nil? || (opts[:look_in_trash] && card.new_card? && !card.trash)
168
- query = { mark_type => expanded_mark }
169
- query[:trash] = false unless opts[:look_in_trash]
170
- card = fetch_from_db query
171
- needs_caching = card && !card.trash
172
- card.restore_subcards if card
173
+ # look in cache
174
+ card = send "fetch_from_cache_by_#{mark_type}", mark_key, opts[:local_only]
175
+
176
+ if retrieve_from_db?(card, opts)
177
+ # look in db if needed
178
+ card = fetch_from_db mark_type, mark_key, opts
179
+ needs_caching = !card.nil? && !card.trash
173
180
  end
174
181
 
175
- [card, mark, needs_caching]
182
+ [card, needs_caching]
176
183
  end
177
184
 
178
- def fetch_from_cache_by_id id, local_only = false
179
- if name = fetch_from_cache("~#{id}", local_only)
180
- fetch_from_cache name, local_only
181
- end
185
+ def retrieve_from_db? card, opts
186
+ card.nil? || (opts[:look_in_trash] && card.new_card? && !card.trash)
182
187
  end
183
188
 
184
- def fetch_from_cache_by_key key, local_only = false
189
+ def fetch_from_cache_by_id id, local_only=false
190
+ name = fetch_from_cache "~#{id}", local_only
191
+ fetch_from_cache name, local_only if name
192
+ end
193
+
194
+ def fetch_from_cache_by_key key, local_only=false
185
195
  fetch_from_cache key, local_only
186
196
  end
187
197
 
188
- def fetch_from_db query
189
- Card.where(query).take
198
+ def fetch_from_db mark_type, mark_key, opts
199
+ query = { mark_type => mark_key }
200
+ query[:trash] = false unless opts[:look_in_trash]
201
+ card = Card.where(query).take
202
+ card.restore_subcards if card
203
+ card
190
204
  end
191
205
 
192
- def new_for_cache name, opts
206
+ def new_for_cache card, name, opts
207
+ return if name.is_a? Integer
208
+ return if !name.present? && !opts[:new]
209
+ return unless !card || (card.type_unknown? && !skip_type_lookup?(opts))
193
210
  new name: name,
194
211
  skip_modules: true,
195
212
  skip_type_lookup: skip_type_lookup?(opts)
@@ -200,53 +217,42 @@ module ClassMethods
200
217
  # different from the cached variant
201
218
  # and can postpone type lookup for the cached variant
202
219
  # if skipping virtual no need to look for actual type
203
- opts[:skip_virtual] || opts[:new].present?
220
+ opts[:skip_virtual] || opts[:new].present? || opts[:skip_type_lookup]
204
221
  end
205
222
 
206
223
  def write_to_cache card, opts
207
224
  if opts[:local_only]
208
- write_to_local_cache card
225
+ write_to_soft_cache card
209
226
  elsif Card.cache
210
227
  Card.cache.write card.key, card
211
228
  Card.cache.write "~#{card.id}", card.key if card.id && card.id != 0
212
229
  end
213
230
  end
214
231
 
215
- def write_to_local_cache card
216
- if Card.cache
217
- Card.cache.write_local card.key, card
218
- Card.cache.write_local "~#{card.id}", card.key if card.id && card.id != 0
219
- end
220
- end
221
-
222
- def expand_mark mark, opts
223
- if mark.is_a?(Integer)
224
- mark
225
- else
226
- fullname_from_name(mark, opts[:new]).key
227
- end
232
+ def write_to_soft_cache card
233
+ return unless Card.cache
234
+ Card.cache.soft.write card.key, card
235
+ Card.cache.soft.write "~#{card.id}", card.key if card.id && card.id != 0
228
236
  end
229
237
 
230
- def normalize_mark mark
238
+ def normalize_mark mark, opts
231
239
  case mark
232
- when String
233
- case mark
234
- when /^\~(\d+)$/ # get by id
235
- $1.to_i
236
- when /^\:(\w+)$/ # get by codename
237
- Card::Codename[$1.to_sym]
238
- else
239
- mark
240
+ when Symbol then Card::Codename[mark]
241
+ when Integer then mark.to_i
242
+ when String, SmartName
243
+ # there are some situations where this breaks if we use Card::Name
244
+ # rather than SmartName, which would seem more correct.
245
+ # very hard to reproduce, not captured in a spec :(
246
+ case mark.to_s
247
+ when /^\~(\d+)$/ then $1.to_i # id
248
+ when /^\:(\w+)$/ then Card::Codename[$1.to_sym] # codename
249
+ else fullname_from_mark mark, opts[:new] # name
240
250
  end
241
- when Symbol
242
- Card::Codename[mark] # id from codename
243
- else
244
- mark
245
251
  end
246
252
  end
247
253
 
248
- def fullname_from_name name, new_opts = {}
249
- if new_opts && supercard = new_opts[:supercard]
254
+ def fullname_from_mark name, new_opts={}
255
+ if new_opts && (supercard = new_opts[:supercard])
250
256
  name.to_name.to_absolute_name supercard.name
251
257
  else
252
258
  name.to_name
@@ -256,41 +262,62 @@ end
256
262
 
257
263
  # ~~~~~~~~~~ Instance ~~~~~~~~~~~~~
258
264
 
259
- def fetch opts = {}
260
- if traits = opts.delete(:trait)
261
- traits = Array.wrap traits
262
- traits.inject(self) do |card, trait|
263
- Card.fetch card.cardname.trait(trait), opts
264
- end
265
+ def fetch opts={}
266
+ traits = opts.delete(:trait)
267
+ return unless traits
268
+ # should this fail as an incorrect api call?
269
+ traits = Array.wrap traits
270
+ traits.inject(self) do |card, trait|
271
+ Card.fetch card.cardname.trait(trait), opts
265
272
  end
266
273
  end
267
274
 
268
- def renew args = {}
275
+ def renew args={}
269
276
  opts = args[:new].clone
277
+ handle_default_content opts
270
278
  opts[:name] ||= cardname
271
279
  opts[:skip_modules] = args[:skip_modules]
272
280
  Card.new opts
273
281
  end
274
282
 
283
+ def handle_default_content opts
284
+ if (default_content = opts.delete(:default_content)) && db_content.blank?
285
+ opts[:content] ||= default_content
286
+ elsif db_content.present? && !opts[:content]
287
+ # don't overwrite existing content
288
+ opts[:content] = db_content
289
+ end
290
+ end
291
+
275
292
  def expire_pieces
276
293
  cardname.piece_names.each do |piece|
277
294
  Card.expire piece, !cardname.field_of?(piece)
278
295
  end
279
296
  end
280
297
 
281
- def expire subcards = false
282
- # Rails.logger.warn "expiring i:#{id}, #{inspect}"
298
+ def expire_hard
299
+ return unless Card.cache.hard
300
+ Card.cache.hard.delete key
301
+ Card.cache.hard.delete "~#{id}" if id
302
+ end
303
+
304
+ def expire_soft subcards=false
283
305
  if subcards
284
306
  expire_subcards
285
307
  else
286
308
  preserve_subcards
287
309
  end
288
- Card.cache.delete key
289
- Card.cache.delete "~#{id}" if id
310
+ Card.cache.soft.delete key
311
+ Card.cache.soft.delete "~#{id}" if id
290
312
  end
291
313
 
292
- def refresh force = false
293
- if force || self.frozen? || self.readonly?
314
+ def expire subcards=false
315
+ expire_hard
316
+ expire_soft subcards
317
+ end
318
+
319
+ def refresh force=false
320
+ if force || frozen? || readonly?
294
321
  fresh_card = self.class.find id
295
322
  fresh_card.include_set_modules
296
323
  fresh_card
@@ -307,12 +334,12 @@ def type_unknown?
307
334
  type_id.nil?
308
335
  end
309
336
 
310
- def rename_from_mark mark
337
+ def name_from_mark! mark, opts
338
+ return if opts[:local_only]
311
339
  return unless mark && mark.to_s != name
312
340
  self.name = mark.to_s
313
341
  end
314
342
 
315
343
 
316
-
317
344
  # ~~~~~~~~~~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/01_core/set/all/fetch.rb ~~~~~~~~~~~
318
345
  end;end;end;end;