-
-
Notifications
You must be signed in to change notification settings - Fork 27
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
Docs goodies #1 #398
Docs goodies #1 #398
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
## Red starter tutorial | ||
|
||
This document is an introduction tutorial which shows the most basic usage examples of Red. | ||
For more in-depth introduction about Red architecture visit [Red architecture](tutorials/architecture) page. | ||
|
||
### Models and tables | ||
|
||
Red is an Object-Relational Mapping (ORM) tool for Perl 6. | ||
|
||
Simply speaking, it allows you to "hide" the layer of interaction | ||
with your relational database and work with Perl 6 objects instead. | ||
|
||
Currently, PostgreSQL and SQLite3 relation databases are supported. | ||
|
||
Let's start with a simple table: | ||
|
||
```sql | ||
CREATE TABLE person( | ||
id integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
name varchar(255) NOT NULL | ||
); | ||
``` | ||
|
||
With this query executed in your database console, a table named `person` was created with | ||
two columns: `id` which is an integer ID of the record, it is a primary key and is | ||
incremented automatically, and `name` which is a string of maximum 255 characters, which is not null. | ||
|
||
In Red, each table is represented using a special type of class called "model". It can do | ||
everything what a usual class can do, but also helps you to interact with your table. | ||
|
||
Red models use `model` keyword instead of `class`: | ||
|
||
```perl6 | ||
model Person { | ||
has Int $.id is serial; | ||
has Str $.name is column is rw; | ||
} | ||
|
||
my $*RED-DB = database “SQLite”; | ||
``` | ||
|
||
We described a model called `Person`. The first attribute `$.id` is typed to be `Int` | ||
and is marked with `is serial` trait. This trait marks the column as a primary one with | ||
autoincrement enabled. The next attribute `$.name` is marked with `is column` trait, which | ||
means this attribute will be mapped onto a column in the table, and is typed as Str. | ||
|
||
Note we don't need to specify that the column is not nullable, as it is the default. | ||
|
||
The second statement specifies a database to work with. In this case, | ||
an in-memory SQLite database is used, which means all changes will be lost after | ||
the script termination. To avoid this, we can specify a name for the database file: | ||
|
||
```perl6 | ||
my $*RED-DB = database “SQLite”, database => 'test.sqlite3'; # Now a file `test.sqlite3` will be created | ||
``` | ||
|
||
Next, we need to create a table itself: | ||
|
||
|
||
```perl6 | ||
Person.^create-table; | ||
``` | ||
|
||
Methods marked with `^` are called "meta methods" and are used in Red | ||
for all kinds of operations on models. In this case, calling `^create-table` | ||
creates a table with name `person`. | ||
|
||
### Insertion of new records | ||
|
||
Let's insert a new record into it. In SQL it could be: | ||
|
||
```sql | ||
INSERT INTO person (name) VALUES 'John'; | ||
``` | ||
|
||
In Red we can express it this way: | ||
|
||
```perl6 | ||
my $person = Person.^create(name => 'John'); | ||
``` | ||
|
||
We call the `^create` method on type object `Person` and assign the result | ||
to the `$person` variable. The assignment is not necessary: | ||
|
||
```perl6 | ||
Person.^create(name => 'John'); | ||
``` | ||
|
||
The `^create` method returns the created object to work with, though | ||
this result can be simply ignored. | ||
|
||
The `$.id` attribute is auto-generated and there is no need to specify it, | ||
while `$.name` attribute must not be null, so we have to specify it: | ||
|
||
```perl6 | ||
Person.^create; # error | ||
``` | ||
|
||
### Update of records | ||
|
||
Let's try to update our record. In SQL it could be: | ||
|
||
```sql | ||
UPDATE person SET name = ‘John Doe’ WHERE id = 1; | ||
``` | ||
|
||
To do the same in Red, we use setters and a call to `^save`: | ||
|
||
```perl6 | ||
$person.name = 'John Doe'; | ||
$person.^save; | ||
``` | ||
|
||
All changes to an object that represents the record are lazy, | ||
which means the database connection is not used until the `^save` | ||
method is called. | ||
|
||
The method `^save` is useful not only for UPDATE operation, but it can be used on | ||
INSERT too: | ||
|
||
```perl6 | ||
my $person2 = Person.new(name => 'Joan'); # ^create is not used | ||
$person2.^save; # does INSERT, not UPDATE | ||
``` | ||
|
||
### Selecting records | ||
|
||
Lets add some more records: | ||
|
||
```perl6 | ||
Person.new(name => "Paul"); # Method call with parentheses and an arrow pair | ||
Person.new: :name<Miki>; # Semicolon form of method call is used | ||
``` | ||
|
||
Lets begin with selecting all records of the table: | ||
|
||
```sql | ||
SELECT * FROM person; | ||
``` | ||
|
||
In Red, `^all` method is used: | ||
|
||
```perl6 | ||
for Person.^all -> $person { say $person } | ||
``` | ||
|
||
Method `^all` returns an instance of class `Seq` that is a lazy sequence of records returned. | ||
|
||
```sql | ||
SELECT * FROM person WHERE person.name like 'Jo%'; | ||
``` | ||
|
||
The query above selects all records where name starts with 'Jo'. In Red, you can use Perl 6 `grep` | ||
method to specify clauses of the select query: | ||
|
||
```perl6 | ||
for Person.^all.grep(*.name.starts-with('Jo')) -> $person { say $person } | ||
``` | ||
|
||
Note that this call chain will result into an equivalent of the SQL code above, | ||
filtering values happens at the database level, not at Perl 6 level. | ||
|
||
```sql | ||
SELECT * FROM person WHERE person.name like 'Jo%' AND person.id = 2; | ||
``` | ||
|
||
To express the query above, calls to `grep` can be combined: | ||
|
||
```perl6 | ||
for Person.^all.grep(*.name.starts-with('Jo')).grep(*.id == 2) -> $person { say $person } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could use Person.^all.grep({ .name.starts-with('Jo') && .id == 2 }) as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also tried There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Altai-man, no... that would generate a block that would receive 2 args... that’s the problem... |
||
``` | ||
|
||
### Selecting a single record | ||
|
||
To get a single record, `^load` method is used. It accepts an arbitrary number of pairs | ||
describing the object properties for the WHERE clause of a SELECT statement. One difference | ||
between using `^all` and `^load` is that the `^load` method returns either a value or a `Nil` | ||
if there are no fitting records, while `^all` returns a `Seq` that might come | ||
with an arbitrary number of elements. The second difference is that `^all` can express | ||
various SELECT statements, while `^load` is restricted to work with columns marked as PRIMARY | ||
and UNIQUE only. | ||
|
||
```perl6 | ||
say Person.^load(id => 4); # correct | ||
# when the primary column is unambiguous, only its value can be passed | ||
say Person.^load(4); # correct, same as `id => 4` | ||
# however, `^load does not work for non-primary columns: | ||
say Person.^load(:name<Foo>); # error | ||
``` | ||
|
||
### Deleting rows | ||
|
||
To delete rows, the `^delete` method is used. It can be called on an individual | ||
object or on a model to delete all records: | ||
|
||
```perl6 | ||
# DELETE FROM person WHERE person.id = 42; | ||
$p.^delete; | ||
# DELETE FROM person; | ||
Person.^delete; | ||
``` | ||
|
||
Here, we covered basics of Red usage. Refer to Red cookbook | ||
for different examples without a particular order or visit the next | ||
tutorial in this series, related to expressing table relationships | ||
using Red, [here](tutorials/relationships). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,72 @@ | ||
- [introduction](introduction) | ||
- [general](https://github.com/FCO/Red/wiki) | ||
- [API](API) | ||
### Red ORM documentation | ||
|
||
Welcome to Red ORM documentation. | ||
|
||
#### Tutorials | ||
|
||
If you are looking for tutorials, you can visit: | ||
|
||
* [Beginner tutorial](tutorials/start) | ||
* Relationships tutorial | ||
* Red CLI | ||
* Working with PostgreSQL | ||
* Working with SQLite | ||
* Red Cookbook | ||
|
||
#### API documentation | ||
|
||
If you are looking for pure API docs, here you go: | ||
|
||
* [API Index page](API) | ||
|
||
#### Wiki | ||
|
||
More examples can be found at the project [Wiki](https://github.com/FCO/Red/wiki) page. | ||
|
||
#### For developers | ||
|
||
* [Red architecture](tutorials/architecture) | ||
* How to create a new driver | ||
* How to create a new cache | ||
|
||
#### How to contribute to documentation | ||
|
||
##### I want to document something | ||
|
||
To document an entity of Red itself (class, operator, | ||
routine etc), do it as Pod6 in the source file. For example, before: | ||
|
||
```perl6 | ||
sub prefix:<Σ>( *@number-list ) is export { | ||
[+] @number-list | ||
} | ||
``` | ||
|
||
After: | ||
|
||
```perl6 | ||
#| A prefix operator that sums numbers | ||
#| It accepts an arbitrary length list of numbers and returns their sum | ||
#| Example: say Σ (13, 16, 1); # 30 | ||
sub prefix:<Σ>( *@number-list ) is export { | ||
[+] @number-list | ||
} | ||
``` | ||
|
||
Then execute `perl6 tools/make-docs.p6` to generate documentation | ||
pages with your symbols included. | ||
|
||
If you want to add a tutorial, write it as Markdown and add to `docs` | ||
directory of this repository. | ||
|
||
##### I want to change existing documentation | ||
|
||
Depending on what it is, the documentation might be generated or not. | ||
|
||
* Try to run a search in the repository for a line you want to change, for example, `grep -R "bad typo" .` | ||
* If you see more than two files, try to narrow your search pattern | ||
* If you see two files found, most likely one will be corresponding to sources or generated Markdown documentation. Please, patch the documentation in sources and, after re-generating pages with `tools/make-docs.p6` script, send a PR. | ||
* If you see a single file found, Markdown file with a tutorial or this introduction text, please, patch it and send a PR. | ||
* When not sure, please, create a ticket at [Red bugtracker](https://github.com/FCO/Red/issues) | ||
|
||
All pull requests are welcome! |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This to lines are not inserting on the database... they are just creating objects. It should call
.^save
or have used.^create
to store on the databaseThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, nice catch!