class Loco::SQLiteAdapter

Public Instance Methods

create_record(record, &block) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 8
def create_record(record, &block)
  type = record.class
  record.id = generate_id(type)
  data = NSEntityDescription.insertNewObjectForEntityForName(type.to_s, inManagedObjectContext:context(type))
  record.serialize(root: false, include_id: true).each do |key, value|
    data.setValue(value, forKey:key)
  end
  save_data_for_type(type)
  load(type, record, data)
  save_has_many(record)
  block.call(record) if block.is_a? Proc
  record
end
delete_record(record, &block) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 22
def delete_record(record, &block)
  type = record.class
  data = request(type, { id: record.id }).first
  if data
    context(type).deleteObject(data)
    save_data_for_type(type)
    block.call(record) if block.is_a? Proc
    record
  else
    raise Loco::FixtureAdapter::RecordNotFound, "#{type} with the id `#{record.id}' could not be deleted."
  end
end
find(record, id, &block) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 35
def find(record, id, &block)
  type = record.class
  data = request(type, { id: record.id }).first
  if data
    load(type, record, data)
    block.call(record) if block.is_a? Proc
    record
  else
    raise Loco::FixtureAdapter::RecordNotFound, "#{type} with the id `#{id}' could not be loaded."
  end
end
find_all(type, records, &block) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 47
def find_all(type, records, &block)
  data = request(type)
  load(type, records, data)
  block.call(records) if block.is_a? Proc
  records
end
find_many(type, records, ids, &block) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 54
def find_many(type, records, ids, &block)
  data = request(type, { id: ids })
  load(type, records, data)
  block.call(records) if block.is_a? Proc
  records
end
find_query(type, records, query, &block) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 61
def find_query(type, records, query, &block)
  data = request(type, query)
  load(type, records, data)
  block.call(records) if block.is_a? Proc
  records
end
serialize(record, options={}) click to toggle source
Calls superclass method Loco::Adapter#serialize
# File lib/motion-loco/sqlite_adapter.rb, line 85
def serialize(record, options={})
  json = {}
  record.class.get_class_relationships.select{|relationship| relationship[:belongs_to] }.each do |relationship|
    key = "#{relationship[:belongs_to]}_id".to_sym
    json[key] = record.valueForKey(key)
  end
  super(record, options, json)
end
update_record(record, &block) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 68
def update_record(record, &block)
  type = record.class
  data = request(type, { id: record.id }).first
  if data
    record.serialize(root: false).each do |key, value|
      data.setValue(value, forKey:key)
    end
    save_data_for_type(type)
    load(type, record, data)
    save_has_many(record)
    block.call(record) if block.is_a? Proc
    record
  else
    raise Loco::FixtureAdapter::RecordNotFound, "#{type} with the id `#{record.id}' could not be updated."
  end
end

Private Instance Methods

context(type) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 118
def context(type)
  @context ||= begin
    model = NSManagedObjectModel.new
    model.entities = [entity(type)]

    store = NSPersistentStoreCoordinator.alloc.initWithManagedObjectModel(model)
    store_url = NSURL.fileURLWithPath(File.join(NSHomeDirectory(), "Documents", "loco.#{type.to_s.underscore.pluralize}.sqlite"))
    Loco.debug(store_url.absoluteString)
    error = Pointer.new(:object)
    raise "Can't add persistent SQLite store: #{error[0].description}" unless store.addPersistentStoreWithType(NSSQLiteStoreType, configuration:nil, URL:store_url, options:nil, error:error)

    context = NSManagedObjectContext.new
    context.persistentStoreCoordinator = store
    context
  end
end
entity(type) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 135
def entity(type)
  @entity ||= begin
    entity = NSEntityDescription.new
    entity.name = type.to_s
    
    properties = type.get_class_properties.select{|prop|
      prop[:type]
    }.map{|prop|
      property = NSAttributeDescription.new
      property.name = prop[:name].to_s
      case prop[:type].to_sym
      when :date
        property.attributeType = NSDateAttributeType
      when :integer
        property.attributeType = NSInteger32AttributeType
      when :float
        property.attributeType = NSFloatAttributeType
      when :string
        property.attributeType = NSStringAttributeType
      end
      property
    }
    
    type.get_class_relationships.select{|relationship| relationship[:belongs_to] }.each do |relationship|
      property = NSAttributeDescription.new
      property.name = "#{relationship[:belongs_to]}_id"
      property.attributeType = NSInteger32AttributeType
      properties << property
    end
    
    entity.properties = properties
    
    entity
  end
end
generate_id(type) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 171
def generate_id(type)
  key = "loco.#{type.to_s.underscore.pluralize}.last_id"
  last_id = App::Persistence[key]
  if last_id.nil?
    last_id = 0 
    data = request(type)
    if data.length > 0
      last_id = data.sort_by{|obj| obj.valueForKey(:id).to_i }.last.id
    end
  end
  new_id = last_id.to_i + 1
  App::Persistence[key] = new_id
  new_id
end
request(type, query=nil) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 96
def request(type, query=nil)
  request = NSFetchRequest.new
  request.entity = entity(type)
  request.sortDescriptors = [NSSortDescriptor.alloc.initWithKey('id', ascending:true)]
  unless query.nil?
    conditions = []
    values = []
    query.each do |key, value|
      if value.is_a? Array
        conditions << "#{key} IN %@"
      else
        conditions << "#{key} = %@"
      end
      values << value
    end
    request.predicate = NSPredicate.predicateWithFormat(conditions.join(' AND '), argumentArray:values) 
  end

  error = Pointer.new(:object)
  context(type).executeFetchRequest(request, error:error)
end
save_data_for_type(type) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 186
def save_data_for_type(type)
  error = Pointer.new(:object)
  raise "Error when saving #{type}: #{error[0].description}" unless context(type).save(error)
end
save_has_many(record) click to toggle source
# File lib/motion-loco/sqlite_adapter.rb, line 191
def save_has_many(record)
  record.class.get_class_relationships.select{|relationship| relationship[:has_many] }.each do |relationship|
    related = record.send("#{relationship[:has_many]}")
    related.each do |r|
      r.save
    end
  end
end
transform_data(type, data) click to toggle source
Calls superclass method Loco::Adapter#transform_data
# File lib/motion-loco/sqlite_adapter.rb, line 200
def transform_data(type, data)
  if data.is_a? Array
    super(type, data.map{|object|
      data_item = {}
      
      type.get_class_properties.each do |property|
        key = property[:name].to_sym
        data_item[key] = object.valueForKey(key)
      end
      
      type.get_class_relationships.select{|relationship| relationship[:belongs_to] }.each do |relationship|
        key = "#{relationship[:belongs_to]}_id".to_sym
        data_item[key] = object.valueForKey(key)
      end
      
      data_item
    })
  else
    json = {}
    
    type.get_class_properties.each do |property|
      key = property[:name].to_sym
      json[key] = data.valueForKey(key)
    end
    
    type.get_class_relationships.select{|relationship| relationship[:belongs_to] }.each do |relationship|
      key = "#{relationship[:belongs_to]}_id".to_sym
      json[key] = data.valueForKey(key)
    end
    
    super(type, json)
  end
end