card 1.16.8 → 1.16.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/db/migrate_core_cards/{20150611203506_rails_inflection_updates.rb → 20120611203506_rails_inflection_updates.rb} +0 -0
- data/db/migrate_core_cards/20150326205655_bootswatch_themes.rb +0 -1
- data/db/migrate_core_cards/20150429090551_search_card_context.rb +1 -1
- data/db/migrate_core_cards/20150708224756_add_list_cards.rb +22 -0
- data/db/seed/new/card_actions.yml +789 -509
- data/db/seed/new/card_acts.yml +1 -1
- data/db/seed/new/card_changes.yml +2618 -1920
- data/db/seed/new/card_references.yml +1034 -901
- data/db/seed/new/cards.yml +2303 -1675
- data/db/seed/test/fixtures/card_actions.yml +1926 -1606
- data/db/seed/test/fixtures/card_acts.yml +354 -324
- data/db/seed/test/fixtures/card_changes.yml +5950 -5175
- data/db/seed/test/fixtures/card_references.yml +1861 -1630
- data/db/seed/test/fixtures/cards.yml +3768 -3048
- data/db/seed/test/seed.rb +121 -107
- data/lib/card.rb +2 -3
- data/lib/card/active_record_helper.rb +44 -0
- data/lib/card/auth.rb +51 -47
- data/lib/card/cache.rb +7 -3
- data/lib/card/codename.rb +7 -7
- data/lib/card/format.rb +2 -1
- data/lib/card/migration.rb +17 -16
- data/lib/card/name.rb +71 -20
- data/lib/card/set.rb +202 -166
- data/lib/card/simplecov_helper.rb +11 -7
- data/lib/card/subcards.rb +249 -0
- data/mod/01_core/set/all/collection.rb +1 -2
- data/mod/01_core/set/all/fetch.rb +167 -92
- data/mod/01_core/set/all/initialize.rb +8 -22
- data/mod/01_core/set/all/name.rb +128 -79
- data/mod/01_core/set/all/phases.rb +93 -95
- data/mod/01_core/set/all/subcards.rb +70 -0
- data/mod/01_core/set/all/tracked_attributes.rb +83 -59
- data/mod/01_core/set/all/trash.rb +14 -12
- data/mod/01_core/set/all/type.rb +3 -24
- data/mod/01_core/spec/set/all/initialize_spec.rb +44 -14
- data/mod/01_core/spec/set/all/permissions_spec.rb +206 -185
- data/mod/01_core/spec/set/all/tracked_attributes_spec.rb +0 -10
- data/mod/01_core/spec/set/all/trash_spec.rb +38 -13
- data/mod/01_core/spec/set/all/type_spec.rb +0 -19
- data/mod/01_history/set/all/content_history.rb +5 -3
- data/mod/01_history/set/all/history.rb +117 -82
- data/mod/02_basic_types/set/all/base.rb +50 -49
- data/mod/03_machines/lib/card/machine.rb +2 -1
- data/mod/03_machines/lib/javascript/wagn_mod.js.coffee +55 -17
- data/mod/03_machines/spec/set/type/javascript_spec.rb +18 -12
- data/mod/05_email/set/right/followers.rb +5 -5
- data/mod/05_email/set/right/following.rb +1 -1
- data/mod/05_email/set/type_plus_right/user/follow.rb +1 -1
- data/mod/05_standard/lib/carrier_wave/cardmount.rb +19 -11
- data/mod/05_standard/lib/file_uploader.rb +1 -1
- data/mod/05_standard/set/abstract/attachment.rb +20 -8
- data/mod/05_standard/set/all/list_changes.rb +43 -0
- data/mod/05_standard/set/all/rich_html/form.rb +21 -11
- data/mod/05_standard/set/all/rich_html/menu.rb +1 -1
- data/mod/05_standard/set/right/account.rb +5 -5
- data/mod/05_standard/set/self/head.rb +0 -1
- data/mod/05_standard/set/self/signin.rb +43 -35
- data/mod/05_standard/set/type/file.rb +9 -2
- data/mod/05_standard/set/type/list.rb +134 -0
- data/mod/05_standard/set/type/listed_by.rb +94 -0
- data/mod/05_standard/set/type/search_type.rb +62 -61
- data/mod/05_standard/set/type/signup.rb +94 -63
- data/mod/05_standard/set/type/user.rb +48 -39
- data/mod/05_standard/spec/set/all/account_spec.rb +1 -1
- data/mod/05_standard/spec/set/all/rich_html/form_spec.rb +2 -2
- data/mod/05_standard/spec/set/self/signin_spec.rb +23 -27
- data/mod/05_standard/spec/set/type/email_template_spec.rb +0 -2
- data/mod/05_standard/spec/set/type/list_spec.rb +140 -0
- data/mod/05_standard/spec/set/type/listed_by_spec.rb +157 -0
- data/mod/05_standard/spec/set/type/signup_spec.rb +38 -32
- data/spec/lib/card/subcards_spec.rb +126 -0
- metadata +14 -3
@@ -6,20 +6,24 @@ def card_simplecov_filters
|
|
6
6
|
add_filter 'spec/'
|
7
7
|
add_filter '/config/'
|
8
8
|
add_filter '/tasks/'
|
9
|
-
|
10
|
-
# filter all card mods
|
9
|
+
# filter all card mods
|
11
10
|
add_filter do |src_file|
|
12
11
|
src_file.filename =~ /tmp\// and not
|
13
|
-
/\d+-(.+\.rb)/.match(src_file.filename)
|
12
|
+
/\d+-(.+\.rb)/.match(src_file.filename) do |m|
|
13
|
+
Dir["mod/**/#{m[1].gsub("-","/").sub("/","/set/")}"].present?
|
14
|
+
end
|
14
15
|
end
|
15
|
-
|
16
|
-
# add group for each deck mod
|
16
|
+
# add group for each deck mod
|
17
17
|
Dir['mod/*'].map{ |path| path.sub('mod/','') }.each do |mod|
|
18
18
|
add_group mod.capitalize do |src_file|
|
19
|
-
src_file.filename =~ /mod\/#{mod}\// or
|
19
|
+
src_file.filename =~ /mod\/#{mod}\// or
|
20
20
|
(
|
21
21
|
src_file.filename =~ /tmp\// and
|
22
|
-
/\d+-(.+\.rb)/.match(src_file.filename)
|
22
|
+
match = /\d+-(.+\.rb)/.match(src_file.filename) do |m|
|
23
|
+
# '/set' is not in the path anymore after some updates
|
24
|
+
# but `set` exists in the path of the source files
|
25
|
+
Dir["mod/**/#{m[1].gsub("-","/").sub("/","/set/")}"].present?
|
26
|
+
end and
|
23
27
|
is_in_mod? src_file,mod
|
24
28
|
)
|
25
29
|
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
# API to create/update/delete additional cards together with the main card.
|
4
|
+
# The most common case is for fields but subcards don't have to be descendants.
|
5
|
+
#
|
6
|
+
# Example toghether with "my address" you want to create the subcards
|
7
|
+
# "my address+name", "my address+street", etc.
|
8
|
+
#
|
9
|
+
# Subcards can be added as card objects or attribute hashes.
|
10
|
+
|
11
|
+
class Card
|
12
|
+
def subcards
|
13
|
+
@subcards ||= Subcards.new(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def preserve_subcards
|
17
|
+
return unless subcards.present?
|
18
|
+
Card.cache.write_local subcards_cache_key, @subcards
|
19
|
+
end
|
20
|
+
|
21
|
+
def restore_subcards
|
22
|
+
cached_subcards = Card.cache.read_local(subcards_cache_key)
|
23
|
+
return unless cached_subcards
|
24
|
+
@subcards = cached_subcards
|
25
|
+
@subcards.context_card = self
|
26
|
+
end
|
27
|
+
|
28
|
+
def expire_subcards
|
29
|
+
Card.cache.delete_local subcards_cache_key
|
30
|
+
subcards.clear
|
31
|
+
end
|
32
|
+
|
33
|
+
def subcards_cache_key
|
34
|
+
"#{key}#SUBCARDS#"
|
35
|
+
end
|
36
|
+
|
37
|
+
class Subcards
|
38
|
+
attr_accessor :context_card, :keys
|
39
|
+
def initialize context_card
|
40
|
+
@context_card = context_card
|
41
|
+
@keys = ::Set.new
|
42
|
+
end
|
43
|
+
|
44
|
+
def clear
|
45
|
+
@keys.each do |key|
|
46
|
+
Card.cache.delete_local key
|
47
|
+
end
|
48
|
+
@keys = ::Set.new
|
49
|
+
end
|
50
|
+
|
51
|
+
def remove name_or_card
|
52
|
+
key = case name_or_card
|
53
|
+
when Card
|
54
|
+
name_or_card.key
|
55
|
+
when Symbol
|
56
|
+
fetch_subcard(name_or_card).key
|
57
|
+
else
|
58
|
+
name_or_card.to_name.key
|
59
|
+
end
|
60
|
+
|
61
|
+
key = absolutize_subcard_name(key).key unless @keys.include?(key)
|
62
|
+
@keys.delete key
|
63
|
+
removed_card = fetch_subcard key
|
64
|
+
Card.cache.delete_local key
|
65
|
+
removed_card
|
66
|
+
end
|
67
|
+
|
68
|
+
def add name_or_card_or_attr, card_or_attr=nil
|
69
|
+
if card_or_attr
|
70
|
+
name = name_or_card_or_attr
|
71
|
+
else
|
72
|
+
card_or_attr = name_or_card_or_attr
|
73
|
+
end
|
74
|
+
case card_or_attr
|
75
|
+
when Hash
|
76
|
+
args = card_or_attr
|
77
|
+
if name
|
78
|
+
new_by_attributes name, args
|
79
|
+
elsif args[:name]
|
80
|
+
new_by_attributes args.delete(:name), args
|
81
|
+
else
|
82
|
+
args.each_pair do |key, val|
|
83
|
+
case val
|
84
|
+
when String then new_by_attributes key, content: val
|
85
|
+
when Card
|
86
|
+
val.name = absolutize_subcard_name key
|
87
|
+
new_by_card val
|
88
|
+
else new_by_attributes key, val
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
when Card
|
93
|
+
new_by_card card_or_attr
|
94
|
+
when Symbol, String
|
95
|
+
new_by_attributes card_or_attr, {}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def rename old_name, new_name
|
100
|
+
return unless @keys.include? old_name.to_name.key
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
def << value
|
107
|
+
add value
|
108
|
+
end
|
109
|
+
|
110
|
+
def method_missing method, *args
|
111
|
+
return unless @keys.respond_to? method
|
112
|
+
@keys.send method, *args
|
113
|
+
end
|
114
|
+
|
115
|
+
def each_card
|
116
|
+
# fetch all cards first to avoid side effects
|
117
|
+
# e.g. deleting a user adds follow rules and +*account to subcards
|
118
|
+
# for deleting but deleting follow rules can remove +*account from the
|
119
|
+
# cache if it belongs to the rule cards
|
120
|
+
cards = @keys.map do |key|
|
121
|
+
fetch_subcard key
|
122
|
+
end
|
123
|
+
cards.each do |card|
|
124
|
+
yield(card) if card
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
alias_method :each, :each_card
|
129
|
+
|
130
|
+
def each_with_key
|
131
|
+
@keys.each do |key|
|
132
|
+
card = fetch_subcard(key)
|
133
|
+
yield(card, key) if card
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def []= name, card_or_attr
|
138
|
+
case card_or_attr
|
139
|
+
when Hash
|
140
|
+
new_by_attributes name, card_or_attr
|
141
|
+
when Card
|
142
|
+
new_by_card card_or_attr
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def [] name
|
147
|
+
card(name) || field(name)
|
148
|
+
end
|
149
|
+
|
150
|
+
def field name
|
151
|
+
key = field_name_to_key name
|
152
|
+
if @keys.include? key
|
153
|
+
fetch_subcard key
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def card name
|
158
|
+
return unless @keys.include? name.to_name.key
|
159
|
+
fetch_subcard name
|
160
|
+
end
|
161
|
+
|
162
|
+
def add_child name, args
|
163
|
+
add prepend_plus(name), args
|
164
|
+
end
|
165
|
+
|
166
|
+
def remove_child name_or_card
|
167
|
+
if name_or_card.is_a? Card
|
168
|
+
remove name_or_card
|
169
|
+
else
|
170
|
+
absolute_name = @context_card.cardname.field_name(name_or_card)
|
171
|
+
if @keys.include? absolute_name.key
|
172
|
+
remove absolute_name
|
173
|
+
else
|
174
|
+
remove @context_card.cardname.relative_field_name(name_or_card)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
alias_method :add_field, :add_child
|
180
|
+
alias_method :remove_field, :remove_child
|
181
|
+
|
182
|
+
def present?
|
183
|
+
@keys.present?
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def fetch_subcard key
|
189
|
+
Card.fetch key, local_only: true, new: {}
|
190
|
+
end
|
191
|
+
|
192
|
+
def prepend_plus name
|
193
|
+
case name
|
194
|
+
when Symbol
|
195
|
+
"+#{Card[name].name}"
|
196
|
+
when /^\+/
|
197
|
+
name
|
198
|
+
else
|
199
|
+
"+#{name}"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def field_name_to_key name
|
204
|
+
if @context_card.name =~ /^\+/
|
205
|
+
@context_card.cardname.relative_field_name(name).key
|
206
|
+
else
|
207
|
+
absolute_key = @context_card.cardname.field_name(name).key
|
208
|
+
if @keys.include? absolute_key
|
209
|
+
absolute_key
|
210
|
+
else
|
211
|
+
@context_card.cardname.relative_field_name(name).key
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def new_by_attributes name, attributes={}
|
217
|
+
absolute_name = absolutize_subcard_name name
|
218
|
+
if absolute_name.field_of?(@context_card.name) &&
|
219
|
+
(absolute_name.parts.size - @context_card.cardname.parts.size) > 2
|
220
|
+
left_card = new_by_attributes absolute_name.left
|
221
|
+
new_by_card left_card
|
222
|
+
left_card.new_by_attributes absolute_name, attributes
|
223
|
+
else
|
224
|
+
card = Card.assign_or_initialize_by absolute_name.s, attributes,
|
225
|
+
local_only: true
|
226
|
+
new_by_card card
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def absolutize_subcard_name name
|
231
|
+
if @context_card.name =~ /^\+/
|
232
|
+
name.to_name
|
233
|
+
else
|
234
|
+
name.to_name.to_absolute_name(@context_card.name)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def new_by_card card
|
239
|
+
card.supercard = @context_card
|
240
|
+
if !card.cardname.simple? &&
|
241
|
+
card.cardname.field_of?(@context_card.cardname)
|
242
|
+
card.superleft = @context_card
|
243
|
+
end
|
244
|
+
@keys << card.key
|
245
|
+
Card.write_to_local_cache card
|
246
|
+
card
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -193,7 +193,6 @@ format do
|
|
193
193
|
end
|
194
194
|
end
|
195
195
|
|
196
|
-
|
197
196
|
def nested_fields args={}
|
198
197
|
result = []
|
199
198
|
each_nested_field(args) do |chunk|
|
@@ -214,7 +213,7 @@ format do
|
|
214
213
|
|
215
214
|
each_nested_chunk(args) do |chunk|
|
216
215
|
# TODO handle structures that are non-virtual
|
217
|
-
if chunk.referee_name.to_name.
|
216
|
+
if chunk.referee_name.to_name.field_of? card.name
|
218
217
|
if chunk.referee_card && chunk.referee_card.virtual? && !processed_chunk_keys.include?(chunk.referee_name.key)
|
219
218
|
processed_chunk_keys << chunk.referee_name.key
|
220
219
|
subformat(chunk.referee_card).each_nested_field(args) do |sub_chunk|
|
@@ -20,64 +20,77 @@ module ClassMethods
|
|
20
20
|
# :skip_virtual Real cards only
|
21
21
|
# :skip_modules Don't load Set modules
|
22
22
|
# :look_in_trash Return trashed card objects
|
23
|
+
# :local_only Use only local cache for lookup and storing
|
23
24
|
# new: { card opts } Return a new card when not found
|
24
25
|
#
|
25
|
-
def fetch mark, opts={}
|
26
|
-
|
27
|
-
|
28
|
-
when /^\~(\d+)$/ # get by id
|
29
|
-
mark = $1.to_i
|
30
|
-
when /^\:(\w+)$/ # get by codename
|
31
|
-
mark = $1.to_sym
|
32
|
-
end
|
33
|
-
end
|
34
|
-
mark = Card::Codename[mark] if Symbol === mark # id from codename
|
26
|
+
def fetch mark, opts = {}
|
27
|
+
validate_fetch_opts! opts
|
28
|
+
mark = normalize_mark mark
|
35
29
|
|
36
30
|
if mark.present?
|
37
|
-
card, mark, needs_caching = fetch_from_cache_or_db mark, opts
|
31
|
+
card, mark, needs_caching = fetch_from_cache_or_db mark, opts
|
38
32
|
else
|
39
33
|
return unless opts[:new]
|
40
34
|
end
|
41
35
|
|
42
|
-
if Integer
|
43
|
-
return if card.nil?
|
44
|
-
|
45
|
-
return card.renew(opts)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
36
|
+
if mark.is_a?(Integer)
|
37
|
+
return if card.nil?
|
38
|
+
elsif card && card.new_card? && opts[:new].present?
|
39
|
+
return card.renew(opts)
|
40
|
+
elsif !card || (card.type_unknown? && !skip_type_lookup?(opts))
|
41
|
+
needs_caching = true
|
42
|
+
card = new_for_cache mark, opts # new (or improved) card for cache
|
50
43
|
end
|
51
44
|
|
52
|
-
write_to_cache card if
|
45
|
+
write_to_cache card, opts if needs_caching
|
53
46
|
|
54
47
|
if card.new_card?
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
card.include_set_modules unless opts[:skip_modules] # need to load modules here to call the right virtual? method
|
61
|
-
return unless card.virtual?
|
48
|
+
case
|
49
|
+
when opts[:new].present? then return card.renew(opts)
|
50
|
+
when opts[:new] # noop for empty hash
|
51
|
+
when opts[:skip_virtual] then return nil
|
62
52
|
end
|
63
|
-
card.
|
53
|
+
card.rename_from_mark mark unless opts[:local_only]
|
64
54
|
end
|
65
|
-
|
55
|
+
# need to load modules here to call the right virtual? method
|
66
56
|
card.include_set_modules unless opts[:skip_modules]
|
67
|
-
card
|
57
|
+
card if opts[:new] || card.known?
|
58
|
+
end
|
59
|
+
|
60
|
+
def fetch_local mark, opts = {}
|
61
|
+
fetch mark, opts.merge(:local_only=>true)
|
62
|
+
end
|
63
|
+
|
64
|
+
def fetch_id mark
|
65
|
+
if mark.is_a?(Integer)
|
66
|
+
mark
|
67
|
+
elsif mark.is_a?(Symbol) && Card::Codename[mark]
|
68
|
+
Card::Codename[mark]
|
69
|
+
else
|
70
|
+
card = quick_fetch mark.to_s
|
71
|
+
card && card.id
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def quick_fetch mark
|
76
|
+
fetch mark, skip_virtual: true, skip_modules: true
|
68
77
|
end
|
69
78
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
79
|
+
def assign_or_initialize_by name, attributes, fetch_opts = {}
|
80
|
+
if (known_card = Card.fetch(name, fetch_opts))
|
81
|
+
known_card.refresh.assign_attributes attributes
|
82
|
+
known_card
|
83
|
+
else
|
84
|
+
Card.new attributes.merge(name: name)
|
85
|
+
end
|
73
86
|
end
|
74
87
|
|
75
|
-
def []
|
88
|
+
def [] mark
|
76
89
|
fetch mark, skip_virtual: true
|
77
90
|
end
|
78
91
|
|
79
92
|
def exists? mark
|
80
|
-
card =
|
93
|
+
card = quick_fetch mark
|
81
94
|
card.present?
|
82
95
|
end
|
83
96
|
|
@@ -86,14 +99,19 @@ module ClassMethods
|
|
86
99
|
card.present?
|
87
100
|
end
|
88
101
|
|
89
|
-
def expire name
|
90
|
-
#note: calling instance method breaks on dirty names
|
102
|
+
def expire name, subcards = false
|
103
|
+
# note: calling instance method breaks on dirty names
|
91
104
|
key = name.to_name.key
|
92
|
-
if card = Card.cache.read(
|
105
|
+
if card = Card.cache.read(key)
|
106
|
+
if subcards
|
107
|
+
card.expire_subcards
|
108
|
+
else
|
109
|
+
card.preserve_subcards
|
110
|
+
end
|
93
111
|
Card.cache.delete key
|
94
112
|
Card.cache.delete "~#{card.id}" if card.id
|
95
113
|
end
|
96
|
-
#Rails.logger.warn "expiring #{name}, #{card.inspect}"
|
114
|
+
# Rails.logger.warn "expiring #{name}, #{card.inspect}"
|
97
115
|
end
|
98
116
|
|
99
117
|
# set_names reverse map (cached)
|
@@ -116,90 +134,135 @@ module ClassMethods
|
|
116
134
|
end
|
117
135
|
end
|
118
136
|
|
119
|
-
def
|
120
|
-
|
137
|
+
def validate_fetch_opts! opts
|
138
|
+
if opts[:new] && opts[:skip_virtual]
|
139
|
+
fail Card::Error, 'fetch called with new args and skip_virtual'
|
140
|
+
end
|
121
141
|
end
|
122
142
|
|
123
|
-
def
|
124
|
-
Card
|
143
|
+
def cache
|
144
|
+
Card::Cache[Card]
|
125
145
|
end
|
126
146
|
|
127
|
-
def
|
128
|
-
if
|
129
|
-
|
130
|
-
|
131
|
-
|
147
|
+
def fetch_from_cache cache_key, local_only=false
|
148
|
+
if Card.cache
|
149
|
+
if local_only
|
150
|
+
Card.cache.read_local cache_key
|
151
|
+
else
|
152
|
+
Card.cache.read cache_key
|
153
|
+
end
|
132
154
|
end
|
133
155
|
end
|
134
156
|
|
135
157
|
def fetch_from_cache_or_db mark, opts
|
136
158
|
needs_caching = false
|
137
|
-
mark_type = Integer
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
159
|
+
mark_type = mark.is_a?(Integer) ? :id : :key
|
160
|
+
expanded_mark = expand_mark mark, opts
|
161
|
+
card = send("fetch_from_cache_by_#{mark_type}",
|
162
|
+
expanded_mark, opts[:local_only])
|
163
|
+
|
164
|
+
if card.nil? || (opts[:look_in_trash] && card.new_card? && !card.trash)
|
165
|
+
query = { mark_type => expanded_mark }
|
166
|
+
query[:trash] = false unless opts[:look_in_trash]
|
167
|
+
card = fetch_from_db query
|
168
|
+
needs_caching = card && !card.trash
|
169
|
+
card.restore_subcards if card
|
144
170
|
end
|
145
171
|
|
146
|
-
card
|
172
|
+
[card, mark, needs_caching]
|
173
|
+
end
|
147
174
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
needs_caching = card && !card.trash
|
152
|
-
end
|
153
|
-
elsif card.nil?
|
154
|
-
needs_caching = true
|
155
|
-
card = Card.where( mark_type => val, trash: false).take
|
175
|
+
def fetch_from_cache_by_id id, local_only = false
|
176
|
+
if name = fetch_from_cache("~#{id}", local_only)
|
177
|
+
fetch_from_cache name, local_only
|
156
178
|
end
|
179
|
+
end
|
157
180
|
|
158
|
-
|
181
|
+
def fetch_from_cache_by_key key, local_only = false
|
182
|
+
fetch_from_cache key, local_only
|
159
183
|
end
|
160
184
|
|
185
|
+
def fetch_from_db query
|
186
|
+
Card.where(query).take
|
187
|
+
end
|
161
188
|
|
162
|
-
def
|
163
|
-
|
164
|
-
|
165
|
-
|
189
|
+
def new_for_cache name, opts
|
190
|
+
new name: name,
|
191
|
+
skip_modules: true,
|
192
|
+
skip_type_lookup: skip_type_lookup?(opts)
|
166
193
|
end
|
167
194
|
|
168
|
-
def
|
169
|
-
|
195
|
+
def skip_type_lookup? opts
|
196
|
+
# if opts[:new] is not empty then we are initializing a variant that is
|
197
|
+
# different from the cached variant
|
198
|
+
# and can postpone type lookup for the cached variant
|
199
|
+
# if skipping virtual no need to look for actual type
|
200
|
+
opts[:skip_virtual] || opts[:new].present?
|
170
201
|
end
|
171
202
|
|
172
|
-
def
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
203
|
+
def write_to_cache card, opts
|
204
|
+
if opts[:local_only]
|
205
|
+
write_to_local_cache card
|
206
|
+
elsif Card.cache
|
207
|
+
Card.cache.write card.key, card
|
208
|
+
Card.cache.write "~#{card.id}", card.key if card.id && card.id != 0
|
209
|
+
end
|
178
210
|
end
|
179
211
|
|
180
|
-
def
|
181
|
-
|
212
|
+
def write_to_local_cache card
|
213
|
+
if Card.cache
|
214
|
+
Card.cache.write_local card.key, card
|
215
|
+
Card.cache.write_local "~#{card.id}", card.key if card.id && card.id != 0
|
216
|
+
end
|
182
217
|
end
|
183
218
|
|
184
|
-
def
|
185
|
-
|
186
|
-
|
219
|
+
def expand_mark mark, opts
|
220
|
+
if mark.is_a?(Integer)
|
221
|
+
mark
|
222
|
+
else
|
223
|
+
fullname_from_name(mark, opts[:new]).key
|
224
|
+
end
|
187
225
|
end
|
188
226
|
|
227
|
+
def normalize_mark mark
|
228
|
+
case mark
|
229
|
+
when String
|
230
|
+
case mark
|
231
|
+
when /^\~(\d+)$/ # get by id
|
232
|
+
$1.to_i
|
233
|
+
when /^\:(\w+)$/ # get by codename
|
234
|
+
Card::Codename[$1.to_sym]
|
235
|
+
else
|
236
|
+
mark
|
237
|
+
end
|
238
|
+
when Symbol
|
239
|
+
Card::Codename[mark] # id from codename
|
240
|
+
else
|
241
|
+
mark
|
242
|
+
end
|
243
|
+
end
|
189
244
|
|
245
|
+
def fullname_from_name name, new_opts = {}
|
246
|
+
if new_opts && supercard = new_opts[:supercard]
|
247
|
+
name.to_name.to_absolute_name supercard.name
|
248
|
+
else
|
249
|
+
name.to_name
|
250
|
+
end
|
251
|
+
end
|
190
252
|
end
|
191
253
|
|
192
254
|
# ~~~~~~~~~~ Instance ~~~~~~~~~~~~~
|
193
255
|
|
194
|
-
def fetch opts={}
|
256
|
+
def fetch opts = {}
|
195
257
|
if traits = opts.delete(:trait)
|
196
|
-
traits =
|
197
|
-
traits.inject(self)
|
258
|
+
traits = Array.wrap traits
|
259
|
+
traits.inject(self) do |card, trait|
|
260
|
+
Card.fetch card.cardname.trait(trait), opts
|
261
|
+
end
|
198
262
|
end
|
199
263
|
end
|
200
264
|
|
201
|
-
|
202
|
-
def renew args={}
|
265
|
+
def renew args = {}
|
203
266
|
opts = args[:new].clone
|
204
267
|
opts[:name] ||= cardname
|
205
268
|
opts[:skip_modules] = args[:skip_modules]
|
@@ -208,18 +271,22 @@ end
|
|
208
271
|
|
209
272
|
def expire_pieces
|
210
273
|
cardname.piece_names.each do |piece|
|
211
|
-
Card.expire piece
|
274
|
+
Card.expire piece, !cardname.field_of?(piece)
|
212
275
|
end
|
213
276
|
end
|
214
277
|
|
215
|
-
|
216
|
-
|
217
|
-
|
278
|
+
def expire subcards = false
|
279
|
+
# Rails.logger.warn "expiring i:#{id}, #{inspect}"
|
280
|
+
if subcards
|
281
|
+
expire_subcards
|
282
|
+
else
|
283
|
+
preserve_subcards
|
284
|
+
end
|
218
285
|
Card.cache.delete key
|
219
286
|
Card.cache.delete "~#{id}" if id
|
220
287
|
end
|
221
288
|
|
222
|
-
def refresh force=false
|
289
|
+
def refresh force = false
|
223
290
|
if force || self.frozen? || self.readonly?
|
224
291
|
fresh_card = self.class.find id
|
225
292
|
fresh_card.include_set_modules
|
@@ -233,4 +300,12 @@ def eager_renew? opts
|
|
233
300
|
opts[:skip_virtual] && new_card? && opts[:new].present?
|
234
301
|
end
|
235
302
|
|
303
|
+
def type_unknown?
|
304
|
+
type_id.nil?
|
305
|
+
end
|
306
|
+
|
307
|
+
def rename_from_mark mark
|
308
|
+
return unless mark && mark.to_s != name
|
309
|
+
self.name = mark.to_s
|
310
|
+
end
|
236
311
|
|