lib/yapper/db.rb in motion-yapper-0.0.1 vs lib/yapper/db.rb in motion-yapper-0.0.2
- old
+ new
@@ -31,61 +31,78 @@
def configure(&block)
block.call(db)
end
- def execute(&block)
+ def execute(notifications={}, &block)
+ Notifications.track(notifications)
+
create_indexes!
- exception = nil; result = nil
- unless self.txn
- txn_proc = proc do |_txn|
- self.txn = _txn
- begin
- result = block.call(txn)
- rescue Exception => e
- self.txn.rollback
- exception = e
- ensure
- self.txn = nil
- end
+ result = nil
+ unless self.transaction
+ self.transaction = Transaction.new(self)
+ begin
+ result = transaction.run(&block)
+ ensure
+ self.transaction = nil
end
- connection.readWriteWithBlock(txn_proc)
-
+ Notifications.trigger
else
- result = block.call(self.txn)
+ result = block.call(self.transaction.txn)
end
- raise exception if exception
result
end
def purge
- create_indexes!(true)
+ Yapper::Settings.purge
+ @index_creation_required = true
+ create_indexes!
execute { |txn| txn.removeAllObjectsInAllCollections }
end
- def txn=(txn)
- Thread.current[:yapper_txn] = txn
+ def transaction=(transaction)
+ Thread.current[:yapper_transaction] = transaction
end
- def txn
- Thread.current[:yapper_txn]
+ def transaction
+ Thread.current[:yapper_transaction]
end
- def index(collection, field, type)
- @indexes[collection] ||= {}
- @indexes[collection][field] = { :type => type }
+ def index(model, args=[])
+ options = args.extract_options!
+
+ @index_creation_required = true
+ @indexes[model._type] ||= {}
+
+ args.each do |field|
+ options = model.fields[field]; raise "#{self._type}:#{field} not defined" unless options
+ type = options[:type]; raise "#{self._type}:#{field} must define type as its indexed" if type.nil?
+
+ @indexes[model._type][field] = { :type => type }
+ end
end
+ def connection
+ Dispatch.once { @connection ||= db.newConnection }
+ @connection
+ end
+
+ def db
+ Dispatch.once { @db ||= YapDatabase.alloc.initWithPath(document_path) }
+ @db
+ end
+
+
private
- def create_indexes!(force=false)
- return if @indexes_created && !force
+ def create_indexes!
+ return unless @index_creation_required
@@queue.sync do
- return if @indexes_created && !force
+ return unless @index_creation_required
@indexes.each do |collection, fields|
setup = YapDatabaseSecondaryIndexSetup.alloc.init
fields.each do |field, options|
@@ -94,10 +111,12 @@
YapDatabaseSecondaryIndexTypeText
when 'Integer'
YapDatabaseSecondaryIndexTypeInteger
when 'Time'
YapDatabaseSecondaryIndexTypeInteger
+ when 'Boolean'
+ YapDatabaseSecondaryIndexTypeInteger
else
raise "Invalid type #{type}"
end
setup.addColumn(field, withType: type)
@@ -109,43 +128,89 @@
field = field.to_s
if _collection == collection
value = case options[:type].to_s
when 'Time'
_attrs[field].to_i
+ when 'Boolean'
+ _attrs[field] ? 1 : 0 unless _attrs[field].nil?
else
_attrs[field]
end
value = NSNull if value.nil?
_dict.setObject(value, forKey: field)
end
end
end
end
- index_block = YapDatabaseSecondaryIndex.alloc.initWithSetup(setup, objectBlock: block)
+ unless Yapper::Settings.get("#{collection}_idx_defn") == @indexes[collection].to_canonical
+ Yapper::Settings.set("#{collection}_idx_defn", @indexes[collection].to_canonical)
+ configure do|yap|
+ yap.unregisterExtension("#{collection}_IDX") if yap.registeredExtension("#{collection}_IDX")
+ end
+ end
+
+ index_block = YapDatabaseSecondaryIndex.alloc.initWithSetup(setup, objectBlock: block, version: 1)
configure do |yap|
yap.registerExtension(index_block, withName: "#{collection}_IDX")
end
end
- @indexes_created = true
+ @index_creation_required = false
end
end
- def connection
- Dispatch.once { @connection ||= db.newConnection }
- @connection
+ def version
+ Yapper::Settings.db_version || 0
end
- def db
- Dispatch.once { @db ||= YapDatabase.alloc.initWithPath(document_path) }
- @db
+ def document_path
+ NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true)[0] + "/yapper.#{version}.db"
end
- def version
- Yapper::Config.db_version || 0
+ class Transaction
+ attr_accessor :txn
+
+ def initialize(db)
+ @db = db
+ end
+
+ def run(&block)
+ result = nil
+ txn_proc = proc do |_txn|
+ @txn = _txn
+ begin
+ result = block.call(@txn)
+ rescue Exception => e
+ @txn.rollback
+ result = e
+ end
+ end
+ @db.connection.readWriteWithBlock(txn_proc)
+
+ raise result if result.is_a?(Exception)
+ result
+ end
end
- def document_path
- NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true)[0] + "/yapper.#{version}.db"
+ class Notifications
+ def self.track(notifications)
+ Thread.current[:yapper_notifications] ||= {}.with_indifferent_access
+ notifications.each do |namespace, instance|
+ Thread.current[:yapper_notifications][namespace] ||= []
+ Thread.current[:yapper_notifications][namespace] << instance
+ end
+ end
+
+ def self.trigger
+ notifications = Thread.current[:yapper_notifications]
+ Thread.current[:yapper_notifications] = nil
+ notifications.each { |namespace, instances| notify(namespace, instances) }
+ end
+
+ private
+
+ def self.notify(namespace, instances)
+ NSNotificationCenter.defaultCenter.postNotificationName("yapper:#{namespace}", object: instances , userInfo: nil)
+ end
end
end