use rust_eloquent::{Eloquent, sqlx::FromRow, EloquentModel};
use rust_eloquent::schema::{Schema, Blueprint};
#[derive(Debug, Clone, FromRow, rust_eloquent::Eloquent)]
#[eloquent(table = "comments")]
pub struct Comment {
pub id: i32,
pub body: String,
pub commentable_id: i32,
pub commentable_type: String,
}
#[derive(Debug, Clone, FromRow, rust_eloquent::Eloquent)]
#[eloquent(table = "posts")]
pub struct Post {
pub id: i32,
pub title: String,
#[eloquent(morph_many = "Comment", name = "commentable")]
#[sqlx(skip)]
pub comments: Option<Vec<Comment>>,
}
#[derive(Debug, Clone, FromRow, rust_eloquent::Eloquent)]
#[eloquent(table = "videos")]
pub struct Video {
pub id: i32,
pub url: String,
#[eloquent(morph_many = "Comment", name = "commentable")]
#[sqlx(skip)]
pub comments: Option<Vec<Comment>>,
}
#[tokio::main]
async fn main() -> Result<(), rust_eloquent::sqlx::Error> {
let _ = std::fs::remove_file("polymorphic.db");
std::fs::File::create("polymorphic.db").unwrap();
Eloquent::init("sqlite://polymorphic.db").await?;
Schema::create("posts", |table| {
table.id();
table.string("title").not_null();
}).await?;
Schema::create("videos", |table| {
table.id();
table.string("url").not_null();
}).await?;
Schema::create("comments", |table| {
table.id();
table.string("body").not_null();
table.integer("commentable_id").not_null();
table.string("commentable_type").not_null();
}).await?;
let mut post = Post { id: 0, title: "Rust ORM Guide".to_string(), comments: None };
post.save().await?;
let mut video = Video { id: 0, url: "https://youtube.com/rust".to_string(), comments: None };
video.save().await?;
let mut c1 = Comment {
id: 0,
body: "Great post!".to_string(),
commentable_id: post.id,
commentable_type: Post::table_name().to_string()
};
c1.save().await?;
let mut c2 = Comment {
id: 0,
body: "Awesome video!".to_string(),
commentable_id: video.id,
commentable_type: Video::table_name().to_string()
};
c2.save().await?;
let fetched_post = Post::query().with_comments().first().await?.unwrap();
println!("Post: {}", fetched_post.title);
for comment in fetched_post.comments.unwrap() {
println!(" - Comment: {}", comment.body);
}
let fetched_video = Video::query().with_comments().first().await?.unwrap();
println!("Video: {}", fetched_video.url);
for comment in fetched_video.comments.unwrap() {
println!(" - Comment: {}", comment.body);
}
Ok(())
}