Module: Card::Set::All::Fetch::ClassMethods

Defined in:
tmpsets/set/mod001-01_core/all/fetch.rb

Overview

and “virtual” card construction

Instance Method Summary collapse

Instance Method Details

#[](mark) ⇒ Object



85
86
87
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 85

def [] mark
  fetch mark, skip_virtual: true
end

#assign_or_initialize_by(name, attributes, fetch_opts = {}) ⇒ Object



76
77
78
79
80
81
82
83
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 76

def assign_or_initialize_by name, attributes, fetch_opts={}
  if (known_card = Card.fetch(name, fetch_opts))
    known_card.refresh.assign_attributes attributes
    known_card
  else
    Card.new attributes.merge(name: name)
  end
end

#cacheObject



146
147
148
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 146

def cache
  Card::Cache[Card]
end

#cached_set_members(key) ⇒ Object

set_names reverse map (cached) FIXME: move to set handling



121
122
123
124
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 121

def cached_set_members key
  set_cache_list = Card.cache.read "$#{key}"
  set_cache_list.nil? ? [] : set_cache_list.keys
end

#exists?(mark) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
92
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 89

def exists? mark
  card = quick_fetch mark
  card.present?
end

#expire(name, subcards = false) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 106

def expire name, subcards=false
  # note: calling instance method breaks on dirty names
  key = name.to_name.key
  return unless (card = Card.cache.read key)
  if subcards
    card.expire_subcards
  else
    card.preserve_subcards
  end
  Card.cache.delete key
  Card.cache.delete "~#{card.id}" if card.id
end

#expire_hard(name) ⇒ Object



99
100
101
102
103
104
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 99

def expire_hard name
  return unless Card.cache.hard
  key = name.to_name.key
  Card.cache.hard.delete key
  Card.cache.hard.delete "~#{card.id}" if card.id
end

#fetch(mark, opts = {}) ⇒ Object

fetch

looks for cards in

- cache
- database
- virtual cards

“mark” here means one of three unique identifiers

 1. a numeric id (Integer)
 2. a name/key (String or Card::Name)
 3. a codename (Symbol)

Options:
  :skip_virtual               Real cards only
  :skip_modules               Don't load Set modules
  :look_in_trash              Return trashed card objects
  :local_only                 Use only local cache for lookup and storing
  new: {  card opts }      Return a new card when not found


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 28

def fetch mark, opts={}
  validate_fetch_opts! opts
  mark = normalize_mark mark, opts

  card, needs_caching = fetch_existing mark, opts

  if (new_card = new_for_cache card, mark, opts)
    card = new_card
    needs_caching = true
  end

  return if card.nil?
  write_to_cache card, opts if needs_caching
  standard_fetch_results card, mark, opts
end

#fetch_existing(mark, opts) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 168

def fetch_existing mark, opts
  return [nil, false] unless mark.present?
  mark_type, mark_key = parse_mark! mark
  needs_caching = false # until proven true :)

  # look in cache
  card = send "fetch_from_cache_by_#{mark_type}", mark_key, opts[:local_only]

  if retrieve_from_db?(card, opts)
    # look in db if needed
    card = fetch_from_db mark_type, mark_key, opts
    needs_caching = !card.nil? && !card.trash
  end

  [card, needs_caching]
end

#fetch_from_cache(cache_key, local_only = false) ⇒ Object



150
151
152
153
154
155
156
157
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 150

def fetch_from_cache cache_key, local_only=false
  return unless Card.cache
  if local_only
    Card.cache.soft.read cache_key
  else
    Card.cache.read cache_key
  end
end

#fetch_from_cache_by_id(id, local_only = false) ⇒ Object



189
190
191
192
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 189

def fetch_from_cache_by_id id, local_only=false
  name = fetch_from_cache "~#{id}", local_only
  fetch_from_cache name, local_only if name
end

#fetch_from_cache_by_key(key, local_only = false) ⇒ Object



194
195
196
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 194

def fetch_from_cache_by_key key, local_only=false
  fetch_from_cache key, local_only
end

#fetch_from_db(mark_type, mark_key, opts) ⇒ Object



198
199
200
201
202
203
204
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 198

def fetch_from_db mark_type, mark_key, opts
  query = { mark_type => mark_key }
  query[:trash] = false unless opts[:look_in_trash]
  card = Card.where(query).take
  card.restore_subcards if card
  card
end

#fetch_id(mark, opts = {}) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 62

def fetch_id mark, opts={}
  mark = normalize_mark mark, opts
  if mark.is_a?(Integer)
    mark
  else
    card = quick_fetch mark.to_s
    card && card.id
  end
end

#fetch_soft(mark, opts = {}) ⇒ Object



58
59
60
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 58

def fetch_soft mark, opts={}
  fetch mark, opts.merge(local_only: true)
end

#fullname_from_mark(name, new_opts = {}) ⇒ Object



254
255
256
257
258
259
260
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 254

def fullname_from_mark name, new_opts={}
  if new_opts && (supercard = new_opts[:supercard])
    name.to_name.to_absolute_name supercard.name
  else
    name.to_name
  end
end

#known?(mark) ⇒ Boolean

Returns:

  • (Boolean)


94
95
96
97
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 94

def known? mark
  card = fetch mark, skip_modules: true
  card.present?
end

#new_for_cache(card, name, opts) ⇒ Object



206
207
208
209
210
211
212
213
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 206

def new_for_cache card, name, opts
  return if name.is_a? Integer
  return if !name.present? && !opts[:new]
  return unless !card || (card.type_unknown? && !skip_type_lookup?(opts))
  new name: name,
      skip_modules: true,
      skip_type_lookup: skip_type_lookup?(opts)
end

#normalize_mark(mark, opts) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 238

def normalize_mark mark, opts
  case mark
  when Symbol        then Card::Codename[mark]
  when Integer       then mark.to_i
  when String, SmartName
    # there are some situations where this breaks if we use Card::Name
    # rather than SmartName, which would seem more correct.
    # very hard to reproduce, not captured in a spec :(
    case mark.to_s
    when /^\~(\d+)$/ then $1.to_i                   # id
    when /^\:(\w+)$/ then Card::Codename[$1.to_sym] # codename
    else fullname_from_mark mark, opts[:new]        # name
    end
  end
end

#parse_mark!(mark) ⇒ Object



159
160
161
162
163
164
165
166
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 159

def parse_mark! mark
  # return mark_type, mark_value, and absolutized mark
  if mark.is_a? Integer
    [:id, mark]
  else
    [:key, mark.key]
  end
end

#quick_fetch(mark) ⇒ Object



72
73
74
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 72

def quick_fetch mark
  fetch mark, skip_virtual: true, skip_modules: true
end

#retrieve_from_db?(card, opts) ⇒ Boolean

Returns:

  • (Boolean)


185
186
187
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 185

def retrieve_from_db? card, opts
  card.nil? || (opts[:look_in_trash] && card.new_card? && !card.trash)
end

#set_members(set_names, key) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 126

def set_members set_names, key
  set_names.compact.map(&:to_name).map(&:key).map do |set_key|
    skey = "$#{set_key}" # dollar sign avoids conflict with card keys
    h = Card.cache.read skey
    if h.nil?
      h = {}
    elsif h[key]
      next
    end
    h = h.dup if h.frozen?
    h[key] = true
    Card.cache.write skey, h
  end
end

#skip_type_lookup?(opts) ⇒ Boolean

Returns:

  • (Boolean)


215
216
217
218
219
220
221
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 215

def skip_type_lookup? opts
  # if opts[:new] is not empty then we are initializing a variant that is
  # different from the cached variant
  # and can postpone type lookup for the cached variant
  # if skipping virtual no need to look for actual type
  opts[:skip_virtual] || opts[:new].present? || opts[:skip_type_lookup]
end

#standard_fetch_results(card, mark, opts) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 44

def standard_fetch_results card, mark, opts
  if card.new_card?
    case
    when opts[:new].present? then return card.renew(opts)
    when opts[:new] # noop for empty hash
    when opts[:skip_virtual] then return nil
    end
    card.name_from_mark! mark, opts
  end
  # need to load modules here to call the right virtual? method
  card.include_set_modules unless opts[:skip_modules]
  card if opts[:new] || card.known?
end

#validate_fetch_opts!(opts) ⇒ Object



141
142
143
144
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 141

def validate_fetch_opts! opts
  return unless opts[:new] && opts[:skip_virtual]
  fail Card::Error, 'fetch called with new args and skip_virtual'
end

#write_to_cache(card, opts) ⇒ Object



223
224
225
226
227
228
229
230
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 223

def write_to_cache card, opts
  if opts[:local_only]
    write_to_soft_cache card
  elsif Card.cache
    Card.cache.write card.key, card
    Card.cache.write "~#{card.id}", card.key if card.id && card.id != 0
  end
end

#write_to_soft_cache(card) ⇒ Object



232
233
234
235
236
# File 'tmpsets/set/mod001-01_core/all/fetch.rb', line 232

def write_to_soft_cache card
  return unless Card.cache
  Card.cache.soft.write card.key, card
  Card.cache.soft.write "~#{card.id}", card.key if card.id && card.id != 0
end