Module: GitModel::Persistable::ClassMethods

Defined in:
lib/gitmodel/persistable.rb

Instance Method Summary collapse

Instance Method Details

#all_values_for_attr(attr) ⇒ Object



275
276
277
278
# File 'lib/gitmodel/persistable.rb', line 275

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



169
170
171
172
173
174
175
# File 'lib/gitmodel/persistable.rb', line 169

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



177
178
179
180
181
182
# File 'lib/gitmodel/persistable.rb', line 177

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



280
281
282
283
284
285
286
287
288
# File 'lib/gitmodel/persistable.rb', line 280

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



290
291
292
293
294
295
296
297
298
# File 'lib/gitmodel/persistable.rb', line 290

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



165
166
167
# File 'lib/gitmodel/persistable.rb', line 165

def db_subdir
  self.to_s.tableize
end

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



300
301
302
303
304
305
306
307
# File 'lib/gitmodel/persistable.rb', line 300

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|
    delete_tree(path, t.index, options)
  end
end

#delete_all(options = {}) ⇒ Object



309
310
311
312
313
314
315
# File 'lib/gitmodel/persistable.rb', line 309

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

#exists?(id) ⇒ Boolean

Returns:

  • (Boolean)


192
193
194
195
# File 'lib/gitmodel/persistable.rb', line 192

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

#find(id) ⇒ Object



184
185
186
187
188
189
190
# File 'lib/gitmodel/persistable.rb', line 184

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

#find_all(conditions = {}) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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
# File 'lib/gitmodel/persistable.rb', line 197

def find_all(conditions = {})
  # TODO Refactor this spaghetti
  GitModel.logger.debug "Finding all #{name.pluralize} with conditions: #{conditions.inspect}"
  return [] unless GitModel.current_tree

  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 = (GitModel.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 = (GitModel.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 (GitModel.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

  return results
end

#index!Object



317
318
319
320
# File 'lib/gitmodel/persistable.rb', line 317

def index!
  index.generate!
  index.save
end