Module: GitModel::Persistable::ClassMethods

Defined in:
lib/gitmodel/persistable.rb

Instance Method Summary collapse

Instance Method Details

#all_values_for_attr(attr) ⇒ Object



299
300
301
302
# File 'lib/gitmodel/persistable.rb', line 299

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



173
174
175
176
177
178
179
# File 'lib/gitmodel/persistable.rb', line 173

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



181
182
183
184
185
186
# File 'lib/gitmodel/persistable.rb', line 181

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



304
305
306
307
308
309
310
311
312
# File 'lib/gitmodel/persistable.rb', line 304

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



314
315
316
317
318
319
320
321
322
# File 'lib/gitmodel/persistable.rb', line 314

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



169
170
171
# File 'lib/gitmodel/persistable.rb', line 169

def db_subdir
  self.to_s.tableize
end

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



324
325
326
327
328
329
330
331
332
# File 'lib/gitmodel/persistable.rb', line 324

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



334
335
336
337
338
339
340
341
# File 'lib/gitmodel/persistable.rb', line 334

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)


199
200
201
202
203
204
205
# File 'lib/gitmodel/persistable.rb', line 199

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



188
189
190
191
192
193
194
195
196
197
# File 'lib/gitmodel/persistable.rb', line 188

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



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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
# File 'lib/gitmodel/persistable.rb', line 213

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



343
344
345
346
# File 'lib/gitmodel/persistable.rb', line 343

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