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

Defined in:
tmpsets/set/mod002-core/all/fetch.rb

Overview

and "virtual" card construction

Instance Method Summary collapse

Instance Method Details

#[](*marks) ⇒ Object



105
106
107
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 105

def [] *marks
  fetch(*marks, skip_virtual: true)
end

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



96
97
98
99
100
101
102
103
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 96

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

#compose_mark(parts, opts) ⇒ Object



219
220
221
222
223
224
225
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 219

def compose_mark parts, opts
  return normalize_mark(parts.first, opts) if parts.size == 1
  parts.map do |p|
    normalized = normalize_mark p, {}
    normalized.is_a?(Integer) ? quick_fetch(normalized).name : normalized.to_s
  end.join("+").to_name
end

#deep_fetch(args) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 179

def deep_fetch args
  opts = deep_opts args
  if args[:action] == "create"
    # FIXME: we currently need a "new" card to catch duplicates
    # (otherwise save will just act like a normal update)
    # We may need a "#create" instance method to handle this checking?
    Card.new opts
  else
    mark = args[:id] || opts[:name]
    Card.fetch mark, new: opts
  end
end

#deep_opts(args) ⇒ Object



192
193
194
195
196
197
198
199
200
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 192

def deep_opts args
  opts = (args[:card] || {}).clone
  # clone so that original params remain unaltered.  need deeper clone?
  opts[:type] ||= args[:type] if args[:type]
  # for /new/:type shortcut.  we should fix and deprecate this.
  opts[:name] ||= args[:id].to_s.tr("_", " ")
  # move handling to Card::Name?
  opts
end

#exists?(mark) ⇒ Boolean

Returns:

  • (Boolean)


109
110
111
112
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 109

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

#fetch(*args) ⇒ Card

Look for cards in

  • cache
  • database
  • virtual cards

Parameters:

  • mark (Integer, String, Card::Name, Symbol, Array)

    one of three unique identifiers

    1. a numeric id (Integer)
    2. a name/key (String or Card::Name)
    3. a codename (Symbol) or any combination of those. If you pass more then one mark they get joined with a '+'
  • options (Hash)

    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: { opts for Card#new } Return a new card when not found

Returns:



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 30

def fetch *args
  mark, opts = normalize_fetch_args args
  validate_fetch_opts! 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



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 142

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



124
125
126
127
128
129
130
131
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 124

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



163
164
165
166
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 163

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



168
169
170
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 168

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



172
173
174
175
176
177
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 172

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
end

#fetch_id(*args) ⇒ Object



82
83
84
85
86
87
88
89
90
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 82

def fetch_id *args
  mark, _opts = normalize_fetch_args args
  if mark.is_a?(Integer)
    mark
  else
    card = quick_fetch mark.to_s
    card && card.id
  end
end

#fetch_real_by_key(key, opts = {}) ⇒ Object

fetch converts String to Card::Name. That can break in some cases.

For example if you fetch "Siemens" by its key "siemen", you won't get "Siemens" because "siemen".to_name.key == "sieman" If you have a key of a real card use this method.

Raises:



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 49

def fetch_real_by_key key, opts={}
  raise Card::Error, "fetch_real_by_key called with new args" if opts[:new]

  # look in cache
  card = fetch_from_cache_by_key key, opts[:local_only]
  # look in db if needed
  if retrieve_from_db?(card, opts)
    card = fetch_from_db :key, key, opts
    write_to_cache card, opts if !card.nil? && !card.trash
  end
  return if card.nil?
  card.include_set_modules unless opts[:skip_modules]
  card
end

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



78
79
80
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 78

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

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



249
250
251
252
253
254
255
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 249

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)


114
115
116
117
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 114

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

#new_for_cache(card, name, opts) ⇒ Object



202
203
204
205
206
207
208
209
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 202

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

#normalize_fetch_args(args) ⇒ Object



227
228
229
230
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 227

def normalize_fetch_args args
  opts = args.last.is_a?(Hash) ? args.pop : {}
  [compose_mark(args, opts), opts]
end

#normalize_mark(mark, opts) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 232

def normalize_mark mark, opts
  case mark
  when Symbol  then Card::Codename[mark]
  when Integer then mark.to_i
  when Card    then mark.cardname
  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



133
134
135
136
137
138
139
140
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 133

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



92
93
94
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 92

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

#retrieve_from_db?(card, opts) ⇒ Boolean

Returns:

  • (Boolean)


159
160
161
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 159

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

#skip_type_lookup?(opts) ⇒ Boolean

Returns:

  • (Boolean)


211
212
213
214
215
216
217
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 211

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



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 64

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

Raises:



119
120
121
122
# File 'tmpsets/set/mod002-core/all/fetch.rb', line 119

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