I'm trying to use the #[primarykey()] macro in Diesel but am getting an error that it is unknown. From what I have found, adding #![feature(primary_key)] should solve the issue, but it doesn't.
lib.rs
#[macro_use]
extern crate diesel;
extern crate dotenv;
pub mod schema;
pub mod models;
use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;
pub fn establish_connection() -> PgConnection {
dotenv().ok();
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
PgConnection::establish(&database_url)
.expect(&format!("Error connecting to {}", database_url))
}
models.rs
#![feature(primary_key)]
extern crate diesel;
#[derive(Queryable, Debug)]
#[primary_key(user_id)]
pub struct User {
pub user_id: i32,
pub email: String,
pub password: String,
pub bio: String,
pub verified: bool,
}
I've also tried adding #![feature(primary_key)] to the top of lib.rs without any luck.
Using Rust 1.26.0-nightly (80785a547 2018-03-30)
The primary_key attribute is only applicable when deriving Identifiable:
#[macro_use]
extern crate diesel;
mod schema {
table! {
users (user_id) {
user_id -> Int4,
email -> Text,
}
}
#[derive(Debug, Identifiable)]
#[primary_key(email)]
pub struct User {
pub user_id: i32,
pub email: String,
}
}
fn main() {}
I believe you could also just change your primary key in your schema definition (users (user_id)).
Related
How can I mock a macro attribute when testing in Rust, is there some library to facilitate this?
For instance #[my_macro] modifies a struct applying another macro #[account()] to one of his fields, this macro doesn't exist in my library but exists in the programs which are using my macro:
// lib.rs
extern crate proc_macro;
use proc_macro::TokenStream;
mod macros;
#[proc_macro_attribute]
pub fn my_macro(args: TokenStream, input: TokenStream) -> TokenStream {
proc_macro::TokenStream::from(quote!(
pub struct MyModifiedStruct{
#[account()]
pub field1: u8
}
))
}
Now how can I test my_macro without getting an error for not having the #[account()] dependency in my library?
// tests/my_test.rs
#[test]
fn test_my_macro() {
#[my_macro]
pub struct MyStruct{}
let my_struct = MyStruct{field1:1}
assert_eq!(my_struct.field1, 1)
}
My normal approach in Python would be mocking the #[account()] attribute, but not sure how can that be done in Rust.
My normal approach in Python would be mocking the #[account()] attribute, but not sure how can that be done in Rust.
You could implement a mock version of your #[account] attribute macro in the same proc-macro crate as #[my_macro] is defined and import it into the scope you are using #[my_macro] in:
lib.rs:
extern crate proc_macro;
use proc_macro::TokenStream;
mod macros;
#[proc_macro_attribute]
pub fn my_macro(args: TokenStream, input: TokenStream) -> TokenStream {
proc_macro::TokenStream::from(quote!(
pub struct MyModifiedStruct{
#[account()]
pub field1: u8
}
))
}
#[proc_macro_attribute]
pub fn account(_args: TokenStream, input: TokenStream) -> TokenStream {
input
}
tests/my_test.rs:
// tests/my_test.rs
use your_crate::{my_macro, account};
#[test]
fn test_my_macro() {
#[my_macro]
pub struct MyStruct{}
let my_struct = MyStruct{field1:1}
assert_eq!(my_struct.field1, 1)
}
I want to do a page query using rust diesel, I am using this code to do a unit test in rust:
#[cfg(test)]
mod test {
use std::env;
use diesel::{Connection, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
use rust_wheel::common::query::pagination::PaginateForQuerySource;
use crate::model::diesel::rhythm::rhythm_schema::favorites::dsl::favorites;
use crate::model::diesel::rhythm::rhythm_schema::favorites::like_status;
use crate::models::Favorites;
#[test]
fn page_test(){
use crate::model::diesel::rhythm::rhythm_schema::favorites::dsl::*;
use rust_wheel::common::query::pagination::{PaginateForQueryFragment, PaginateForQuerySource};
let conn = establish_music_connection();
let query = favorites
.filter(like_status.eq(1))
.paginate(1)
.per_page(10)
.load::<Favorites>(&conn)
.expect("query fav failed");
println!("{:?}", 1);
}
pub fn establish_music_connection() -> PgConnection {
let database_url = std::env::var("MUSIC_DATABASE_URL").expect("MUSIC_DATABASE_URL must be set");
PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
}
}
shows error like this:
error: cannot find attribute `table_name` in this scope
--> src/models.rs:15:3
|
15 | #[table_name = "favorites"]
| ^^^^^^^^^^
this is my models.rs define, this two models are store in different database:
use rocket::serde::Serialize;
use serde::Deserialize;
use crate::model::diesel::dolphin::dolphin_schema::dashboard;
use crate::model::diesel::rhythm::rhythm_schema::favorites;
#[derive(Insertable, Serialize, Queryable, Deserialize,Default)]
#[table_name = "dashboard"]
pub struct Dashboard {
pub id: i32,
pub app_count: i32,
pub user_count: i32
}
#[derive(Serialize, Queryable, Deserialize,Default)]
#[table_name = "favorites"]
pub struct Favorites {
pub id: i64,
pub song_id: String,
pub created_time: i64
}
why did this happen? what should I do to fix it?
Only the Insertable derive macro handles the #[table_name = ...] attribute. So it should not be included if you're not using it.
I have the file "user.rs" that has the struct of a postgres database table. Whenever I try to include it in my main.rs file (A Rocket web project), all of the Diesel "stuff" can't resolve. Here is my user.js file:
use super::schema::users;
pub mod handler;
pub mod repository;
pub mod router;
#[derive(Queryable, AsChangeset, Serialize, Deserialize)]
#[table_name = "users"]
pub struct User {
pub id: String,
pub username: String,
pub password: String,
}
#[derive(Insertable)]
#[table_name = "users"]
pub struct InsertableUser {
username: String,
password: String,
}
pub impl InsertableUser {
pub fn from_user(user: User) -> InsertableUser {
InsertableUser {
username: user.username,
password: user.password,
}
}
}
pub fn all(connection: &PgConnection) -> QueryResult<Vec<User>> {
users::table.load::<User>(&*connection)
}
pub fn get(id: i32, connection: &PgConnection) -> QueryResult<User> {
users::table.find(id).get_result::<User>(connection)
}
pub fn insert(user: User, connection: &PgConnection) -> QueryResult<User> {
diesel::insert_into(users::table)
.values(&InsertableUser::from_user(user))
.get_result(connection)
}
pub fn update(id: i32, user: User, connection: &PgConnection) -> QueryResult<User> {
diesel::update(users::table.find(id))
.set(&user)
.get_result(connection)
}
pub fn delete(id: i32, connection: &PgConnection) -> QueryResult<usize> {
diesel::delete(users::table.find(id)).execute(connection)
}
And here is my main.rs:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
use rocket_contrib::databases::diesel;
#[database("camera-server-db")]
struct CameraServerDbConn(diesel::PgConnection);
mod user;
#[get("/")]
fn index() -> &'static str {
"Hello World!"
}
fn main() {
rocket::ignite()
.attach(CameraServerDbConn::fairing())
.mount("/", routes![index])
.launch();
}
If I remove mod user; from main.rs, no error show up. When I run cargo check, I get many "cannot find x in this scope". Here's an example:
error: cannot find derive macro `AsChangeset` in this scope
--> src/user.rs:7:21
|
7 | #[derive(Queryable, AsChangeset, Serialize, Deserialize)]
| ^^^^^^^^^^^
I'm trying to follow this guide (which is admittedly quite out of date, but it was one of the only actual guides I could find).
As mentioned in the linked guide in the section "The last step", you need to import diesel correctly otherwise the compiler cannot resolve those traits/derives/functions. That means you need to change your main.rs file as following:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate diesel;
use rocket_contrib::databases::diesel;
#[database("camera-server-db")]
struct CameraServerDbConn(diesel::PgConnection);
mod user;
#[get("/")]
fn index() -> &'static str {
"Hello World!"
}
fn main() {
rocket::ignite()
.attach(CameraServerDbConn::fairing())
.mount("/", routes![index])
.launch();
}
(note the additional #[macro_use] extern crate diesel; in your extern crate section.)
I'm using wasm bindgen and I have following function :
#[wasm_bindgen]
pub fn obj(o: &JsValue){
console::log_1(o);
}
and in js I call this function obj({name: "john"});
and it works fine, but when i try to console::log_1(o.name);
it gives error unknown field pointing at name
JsValue does not have a field name. To get this field you have to declare the JS object.
Variant 1
Add serde to your dependencies:
serde = "^1.0.101"
serde_derive = "^1.0.101"
Rust code:
extern crate serde;
#[derive(Serialize, Deserialize)]
pub struct User {
pub name: String,
}
#[wasm_bindgen]
pub fn obj(o: &JsValue){
let user: User = o.into_serde().unwrap();
console::log_1(user.name);
}
Variant 2
Another way is to use wasm-bindgen directly but I never used it. It should work like this I think:
#[wasm_bindgen]
pub struct User {
pub name: String,
}
#[wasm_bindgen]
pub fn obj(o: User){
console::log_1(o.name);
}
I have a struct:
#[derive(Serialize,Deserialize,Debug)]
struct Post {
#[serde(rename(deserialize = "userId"))]
user_id: i32,
id: i32,
title: String,
body: String,
}
I need to deserialize JSON to Vec<Post>:
extern crate restson;
extern crate serde;
extern crate serde_derive;
use std::fs;
use std::path::Path;
use restson::{RestClient, RestPath, Error};
use serde_derive::{Serialize, Deserialize};
const URI: &str ="https://jsonplaceholder.typicode.com/";
impl RestPath<()> for Vec<Post> {
fn get_path(_: ()) -> Result<String, Error> {
Ok(String::from("posts"))
}
}
fn main() {
let mut client = RestClient::new(URI).unwrap();
let posts: Vec<Post> = client.get(()).unwrap();
println!("{:?}", posts.len());
}
I'm totally new, so please help me.