- Notifications
You must be signed in to change notification settings - Fork27
FCO/Red
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Take a look at our Documentation:https://fco.github.io/Red/
Install with (you needrakudo 2018.12-94-g495ac7c00 ornewer):
zef install Red
use Red:api<2>;model Person {...}model Postisrw {hasInt$.idis serial;hasInt$!author-idis referencing(*.id,:model(Person) );hasStr$.titleis column{:unique };hasStr$.bodyis column;has Person$.authoris relationship{.author-id };hasBool$.deletedis column=False;hasDateTime$.createdis column.= now;hasSet$.tagsis column{:type<string>,:deflate{.keys.join:"," },:inflate{ set(.split:",") } }= set();methoddelete {$!deleted=True;self.^save }}model Personisrw {hasInt$.idis serial;hasStr$.nameis column;has Post@.postsis relationship{.author-id };methodactive-posts {@!posts.grep:not*.deleted }}my$*RED-DB= database"SQLite";Person.^create-table;
-- Equivalent to the following query:CREATETABLEperson( idintegerNOT NULLprimary key AUTOINCREMENT, namevarchar(255)NOT NULL)
Post.^create-table;
-- Equivalent to the following query:CREATETABLEpost( idintegerNOT NULLprimary key AUTOINCREMENT, author_idintegerNULLreferences person(id), titlevarchar(255)NOT NULL, bodyvarchar(255)NOT NULL, deletedintegerNOT NULL, createdvarchar(32)NOT NULL, tagsvarchar(255)NOT NULL, UNIQUE (title))
my Post$post1= Post.^load::42id;
-- Equivalent to the following query:SELECTpost.id,post.author_idas"author-id",post.title,post.body,post.deleted,post.created,post.tagsFROM postWHEREpost.id=42
my Post$post1= Post.^load:42;
-- Equivalent to the following query:SELECTpost.id,post.author_idas"author-id",post.title,post.body,post.deleted,post.created,post.tagsFROM postWHEREpost.id=42
my Post$post1= Post.^load::title("my title");
-- Equivalent to the following query:SELECTpost.id,post.author_idas"author-id",post.title,post.body,post.deleted,post.created,post.tagsFROM postWHEREpost.title= ‘my title’
my$person= Person.^create::name<Fernando>;
-- Equivalent to the following query:INSERT INTO person( name)VALUES( $1) RETURNING*-- BIND: ["Fernando"]
RETURNS:Person.new(name=>"Fernando")
say$person.posts;
-- Equivalent to the following query:SELECTpost.id,post.author_idas"author-id",post.title,post.body,post.deleted,post.created,post.tagsFROM postWHEREpost.author_id= ?-- BIND: [1]
say Person.new(:2id).active-posts.grep: {.created> now }
-- Equivalent to the following query:SELECTpost.id,post.author_idas"author-id",post.title,post.body,post.deleted,post.created,post.tagsFROM postWHERE (post.author_id= ?AND (post.deleted==0ORpost.deleted ISNULL ) )ANDpost.created>1554246698.448671-- BIND: [2]
my$now= now;say Person.new(:3id).active-posts.grep: {.created>$now }
-- Equivalent to the following query:SELECTpost.id,post.author_idas"author-id",post.title,post.body,post.deleted,post.created,post.tagsFROM postWHERE (post.author_id= ?AND (post.deleted==0ORpost.deleted ISNULL ) )ANDpost.created> ?-- BIND: [-- 3,-- Instant.from-posix(-- <399441421363/257>,-- Bool::False-- )-- ]
Person.^create::name<Fernando>,:posts[ {:title("My new post"),:body("A long post") }, ];
-- Equivalent to the following query:INSERT INTO person( name)VALUES( ?) RETURNING*-- BIND: ["Fernando"]INSERT INTO post( created, title, author_id, tags, deleted, body)VALUES( ?, ?, ?, ?, ?, ?) RETURNING*-- BIND: [-- "2019-04-02T22:55:13.658596+01:00",-- "My new post",-- 1,-- "",-- Bool::False,-- "A long post"-- ]
my$post= Post.^load::title("My new post");
-- Equivalent to the following query:SELECTpost.id,post.author_idas"author-id",post.title,post.body,post.deleted,post.created,post.tagsFROM postWHEREpost.title= ‘My new post’-- BIND: []
RETURNS:Post.new(title=>"My new post",body=>"A long post",deleted=>0,created=>DateTime.new(2019,4,2,23,7,46.677388,:timezone(3600) ),tags=>Set.new(""))
say$post.body;
PRINTS:Along post
my$author=$post.author;
RETURNS:Person.new(name=>"Fernando")
$author.name="John Doe";$author.^save;
-- Equivalent to the following query:UPDATE personSET name= ‘John Doe’WHERE id=1
$author.posts.create::title("Second post"),:body("Another long post");
-- Equivalent to the following query:INSERT INTO post( title, body, created, tags, deleted, author_id)VALUES( ?, ?, ?, ?, ?, ?) RETURNING*-- BIND: [-- "Second post",-- "Another long post",-- "2019-04-02T23:28:09.346442+01:00",-- "",-- Bool::False,-- 1-- ]
$author.posts.elems;
-- Equivalent to the following query:SELECTcount(*)as"data_1"FROM postWHEREpost.author_id= ?-- BIND: [1]
RETURNS:2
Red is aWiP ORM for Raku.
is column
is column{}
is id
is id{}
is serial
is referencing{}
is relationship{}
is table<>
is nullable
Red will infer relationship data if you use type constraints on your properties.
# Single file e.g. Schema.pm6model Related {... }# belongs tomodel MyModel {hasInt$!related-idis referencing(*.id,:model<Related> );has Related$.relatedis relationship{.id };}# has one/has manymodel Related {hasInt$.idis serial;has MyModel@.my-modelsis relationship{.related-id };}
If you want to put your schema into multiple files, you can create an "indirect" relationship, and Red will look up the related models as necessary.
# MyModel.pm6model MyModel {hasInt$!related-idis referencing{:model<Related>,:column<id> };has$.relatedis relationship({.id },:model<Related>);}# Related.pm6model Related {hasInt$.idis serial;has@.my-modelsis relationship({.related-id },:model<MyModel>);}
If Red can’t find where yourmodel
is defined you can override where it looks withrequire
:
hasInt$!related-idis referencing{:model<Related>,:column<id>,:require<MyApp::Schema::Related> };
model MyModelis table<custom_table_name> {}
Red, by default, has not nullable columns, to change it:
#| This makes this model’s columns nullable by defaultmodel MyModelis nullable {hasInt$.col1is column;#= this column is nullablehasInt$.col2is column{:!nullable };#= this one is not nullable}
MyModel.^load:42;MyModel.^load:id=>42;
$object.^save;
Question.^all.grep: {.answer==42 };# returns a result seq
before-create
after-create
before-update
after-update
before-delete
after-delete
model Blaistemp {... }
Question.^create-table;Question.^create-table::if-not-exists;Question.^create-table::unless-exists;
Question.^all.grep:*.answer⊂ (3.14,13,42)
Post.^create::body("bla ble bli blo blu"),:title("qwer");model Tree {hasUInt$!idis id;hasStr$.valueis column;hasUInt$!parent-idis referencing{ Tree.id };has Tree$.parentis relationship{.parent-id };has Tree@.kidsis relationship{.parent-id };}Tree.^create-table::if-not-exists;Tree.^create::value<Bla>,:parent{:value<Ble>},:kids[ {:value<Bli>}, {:value<Blo>}, {:value<Blu>} ];
Fernando Correa de Oliveirafernandocorrea@gmail.com
Copyright 2018 Fernando Correa de Oliveira
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.
About
A WiP ORM for Raku