{"id":18463924,"url":"https://github.com/badchoice/daikiri","last_synced_at":"2025-04-08T08:30:51.171Z","repository":{"id":7803516,"uuid":"56386737","full_name":"BadChoice/daikiri","owner":"BadChoice","description":"Json \u003c-\u003e Model \u003c-\u003e CoreData made easy","archived":false,"fork":false,"pushed_at":"2025-01-13T16:19:05.000Z","size":241,"stargazers_count":5,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T08:51:14.541Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BadChoice.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-04-16T14:03:26.000Z","updated_at":"2025-01-13T16:19:00.000Z","dependencies_parsed_at":"2022-08-08T17:31:21.201Z","dependency_job_id":"2dd0a894-4a28-41af-9cc0-97d968df8de5","html_url":"https://github.com/BadChoice/daikiri","commit_stats":{"total_commits":148,"total_committers":6,"mean_commits":"24.666666666666668","dds":"0.17567567567567566","last_synced_commit":"547ca17df8b4ea109a615c56e1b2eaff0e052926"},"previous_names":[],"tags_count":86,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BadChoice%2Fdaikiri","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BadChoice%2Fdaikiri/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BadChoice%2Fdaikiri/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BadChoice%2Fdaikiri/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BadChoice","download_url":"https://codeload.github.com/BadChoice/daikiri/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247804308,"owners_count":20998945,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T09:08:22.207Z","updated_at":"2025-04-08T08:30:50.895Z","avatar_url":"https://github.com/BadChoice.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Daikiri\n\n## Description\nIts a lighweight and simple library to work with models allowing the JSON to Model to Core Data both ways.\nReally useful for server / app synchronization.\n\n## Installation\n\nUsing pods:\n\n\n```\npod 'daikiri'\n```\n\n## Usage\n\nCreate a model that inherts from `Daikiri` and add the properties you want to be automatically converted\nNote that `submodels` will automatically be converted if they also inhert from `Daikiri`\n\n#### JSON\n\n```\n#import \"Daikiri.h\"\n#import \"Headquarter.h\"\n\n@interface Hero : Daikiri\n\n@property (strong,nonatomic) NSString* name;\n@property (strong,nonatomic) NSNumber* age;\n@property (strong,nonatomic) Headquarter* headquarter;\n\n@end\n\n```\n\nThen you can do:\n\n```\nNSDictionary* d = @{\n    @\"name\" : @\"Batman\",\n    @\"age\"  : @10,\n    @\"headquarter\":@{\n        @\"address\" : @\"patata\",\n        @\"isActive\" : @1,\n        @\"vehicles\"   : @[\n            @{@\"model\" : @\"Batmobile\"},\n            @{@\"model\" : @\"Batwing\"},\n            @{@\"model\" : @\"Tumbler\"},\n        ]\n    }\n};\n\nHero * model = [Hero fromDictionary:d];    \n\n```\n\nAnd convert it back\n\n```\nNSDictionary* modelToDict = [model toDictionary];\nNSLog(@\"Model to dict: %@\",modelToDict);\n\n```\n\nYou can also convert the arrays to its class, for doing so you need to create the method \n`-(Class)property_DaikiriArray` where `property` is the name of the `NSArray` property.\n\nIn the previous case we have the model `Headquarter` like this\n\n```\n@interface Headquarter : Daikiri\n\n@property(strong,nonatomic) NSString* address;\n@property(strong,nonatomic) NSNumber* isActive;\n@property(strong,nonatomic) NSArray*  vehicles;\n\n@end\n\n```\n\nwith the following method \n\n```\n-(Class)vehicles_DaikiriArray{\n    return [Vehicle class];\n}\n\n```\n\nAnd vehicles will be converted automatically.\n\n\n#### CORE DATA\n\n##### Setup\n`Daikiri` Comes with a `CoreData` manager. It creaes the `managedObjectContents` and connects to the database named `yourprojectname.sqlite` at \n`applicationDocumentsDirectory`.\n\nYou can change the project name by setting the property `databaseName` of the `DaikiriCoreData` manager\n\n```\n[DaikiriCoreData manager].databaseName = @\"youdatabasename\";\n```\n\nYou should place this call before any other `CoreData` call so it's recomended to do it at `didFinishLaunchingWithOptions`.\n\nThe only thing you need to do is to add a call to `[[DaikiriCoreData manager] saveContex]` in your app delegate `-(void)applicationWillTerminate:(UIApplication *)application` to save the context even if there is a crash.\n\n\nHowever, you can also use you custom `CoreData` manager by overridin the `+(NSManagedObjectContext*)managedObjectContext` function in your model.\n\n```\n+(NSManagedObjectContext*)managedObjectContext{\n    NSManagedObjectContext *context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];\n    return context;\n}\n```\n\n##### Testing\nDaikiri offers a really easy method to setup the testing database as a full clean one in each test so you can fully do unint testing without any problem. It also uses transactions in each tests so everything is rolled back and the databse is clean in every test.\n\njust add these on your `setUp` and `tearDown` methods in the test\n\n```\n    - (void)setUp {\n        [super setUp];\n        [[DaikiriCoreData manager] useTestDatabase:YES];\n        [[DaikiriCoreData manager] beginTransaction];\n    }\n\n    - (void)tearDown {\n        [super tearDown];\n        [[DaikiriCoreData manager] rollback];\n    }\n\n```\n\n\n\n\n\n##### Core data models\nWith a `Daikiri` model we can work with coredata in an active recod like way. You just need to name the\nmodel the same way it is in the database `.xcdatamodeld`\n\nA `Daikiri` model comes with an `id` property that is the `primary key` used for all the following methods\n\nThen you can do the following\n\n```\n[model create] //It creates a new record in the database needs to have the id\n\nmodel.name = \"Bruce wayne\";\nmodel.age  = @10;\n\n[model save]    //Updates the record saved in the database (if it doesn't exists, it will create it)\n```\n\nWe can also\n\n```\n// Get an specific hero\nHero* batman = [Hero find:@10]; //Search the model in the database\n[batman delete];                //Deletes it from the database\n\n// Get all heros\nNSArray* allHeros = [Hero all];    \n```\n\nIf you want, there are the convenience methods to to those basic actions directly from a dictionary\n\n\n```    \n+(bool)createWith:(NSDictionary*)dict;\n+(bool)updateWith:(NSDictionary*)dict;    \n+(bool)deleteWith:(NSNumber*)id;\n```\n    \n\n\n#### Relationships\nAlongs with the `find` and `all` When your models are in the database you have diferent ways to acces their relationships\n\n`belongsTo`, `hasMany` and `belongsToMany`.\n\nCheck the examples below to understand them\n\n```\n//Add models to database\nHero * batman               = [Hero createWith:@{@\"id\":@1, @\"name\":@\"Batman\"         ,@\"age\":@49}];\nHero * spiderman            = [Hero createWith:@{@\"id\":@2, @\"name\":@\"Spiderman\"      ,@\"age\":@19}];\nHero * superman             = [Hero createWith:@{@\"id\":@3, @\"name\":@\"Superman\"       ,@\"age\":@99}];\n\nEnemy* luxor                = [Enemy createWith:@{@\"id\":@1, @\"name\":@\"Luxor\"          ,@\"age\":@32}];\nEnemy* greenGoblin          = [Enemy createWith:@{@\"id\":@2, @\"name\":@\"Green Goblin\"   ,@\"age\":@56}];\nEnemy* joker                = [Enemy createWith:@{@\"id\":@4, @\"name\":@\"Joker\"          ,@\"age\":@45}];\n\nFriend* robin               = [Friend createWith:@{@\"id\":@1, @\"name\":@\"Robin\"         ,@\"hero_id\":batman.id}];\nFriend* maryJane            = [Friend createWith:@{@\"id\":@2, @\"name\":@\"Mary Jane\"     ,@\"hero_id\":spiderman.id}];\nFriend* blackCat            = [Friend createWith:@{@\"id\":@3, @\"name\":@\"Black cat\"     ,@\"hero_id\":spiderman.id}];\n\nEnemyHero* luxorBatman      = [EnemyHero createWith:@{@\"id\":@1, @\"hero_id\":batman.id      ,@\"enemy_id\":luxor.id, @\"level\":@7}];\nEnemyHero* luxorSuperman    = [EnemyHero createWith:@{@\"id\":@2, @\"hero_id\":superman.id    ,@\"enemy_id\":luxor.id, @\"level\":@5}];\nEnemyHero* jokerBatman      = [EnemyHero createWith:@{@\"id\":@3, @\"hero_id\":batman.id      ,@\"enemy_id\":joker.id, @\"level\":@10}];\nEnemyHero* greenGoblinSpider= [EnemyHero createWith:@{@\"id\":@4, @\"hero_id\":spiderman.id   ,@\"enemy_id\":greenGoblin.id, @\"level\":@10}];\n\n\nNSLog(@\"Robin's hero is: %@\",robin.hero.name);      //Belongs to\n\nfor(Friend* friend in spiderman.friends){           //has many\n    NSLog(@\"Spiderman friend: %@\",friend.name);\n}\n\nfor(Enemy* enemy in batman.enemies){                //Belongs to many\n    NSLog(@\"Batman enemy: %@ with level: %@\",enemy.name, ((EnemyHero*)enemy.pivot).level);\n}\n```\n\n#### Query builder\nWe have a `QueryBuilder` to create custom queries, you can do things like\n\n```\nEnemyHero * enemyHero = [[EnemyHero.query\n                            where:@\"hero_id\"  is:batman.id]\n                            where:@\"enemy_id\" is:joker.id]\n                        .first;\n\nNSArray * heroes = [[Hero.query \n                        where:@\"id\" operator:@\"\u003e\" value:@2] \n                        orderBy:@\"age\"]\n                    .get;\n\nfor(Hero * hero in heroes){\n    NSLog(@\"Hero: %@\",hero.name);\n}\n\n```\n\nIf you class names use a prefix (two chars) and your entities don't, you can override the function\n`usesPrefix` to return `true`. This will remove the prefix when fetching to the DB\n\n\n#### Factory\n`Daikiri` comes with a Laravel Like factory class for tests. You can have you factories to create tests objects for you and making each test look very neat.\n\n#### Usage\nFirst create a factory class with a simple `registerFactories` method and create the factories giving a simple dict\n\n@implementation HeroFactory\n\n```\n+(void)registerFactories{\n\n    [DKFactory define:Hero.class builder:^NSDictionary *{\n        return @{\n            @\"name\": @\"Batman\",\n            @\"age\" : @\"49\"\n        };\n    }];\n\n    [DKFactory define:Enemy.class builder:^NSDictionary *{\n        return @{\n            @\"name\": @\"Luxor\",\n            @\"age\" : @\"32\"\n        };\n    }];\n}\n```\n\n##### Factory states\nYou can have some diferent types of you class you can define with another name (it will merge the default one and the new one)\n\n```\n+(void)registerFactories{\n\n    [DKFactory define:Hero.class builder:^NSDictionary *{\n        return @{\n            @\"name\": @\"Batman\",\n            @\"age\" : @\"49\"\n        };\n    }];\n\n    [DKFactory define:Hero.class name:@\"old\" builder:^NSDictionary *{\n        return @{\n            @\"age\" : @\"100\"\n        };\n    }];\n}\n```\n\nThen on your testClass setup method call the `[Yourfactory registerFactories]`.\n\nAfter that on your tests you can instantiate any class with a simply call to\n\n\n```\n    Hero* testHero   = [factory(Hero.class)  make];\n    Enemy* testEnemy = [factory(Enemy.class) create];\n```\n\nNote that `make` just creates the object without storing it to the database but `create` does store it to the database.\n\nYou can use the non macro constructor to have more options\n\n```\n    NSArray* oldHerosArray = [[DKFactory factory:Hero.class name:@\"old\" count:4] make];\n```\n\n##### Relationships\nThe cool thing in the factory is that you can use callbacks to create relationships so you can do something like this:\n\n```\n    [DKFactory define:Headquarter.class builder:^NSDictionary *{\n        return @{\n            @\"name\": @\"Star tower\",\n            @\"hero_id\" : ^{\n                return ((Daikiri*)[factory(Hero.class) create]).id;\n            }\n        };\n    }];\n```\n\nAnd the Hero will be only created when insantiating the object in the `make` or `create`, isn't it cool?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbadchoice%2Fdaikiri","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbadchoice%2Fdaikiri","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbadchoice%2Fdaikiri/lists"}