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

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

Overview

and "virtual" card construction

Instance Method Summary collapse

Instance Method Details

#[](*marks) ⇒ Object



103
104
105
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 103

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

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



94
95
96
97
98
99
100
101
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 94

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



217
218
219
220
221
222
223
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 217

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



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

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



190
191
192
193
194
195
196
197
198
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 190

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)


107
108
109
110
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 107

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

#fetch(*args) ⇒ Card

Look for cards in

  • cache
  • database
  • virtual cards

Parameters:

  • args (Integer, String, Card::Name, Symbol)

    one or more of the three unique identifiers

    1. a numeric id (Integer)
    2. a name/key (String or Card::Name)
    3. a codename (Symbol) If you pass more then one mark they get joined with a '+'. The final argument can be a hash to set the following 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:



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

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



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

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



122
123
124
125
126
127
128
129
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 122

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



161
162
163
164
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 161

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



166
167
168
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 166

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



170
171
172
173
174
175
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 170

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



80
81
82
83
84
85
86
87
88
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 80

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:



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

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



76
77
78
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 76

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

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



247
248
249
250
251
252
253
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 247

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)


112
113
114
115
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 112

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

#new_for_cache(card, name, opts) ⇒ Object



200
201
202
203
204
205
206
207
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 200

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



225
226
227
228
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 225

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

#normalize_mark(mark, opts) ⇒ Object



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

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



131
132
133
134
135
136
137
138
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 131

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



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

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

#retrieve_from_db?(card, opts) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 157

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)


209
210
211
212
213
214
215
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 209

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



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

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:



117
118
119
120
# File 'tmpsets/set/mod001-core/all/fetch.rb', line 117

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