This is a library that contains some macros and derives to help the developer to access database using Rocket and Diesel. This is only for projects with Rocket and Diesel (Rest API). This version works with all the Diesel supported databases (MySQL, PostgreSQL and SQLite).
The idea
Because we don't have any current solution like JPA (Java Persistence API) in Rust, we decided to make one using macros and derives. Basically using a macro you can generate all the methods to access the database using Diesel framework without the need to implement all the methods for each type.
Modules
This library has 2 modules, one for derives and another for macros, we did this because Cargo doesn't let us publish if we don't separate our modules for now. In the future we could put everything in just one repository if Cargo let us do it.
Dependencies
In your project you need to import these dependencies:
# Rocket Webserver
[]
= "0.4.1"
[]
= "0.4.1"
= false
= ["json", "diesel_mysql_pool"]
#features = ["json", "diesel_postgres_pool"] if you use PostgreSQL
#features = ["json", "diesel_sqlite_pool"] if you use SQLite
# Json Serialize and Deserialize
[]
= "1.0.92"
= ["derive"]
[]
= "1.0.39"
# For connecting with the MySQL database
[]
= "1.4.2"
= ["chrono"]
# You can import this dependency like this or download this repo and import it manually
[]
= "0.2.0"
How to use it
You need to make a model structure, let's take this example using the Hero model:
As you can see here, we have a structure called Hero with some macros above. This macros are going to make magic for us. We have AsChangeset, Queryable and Insertable macros from Diesel, which are needed to access the database, also we have Serialize, Deserialize from Serde that are needed for Json Deserialization and Serialization. We have TypeInfo, Debug and Clone derives, those are used by our library. Finally you can see the Rpa macro, that's a custom macro that will generate the basics to let us access the database. You can see the methods available under the file rpa_macros/src/database/rpa.rs in the Rpa trait in the rpa_macros module. For the associations we can't define those methods in a trait because those are dynamic but we have comments on how the library generates those methods.
After we define the entity structure we can now call the generated methods like this:
use ;
use MysqlConnection;
use Json;
...
let result: = find; // to find
let json: = result.unwrap.into_json; // to convert into serde json
let hero: Hero = from_json; // to convert from serde json
...
NOTE: &*_connection in all the examples is the connection instance for the database. In Rocket that's injected by the framework with fairings and you need to initialize it. (see the rocket documentation for more information on how to do it).
For now we can only assume that the schema location will always be in src/schema.rs of the parent project. Also all the structure id's are assumed as Strings. We should improve that in the future to support more types.
Associations
We can use associations from Diesel to map relationships. Diesel is not like other ORM's because we don't have nested structures as results, instead you have to query the parent structures and then with the instance of the parent type query all the children. Is better this way because we can avoid a lot of problems that nesting structures can have and also it's more efficient (we don't query data that we don't need). We provide a way to use these associations in this library, here is how:
use Rpa;
As you can see we added Identifiable derive, which is needed by Diesel to map our structures. Now we need to have another structure to relate, like this:
use Rpa;
use crate Hero;
We have a structure Post with some reference to the Hero structure and the Identifiable derive but we need to add the Associations derive too. This is a Diesel requirement as you can see in the associations documentation.
After you follow the steps above you have available methods that you can use like this:
let hero: Hero = find.unwrap;
let posts: = find_for_hero.unwrap;
let grouped_posts: = find_grouped_by_hero.unwrap;
Some methods are generated when you use Rpa, find_for_{parent_name_lowercase} that searches for all the children owned by the parent or parents. Other method is called find_grouped_by_{parent_name_lowercase} that works like the above method but it groups the results by parents.
Different databases
By default Rpa uses Mysql but if you want to use another database we support Diesel databases, those are PostgreSQL and SQLite for now. To change the default database into another you can use an attribute called connection_type. That attribute can have only one of these 3 values ("MYSQL", "POSTGRESQL", "SQLITE") per structure. Here is how you can use it:
extern crate chrono;
use NaiveDateTime;
use Rpa;
use crate custom_date_format;
Also you need to change your Cargo.toml to use diesel_postgres_pool in rocket_contrib dependency in this case to make it work. You can have multiple databases using this library but you need to be careful with the mixes, you CAN NOT mix different structures in different DB's.
Next Steps
- Generate Schemas from structures.
- Add more useful methods to query data.
- Add some support like Spring has in Java for JPARepositories.