infinitered / cdq

Core Data Query for RubyMotion
MIT License
172 stars 35 forks source link

Using cdq with restkit to delete orphaned objects not playing nice #111

Closed no-itsbackpack closed 9 years ago

no-itsbackpack commented 9 years ago

So this is more of a question than an issue. I am currently using cdq with RestKit to fetch and store data, everything works as it should until I try to delete orphaned objects by passing RestKit a fetch_request_block.

rest_setup.rb

...
def _manager
  Dispatch.once do
    @_manager ||= RKObjectManager.managerWithBaseURL(NSURL.URLWithString(server)).tap do |manager|
       manager.managedObjectStore = _store
       add_fetch_request_blocks(manager)
     end
  end
 @_manager
end

def _store
  Dispatch.once do
    @_store ||= RKManagedObjectStore.alloc.initWithPersistentStoreCoordinator(cdq.stores.current).tap do |store|
      store.createManagedObjectContexts
      cdq.contexts.push(store.persistentStoreManagedObjectContext, named: :root)
      cdq.contexts.push(store.mainQueueManagedObjectContext, named: :main)
    end
  end
  @_store
end

def add_fetch_request_blocks(manager)
  manager.addFetchRequestBlock(delete_orphaned_posts)
end

def delete_orphaned_posts
  -> (url) {
    fetch_request = nil
    path_matcher = RKPathMatcher.pathMatcherWithPattern('v1/users/feed')
    dict = nil
    match = path_matcher.matchesPath(url.relativePath, tokenizeQueryStrings: true, parsedArguments: dict)

    if match
      feed = Feed.first
      posts = feed.posts.sort_by(:created_at, order: :descending)
      fetch_request =  posts.fetch_request
    end
  }
end
...

Running this code crashes when trying to access Feed.first with an error message that says cdq has not been initialized and that no contexts have been pushed onto the stack so please try running cdq.setup! even though I have clearly setup the store above.

so I then added the following line

 if match
  # added line below
  cdq.contexts.push(_store.mainQueueManagedObjectContext, named: :main) 
  posts = feed.posts.sort_by(:created_at, order: :descending)
  fetch_request =  posts.fetch_request
end

but this does not work all the time, it clears the objects when the controller is initially loaded but fails to delete anything on subsequent attempts. My guess is that I am trying to access/change the entity on a different thread, I also don't want to push a different context onto the stack every time I want to delete orphaned posts. This leads to my question:

kemiller commented 9 years ago

So I don't know how fetch request blocks work in RestKit. It's possible that gets run on a background thread; that would certainly explain why it can't find a context. I'm not quite sure what you ultimately do with fetch_request but doing that on the main thread could be the right thing. You might also need to make a child context and work with that.

no-itsbackpack commented 9 years ago

I will try running it on the main queue and let you know how it goes

no-itsbackpack commented 9 years ago

Running on the main queue solved the issue