-
-
Notifications
You must be signed in to change notification settings - Fork 727
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Protocol with CRUD operations for structs #12
Comments
Hello @chiliec, Are you asking for a protocol that would automagically add CRUD operations to your structs? |
@groue yes, exactly ) |
I did not chose this path, because :
You may not care about the point 2 and 3, and I may not convince you with them - they are API design issue. See https://github.com/groue/GRDB.swift/blob/master/DESIGN.md for more information. Yet, did you consider change tracking seriously? Even if you don't use it know, I mean. Change tracking avoids a lot of useless update requests, and has a real performance advantage (see https://gist.github.com/groue/dcdd3784461747874f41) |
BTW, what difficulty do you have adding your own insert(), update() and delete() methods to your structs? |
I've been experimenting a little. First, of course, such a protocol can be written, and that's a good news because it means that you can write it yourself. Now I'm not happy with the result, and that's not good for your issue to be solved by GRDB itself. Particularly, since protocols don't provide If you have ideas on how to resolve that, I would be happy. |
Here is some sample code for adding your own CRUD functions to your structs: // Setup database
var configuration = Configuration()
configuration.trace = { print($0) }
let dbQueue = DatabaseQueue(configuration: configuration)
try dbQueue.inDatabase { db in
try db.execute(
"CREATE TABLE persons (" +
"id INTEGER PRIMARY KEY, " +
"name TEXT, " +
"url TEXT " +
")")
}
// A Struct with CRUD operations
struct Person : RowConvertible {
var id: Int64?
var name: String?
var url: NSURL?
init(id: Int64?, name: String?, url: NSURL?) {
self.id = id
self.name = name
self.url = url
}
init(row: Row) {
id = row.value(named: "id")
name = row.value(named: "name")
url = row.value(named: "url")
}
mutating func insert(db: Database) throws {
let changes = try db.execute("INSERT INTO persons (name, url) VALUES (?, ?)", arguments: [name, url])
id = changes.insertedRowID
}
func update(db: Database) throws {
try db.execute("UPDATE persons SET name = ?, url = ? WHERE id = ?", arguments: [name, url, id])
}
func delete(db: Database) throws {
try db.execute("DELETE FROM persons WHERE id = ?", arguments: [id])
}
}
var arthur = Person(id: nil, name: "Arthur", url: nil)
var barbara = Person(id: nil, name: "Barbara", url: NSURL(string: "http://example.com"))
try dbQueue.inDatabase { db in
// Insert
try arthur.insert(db)
try barbara.insert(db)
// Update
arthur.url = NSURL(string: "http://arthur.me")
try arthur.update(db)
// Delete
try barbara.delete(db)
// Select
for person in Person.fetch(db, "SELECT * FROM persons") {
print(person)
}
} The output is:
|
What solution did you pick, @chiliec ? |
I'm still thinking :) |
Take your time! It wasn't an easy decision to leave structs out of the CRUD game... |
Hi @chiliec, I've got some news. I've tried again to write the protocol you look after, after realizing that functions declared in a protocol extension can be statically dispatched, which allows Record to reuse those methods in its own implementation, and avoid the code duplication. I was pretty happy, until... Until I stumbled upon a nasty bug in Swift. The class Person : Record { ... }
let person = Person(...)
// error: cannot use mutating member on immutable value: 'person' is a 'let' constant
person.save(db) This is a wrong error, since this kind of mutability does not apply to class instances: there is no reason for So, again, I'm afraid I still can not expose this protocol yet. But I have enough matter for a Swift bug report. |
Relevant Swift issue: https://bugs.swift.org/browse/SR-142 |
Another update. Could you please check the DatabasePersistable branch? It includes a DatabasePersistable protocol that may interest you. Will you tell me what you think? |
… dispatched. The protocol exposes default implementation for CRUD methods as statically dispatched method that are available for adopting types in their own implementations of CRUD methods. Introduce DatabasePersistable.save() (#12)
…hen there is no INTEGER PRIMARY KEY column. DatabaseTableMapping no longer extends RowConvertible. (#12)
I think we are on the way. Hold on, it's gonna ship soon. |
OK @chiliec. The DatabasePersistable protocol has landed in the master branch. It just misses a tests before a new version of the library is shipped. Documentation: https://github.com/groue/GRDB.swift#databasepersistable-protocol Let me close this issue: you will open another if the protocol leaves something to be desired. |
Thanks for your feature request, BTW 😄! |
@chiliec version v0.33.0 has just shipped with your protocol ! Er... there are two protocols, actually: check the updated documentation https://github.com/groue/GRDB.swift#databasepersistable-protocol |
Thank you! |
All my models is a structs and I can't use Record. RowConvertible protocol only allow to fetch models, but I want to give CRUD operations, at least.
The text was updated successfully, but these errors were encountered: