Module: GitModel::Persistable::ClassMethods

Defined in:
lib/gitmodel/persistable.rb

Instance Method Summary collapse

Instance Method Details

#all_values_for_attr(attr) ⇒ Object



334
335
336
337
# File 'lib/gitmodel/persistable.rb', line 334

def all_values_for_attr(attr)
  attr_index = index.attr_index(attr.to_s)
  values = attr_index ? attr_index.keys : []
end

#attribute(name, options = {}) ⇒ Object



208
209
210
211
212
213
214
# File 'lib/gitmodel/persistable.rb', line 208

def attribute(name, options = {})
  default = options[:default]
  self.class_eval <<-EOF
    def #{name}; attributes[:#{name}] || #{default.inspect}; end
    def #{name}=(value); attributes[:#{name}] = value; end
  EOF
end

#blob(name, options = {}) ⇒ Object



216
217
218
219
220
221
# File 'lib/gitmodel/persistable.rb', line 216

def blob(name, options = {})
  self.class_eval <<-EOF
    def #{name}; blobs[:#{name}]; end
    def #{name}=(value); blobs[:#{name}] = value; end
  EOF
end

#create(args) ⇒ Object



339
340
341
342
343
344
345
346
347
# File 'lib/gitmodel/persistable.rb', line 339

def create(args)
  if args.is_a?(Array)
    args.map{|arg| create(arg)}
  else
    o = self.new(args)
    o.save
  end
  return o
end

#create!(args) ⇒ Object



349
350
351
352
353
354
355
356
357
# File 'lib/gitmodel/persistable.rb', line 349

def create!(args)
  if args.is_a?(Array)
    args.map{|arg| create!(arg)}
  else
    o = self.new(args)
    o.save!
  end
  return o
end

#db_subdirObject



204
205
206
# File 'lib/gitmodel/persistable.rb', line 204

def db_subdir
  self.to_s.tableize
end

#delete(id, options = {}) ⇒ Object



359
360
361
362
363
364
365
366
367
# File 'lib/gitmodel/persistable.rb', line 359

def delete(id, options = {})
  GitModel.logger.debug "Deleting #{name} with id: #{id}"
  path = File.join(db_subdir, id)
  transaction = options.delete(:transaction) || GitModel::Transaction.new(options) 
  result = transaction.execute do |t|
    branch = t.branch || options[:branch] || GitModel.default_branch
    delete_tree(path, t.index, branch, options)
  end
end

#delete_all(options = {}) ⇒ Object



369
370
371
372
373
374
375
376
# File 'lib/gitmodel/persistable.rb', line 369

def delete_all(options = {})
  GitModel.logger.debug "Deleting all #{name.pluralize}"
  transaction = options.delete(:transaction) || GitModel::Transaction.new(options) 
  result = transaction.execute do |t|
    branch = t.branch || options[:branch] || GitModel.default_branch
    delete_tree(db_subdir, t.index, branch, options)
  end
end

#exists?(id, branch = GitModel.default_branch) ⇒ Boolean

Returns:

  • (Boolean)


234
235
236
237
238
239
240
# File 'lib/gitmodel/persistable.rb', line 234

def exists?(id, branch = GitModel.default_branch)
  GitModel.logger.debug "Checking existence of #{name} with id: #{id}"
  result = GitModel.cache(branch, "#{db_subdir}-exists-#{id}") do
    GitModel.repo.commits.any? && !(GitModel.current_tree(branch) / File.join(db_subdir, id, 'attributes.json')).nil?
  end
  return result
end

#find(id, branch = GitModel.default_branch) ⇒ Object



223
224
225
226
227
228
229
230
231
232
# File 'lib/gitmodel/persistable.rb', line 223

def find(id, branch = GitModel.default_branch)
  GitModel.logger.debug "Finding #{name} with id: #{id}"
  result = GitModel.cache(branch, "#{db_subdir}-find-#{id}") do
    o = new
    dir = File.join(db_subdir, id)
    o.send :load, dir, branch
    o
  end
  return result
end

#find_all(conditions = {}) ⇒ Object

TODO document conditions :branch :cache_key :order_by :order any model attribute



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/gitmodel/persistable.rb', line 248

def find_all(conditions = {})
  branch = conditions.delete(:branch) || GitModel.default_branch
  # TODO Refactor this spaghetti
  GitModel.logger.debug "Finding all #{name.pluralize} with conditions: #{conditions.inspect}"
  cache_key = "#{db_subdir}-find_all-#{format_conditions_hash_for_cache_key(conditions)}"
  cached_results = GitModel.cache(branch, cache_key) do
    current_tree = GitModel.current_tree(branch)
    unless current_tree
      []
    else
      order = conditions.delete(:order) || :asc
      order_by = conditions.delete(:order_by) || :id
      limit = conditions.delete(:limit)

      matching_ids = []
      if conditions.empty?  # load all objects
        trees = (current_tree / db_subdir).trees
        trees.each do |t|
          matching_ids << t.name if t.blobs.any?
        end
      else # only load objects that match conditions
        matching_ids_for_condition = {}
        conditions.each do |k,v|
          matching_ids_for_condition[k] = []
          if k == :id # id isn't indexed
            if v.is_a?(Proc)
              trees = (current_tree / db_subdir).trees
              trees.each do |t|
                matching_ids_for_condition[k] << t.name if t.blobs.any? && v.call(t.name)
              end
            else
              # an unlikely use case but supporting it for completeness
              matching_ids_for_condition[k] << v if (current_tree / db_subdir / v)
            end
          else
            raise GitModel::IndexRequired unless index.generated?
            attr_index = index.attr_index(k)
            if v.is_a?(Proc)
              attr_index.each do |value, ids|
                matching_ids_for_condition[k] += ids.to_a if v.call(value)
              end
            else
              matching_ids_for_condition[k] += attr_index[v].to_a
            end
          end
        end
        matching_ids += matching_ids_for_condition.values.inject{|memo, obj| memo & obj}
      end

      results = nil
      if order_by != :id
        GitModel.logger.warn "Ordering by an attribute other than id requires loading all matching objects before applying limit, this will be slow" if limit
        results = matching_ids.map{|k| find(k)}

        if order == :asc
          results = results.sort{|a,b| a.send(order_by) <=> b.send(order_by)}
        elsif order == :desc
          results = results.sort{|b,a| a.send(order_by) <=> b.send(order_by)}
        else
          raise GitModel::InvalidParams("invalid order: '#{order}'")
        end

        if limit
          results = results[0, limit]
        end
      else
        if order == :asc
          matching_ids = matching_ids.sort{|a,b| a <=> b}
        elsif order == :desc
          matching_ids = matching_ids.sort{|b,a| a <=> b}
        else
          raise GitModel::InvalidParams("invalid order: '#{order}'")
        end
        if limit

          matching_ids = matching_ids[0, limit]
        end
        results = matching_ids.map{|k| find(k)}
      end

      results
    end
  end # cached block
  return cached_results
end

#index!(branch) ⇒ Object



378
379
380
381
# File 'lib/gitmodel/persistable.rb', line 378

def index!(branch)
  index.generate!(branch)
  index.save(:branch => branch)
end