I have the following model:
use diesel::prelude::*;
use crate::schema::category;
#[derive(Debug, Identifiable, Queryable)]
#[table_name = "category"]
pub struct Category {
pub id: i64,
pub name: String,
pub description: String,
pub parent_id: Option<i64>,
}
#[derive(Debug, Insertable)]
#[table_name = "category"]
pub struct NewCategory<'a> {
pub name: &'a str,
pub description: &'a str,
pub parent_id: &'a Option<i64>,
}
and schema.rs:
table! {
category (id) {
id -> Integer,
name -> Text,
description -> Text,
parent_id -> Nullable<Integer>,
}
}
However, when I try to compile this code, I get the following errors:
error[E0277]: the trait bound `std::option::Option<i64>: diesel::Expression` is not satisfied
--> src/models/categories.rs:15:17
|
15 | #[derive(Debug, Insertable)]
| ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `std::option::Option<i64>`
|
= note: required because of the requirements on the impl of `diesel::Expression` for `&std::option::Option<i64>`
error[E0277]: the trait bound `std::option::Option<i64>: diesel::Expression` is not satisfied
--> src/models/categories.rs:15:17
|
15 | #[derive(Debug, Insertable)]
| ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `std::option::Option<i64>`
|
= note: required because of the requirements on the impl of `diesel::Expression` for `&'a std::option::Option<i64>`
What do I need to get this to work? I've looked around, but the only similar issue that I've found is when someone had more than 16 columns in their table, which is not the case here.
Modify pub parent_id: &'a Option<i64> to place the &'a inside of the Option: pub parent_id: Option<&'a i64>.
Related
I am trying to create a struct that has a hashmap of changed values.
Example:
#[derive(Debug, Clone, Eq, PartialEq)]
struct ItemChange {
time: i64,
metadata: HashMap<String, String>,
changed_metadata: HashMap<String, String>,
user_defined_description: String,
description: String,
}
#[derive(Debug, Clone)]
pub struct ProductItem {
id: String,
/// Ordered change_history by date
change_history: HashMap<ItemChange, i64>,
}
impl ProductItem {
pub fn add_change(&self, change: ItemChange, date: i64) {
self.change_history.insert(); // <-- change_history doesn't have insert :(
}
}
The code doesn't compile with an error saying
58 | struct ItemChange {
| ----------------- doesn't satisfy `ItemChange: Hash`
...
97 | self.change_history.insert();
| ^^^^^^
|
= note: the following trait bounds were not satisfied:
`ItemChange: Hash`
help: consider annotating `ItemChange` with `#[derive(Hash)]`
What am I doing wrong?
I have the following two structs for which I derive serde traits.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Item<'a> {
pub id: &'a str,
pub name: &'a str
}
#[derive(Serialize, Deserialize)]
struct Set<'a> {
items: Vec<Item<'a>>
}
When I try to compile this, I am getting am getting the following error message to ensure that lifetime parameter 'de from Deserialize needs to outlife lifetime parameter 'a:
15 | #[derive(Serialize, Deserialize)]
| ----------- lifetime `'de` defined here
16 | struct Set<'a> {
| -- lifetime `'a` defined here
17 | sets: Vec<Item<'a>>
| ^^^^ requires that `'de` must outlive `'a`
|
= help: consider adding the following bound: `'de: 'a`
But when I add the required bound as follows, I am getting an error message that 'de is not used.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Item<'a> {
pub id: &'a str,
pub name: &'a str
}
#[derive(Serialize, Deserialize)]
struct Set<'a, 'de: 'a> {
items: Vec<Item<'a>>
}
16 | struct Set<'a, 'de: 'a> {
| ^^^ unused parameter
|
= help: consider removing `'de`, referring to it in a field, or using a marker such as `PhantomData`
How can I fix this?
You need to add #[serde(borrow)] to the sets field:
#[derive(Serialize, Deserialize)]
struct Set<'a> {
#[serde(borrow)]
items: Vec<Item<'a>>,
}
This will bound the 'de lifetime in the generated code on 'a. Note that this happens implicitly for fields of type &str or &[u8], but for anything else you need to expicitly request the trait bound.
I've got the following code:
use std::fmt::Debug;
use rocket::serde::{Serialize};
#[serde(crate = "rocket::serde")]
pub trait ComponentDto: Debug + Send + Sync + Serialize {}
use rocket::serde::{Deserialize, Serialize};
#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
pub struct ParagraphDto {
pub id: i32,
pub uuid: String,
pub user_id: i32,
pub project_id: i32,
pub position: i32,
pub component: Box<dyn ComponentDto>,
pub status: String,
pub created_at: String,
pub updated_at: String,
}
impl ParagraphDto {
How do I serialize trait object using rocket::serde?
Using rockett::serde as a normal struct to trait object results in the following error:
Compiling testa v0.1.0 (/mnt/repository/repository/projects/rust/testa)
error[E0038]: the trait `MyTrait` cannot be made into an object
--> src/main.rs:21:20
|
21 | fn getStruct() -> Box<dyn MyTrait> {
| ^^^^^^^^^^^^^^^^^ `MyTrait` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits. html#object-safety>
I would like to store timezone-aware dates in Postgres, but I am struggling figure out how to do so. I have included the chrono feature for diesel in my cargo.toml.
Here is the relevant portion of my schema.rs:
table! {
budgets (id) {
id -> Uuid,
is_shared -> Bool,
is_private -> Bool,
is_deleted -> Bool,
name -> Varchar,
description -> Nullable<Text>,
start_date -> Timestamptz,
end_date -> Timestamptz,
latest_entry_time -> Timestamp,
modified_timestamp -> Timestamp,
created_timestamp -> Timestamp,
}
}
And my model:
#[derive(Debug, Serialize, Deserialize, Associations, Identifiable, Queryable, QueryableByName)]
#[table_name = "budgets"]
pub struct Budget {
pub id: uuid::Uuid,
pub is_shared: bool,
pub is_private: bool,
pub is_deleted: bool,
pub name: String,
pub description: Option<String>,
pub start_date: DateTime<FixedOffset>,
pub end_date: DateTime<FixedOffset>,
pub latest_entry_time: NaiveDateTime,
pub modified_timestamp: NaiveDateTime,
pub created_timestamp: NaiveDateTime,
}
#[derive(Debug, Insertable)]
#[table_name = "budgets"]
pub struct NewBudget<'a> {
pub id: uuid::Uuid,
pub is_shared: bool,
pub is_private: bool,
pub is_deleted: bool,
pub name: &'a str,
pub description: Option<&'a str>,
pub start_date: DateTime<FixedOffset>,
pub end_date: DateTime<FixedOffset>,
pub latest_entry_time: NaiveDateTime,
pub modified_timestamp: NaiveDateTime,
pub created_timestamp: NaiveDateTime,
}
When I try to build, I get this error when I try to use the model:
error[E0277]: the trait bound `chrono::DateTime<chrono::FixedOffset>: FromSql<diesel::sql_types::Timestamptz, Pg>` is not satisfied
--> src/utils/db/budget.rs:20:42
|
20 | let budget = budgets.find(budget_id).first::<Budget>(db_connection)?;
| ^^^^^ the trait `FromSql<diesel::sql_types::Timestamptz, Pg>` is not implemented for `chrono::DateTime<chrono::FixedOffset>`
|
= help: the following implementations were found:
<chrono::DateTime<Utc> as FromSql<diesel::sql_types::Timestamptz, Pg>>
= note: required because of the requirements on the impl of `diesel::Queryable<diesel::sql_types::Timestamptz, Pg>` for `chrono::DateTime<chrono::FixedOffset>`
= note: 2 redundant requirements hidden
= note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Uuid, diesel::sql_types::Bool, diesel::sql_types::Bool, diesel::sql_types::Bool, diesel::sql_types::Text, diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Timestamptz, diesel::sql_types::Timestamptz, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp), Pg>` for `Budget`
= note: required because of the requirements on the impl of `LoadQuery<_, Budget>` for `diesel::query_builder::SelectStatement<budgets::table, query_builder::select_clause::DefaultSelectClause, query_builder::distinct_clause::NoDistinctClause, query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<budgets::columns::id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, &uuid::Uuid>>>, query_builder::order_clause::NoOrderClause, query_builder::limit_clause::LimitClause<diesel::expression::bound::Bound<BigInt, i64>>>`
note: required by a bound in `first`
--> /Users/tanner/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-1.4.8/src/query_dsl/mod.rs:1343:22
|
1343 | Limit<Self>: LoadQuery<Conn, U>,
| ^^^^^^^^^^^^^^^^^^ required by this bound in `first`
Here is the function that the error refers to:
pub fn get_budget_by_id(
db_connection: &DbConnection,
budget_id: &Uuid,
) -> Result<OutputBudget, diesel::result::Error> {
let budget = budgets.find(budget_id).first::<Budget>(db_connection)?;
let loaded_categories = Category::belonging_to(&budget).load::<Category>(db_connection)?;
let output_budget = OutputBudget {
id: budget.id,
is_shared: budget.is_shared,
is_private: budget.is_private,
is_deleted: budget.is_deleted,
name: budget.name,
description: budget.description,
categories: loaded_categories,
start_date: budget.start_date,
end_date: budget.end_date,
latest_entry_time: budget.latest_entry_time,
modified_timestamp: budget.modified_timestamp,
created_timestamp: budget.created_timestamp,
};
Ok(output_budget)
}
I would like to be able to store timestamps from multiple timezones. Can I only use chrono::DateTime<Utc> or am I missing something?
We're trying to return structure in RPC, but as far as I understand it should be serializable:
error[E0277]: the trait bound `pallet_spaces::Space<T>: serde::de::Deserialize<'_>` is not satisfied
--> pallets/spaces/rpc/src/lib.rs:15:1
|
15 | #[rpc]
| ^^^^^^ the trait `serde::de::Deserialize<'_>` is not implemented for `pallet_spaces::Space<T>`
|
= note: required because of the requirements on the impl of `for<'de> serde::de::Deserialize<'de>` for `std::vec::Vec<pallet_spaces::Space<T>>`
= note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `std::vec::Vec<pallet_spaces::Space<T>>`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
The problem is that we use T::Moment from pallet_timestamp and it's not serializable, so we stuck at this point:
error[E0277]: the trait bound `<T as pallet_timestamp::Trait>::Moment: _::_serde::Serialize` is not satisfied
--> pallets/spaces/src/lib.rs:25:5
|
25 | pub created: WhoAndWhen<T>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `_::_serde::Serialize` is not implemented for `<T as pallet_timestamp::Trait>::Moment`
|
= note: required because of the requirements on the impl of `_::_serde::Serialize` for `pallet_utils::WhoAndWhen<T>`
= note: required by `_::_serde::ser::SerializeStruct::serialize_field`
What can you suggest to easily return a structure like this?
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, Serialize, Deserialize)]
pub struct Space<T: Trait> {
pub id: SpaceId,
pub created: WhoAndWhen<T>,
pub updated: Option<WhoAndWhen<T>>,
pub owner: T::AccountId,
// Can be updated by the owner:
pub parent_id: Option<SpaceId>,
pub handle: Option<Vec<u8>>,
pub content: Content,
pub hidden: bool,
pub posts_count: u32,
pub hidden_posts_count: u32,
pub followers_count: u32,
pub score: i32,
/// Allows to override the default permissions for this space.
pub permissions: Option<SpacePermissions>,
}
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, Serialize, Deserialize)]
pub struct WhoAndWhen<T: Trait> {
pub account: T::AccountId,
pub block: T::BlockNumber,
pub time: T::Moment,
}
Your main problem is that you are mixing std and no-std here. Substrate only depends on serde in std mode, as you can learn about in literally any Cargo.toml file in the project.
Start by fixing this: You only derive serde::* when you are in std mode.
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)]
pub struct Space<T: Trait> {
// snip..
}