When I run below code it compiles but it won't update any todo item and affected_rows is equal to 0. What I'm doing wrong here?
Note: I checked official documentation and I didn't find any solution...
pub fn update_todo(req_id: i32, update_payload: TodoUpdate) -> Result<usize, Error>
{
let connection = establish_connection();
let title_payload = match update_payload.title {
Some(title_payload)=> title_payload,
None => "".to_string()
};
let status_payload = match update_payload.status {
Some(status_payload)=> status_payload,
None => "".to_string()
};
let mut query = update(todos)
.set(id.eq(req_id)).into_boxed();
if title_payload.len() > 5 {
query = query.filter(title.eq(title_payload));
}
if status_payload.len() > 3 {
query = query.filter(status.eq(status_payload));
}
query.execute(&connection)
}
Note2: It works fine when I don't use into_boxed() and removing if statements. but I want to work if only title length is greater than 5 and status length greater than 3. It's why I used into_boxed method.
I found the solution. I was doing the whole thing wrong and the right concept is to use AsChangeset in order to update rows in database;
For any one reading this:
The right approach is to use an Option in your structs and derive the AsChangeset alongside table_name like below example:
In this example we have a todo row and we only want to change/update the title of our todo but not changing the status
#[derive(Serialize, Deserialize, AsChangeset)]
#[table_name="todos"]
pub struct TodoUpdate {
pub title: Option<String>,
pub status: Option<String>
}
Now we have to fix handler and add validations! I use match statement to check if there's a value or not and if there was a value inside title I check for it's length otherwise I just ignore it. for example:
match update_payload.title {
Some(ref title_req) => if title_req.len() < 3 {
return HttpResponse::BadRequest().json(json!({
"result": false,
"message": "Title should be at least 3 letter"
}));
},
None => (),
};
match update_payload.status {
Some(ref status_req) => if status_req.len() < 3 {
return HttpResponse::BadRequest().json(json!({
"result": false,
"message": "Status should be at least 3 letter"
}));
},
None => (),
};
After all I call the service I made for updating todos and it's very simple.
pub fn update_todo(req_id: i32, update_payload: TodoUpdate) -> Result<usize, Error>
{
let connection = establish_connection();
diesel::update(todos.filter(id.eq(req_id)))
.set::<TodoUpdate>(update_payload)
.execute(&connection)
}
whew!!! and these codes works fine.. I hope this was helpful for you all.
PS: if you really want to validate user request data you can use actix-web-validator
Related
Currently building a CRUD system and want to replace the selected item with the new updated item value. Since I am a noob, still need to learn lot of things, so how can I fix this. Completely confused on how to fix that.
What the current problem is that I am not able to find the item name for example bob and replace that with a new item value.
let action = std::env::args().nth(1).expect("Please provide an action");
let item = std::env::args().nth(2).expect("Please provide an item");
let _getitem = std::env::args().nth(3).expect("Please provide an item");
struct Todo {
map: HashMap<String, bool>,
}
if action == "edit" {
match todo.edit(&item, &_getitem) {
None => println!("'{}' is not present in the list", item),
Some(_) => match todo.save() {
Ok(_) => println!("todo saved"),
Err(why) => println!("An error occurred: {}", why),
},
}
}
fn edit(&mut self, key: &String, value: &String) -> Option<()> {
let elements = self.map.get_mut(key);
elements.push(value.to_string());
}
Data structure of hashmap looks like:
{"bob": true, "new": true }
I assume you want to update an existing record in a HashMap. One way to go about this is using HashMap::entry (Rust Doc):
Once you select an entry you can modify it using the Entry API. This allows you to chain updates and inserts, for example:
let mut map: HashMap<&'static str, usize> = HashMap::new();
map.insert("a", 1);
map
.entry("a")
.and_modify(|val| *val += 1);
In your case edit can look like this:
fn edit(&mut self, key: &String, value: bool) {
self.map.entry(key)
.and_modify(|val| *val = value);
}
Note that in your example the value of a HashMap must be bool but you are trying to update it to a string. You need to parse this first, e.g. using from_str (Rust Doc) or by using your own function:
fn to_bool(s: &str) -> Result<bool, ()> {
if s == "x" {
return Ok(true);
}
if s == "" {
return Ok(false);
}
Err(())
}
I am using the Serde crate to deserialise a JSON file, which has a nested structure like this:
struct Nested {
a: Vec<Foo>,
b: u8,
}
struct Foo {
c: Bar,
d: Vec<f32>,
}
Struct Bar {
e: u32,
f: String,
}
Part of the applications purpose is to check for missing parameters (or incorrect types in parameters), and then display a nicely printed list of errors found in the file, so I need to handle the structure missing parameters or wrongly typed.
I came across this great post that helped solved my issue, by wrapping each parameter in an enum result that contains the value if it passed, the value if it failed, or a final enum if it was missing (since the nested structures might also be missing I wrapped them in the same enum):
pub enum TryParse<T> {
Parsed(T),
Unparsed(Value),
NotPresent
}
struct Nested {
a: TryParse<Vec<Foo>>,
b: TryParse<u8>,
}
struct Foo {
c: TryParse<Bar>,
d: TryParse<Vec<f32>>,
}
Struct Bar {
e: TryParse<u32>,
f: TryParse<String>,
}
However, I'm not sure how to access them now without unpacking every step into a match statement. For example, I can access B very easily:
match file.b {
Parsed(val) => {println!("Got parameter of {}", val)},
Unparsed(val) => {println!("Invalid type: {:?}", val)}
NotPresent => {println!("b not found")},
};
However, I'm not sure how to access the nested ones (C D E and F). I can't use Unwrap or expect since this isn't technically a 'Result', so how do I unpack these?:
if file.a.c.e.Parsed() && file.a.c.e == 32 {... //invalid
if file.a.d && file.a.d.len() == 6... //invalid
I know in a way this flies against rust's 'handle every outcome' philosophy, and I want to handle them, but I want to know if there is a nicer way than 400 nested match statements (the above example is very simplified, the files I am using have up to 6 nested layers, each parameter in the top node has at least 3 layers, some are vectors as well)…
Perhaps I need to implement a function similar to unwrap() on my 'TryParse'? or would it be better to wrap each parameter in a 'Result', extend that with the deserialise trait, and then somehow store the error in the Err option that says if it was a type error or missing parameter?
EDIT
I tried adding the following, some of which works and some of which does not:
impl <T> TryParse<T> {
pub fn is_ok(self) -> bool { //works
match self {
Self::Parsed(_t) => true,
_ => false,
}
}
pub fn is_absent(self) -> bool { //works
match self {
Self::NotPresent => true,
_ => false,
}
}
pub fn is_invalid(self) -> bool { //works
match self {
Self::Unparsed(_) => true,
_ => false,
}
}
pub fn get(self) -> Result<T, dyn Error> { //doesnt work
match self {
Self::Parsed(t) => Ok(t),
Self::Unparsed(e) => Err(e),
Self::NotPresent => Err("Invalid")
}
}
}
I can't believe it is this hard just to get the result, should I just avoid nested enums or get rid of the TryParse enums/ functions all together and wrap everything in a result, so the user simply knows if it worked or didn't work (but no explanation why it failed)
Implementing unwrap() is one possibility. Using Result is another, with a custom error type. You can deserialize directly into result with #[serde(deserialize_with = "...")], or using a newtype wrapper.
However, a not-enough-used power of pattern matching is nested patterns. For example, instead of if file.a.c.e.Parsed() && file.a.c.e == 32 you can write:
if let TryParse::Parsed(a) = &file.a {
// Unfortunately we cannot combine this `if let` with the surrounding `if let`,
// because `Vec` doesn't support pattern matching (currently).
if let TryParsed::Parsed(
[Foo {
c:
TryParse::Parsed(Bar {
e: TryParse::Parsed(32),
..
}),
..
}, ..],
) = a.as_slice()
{
// ...
}
}
May not be the most Rust-y way of doing it, but for those like me moving from another language like C/Python/C++, this is the way I have done it that still allows me to quickly validate if I have an error and use the match syntax to handle it. Thanks to #Chayim Friedman for assisting with this, his way is probably better but this made the most sense for me:
#[derive(Debug)]
pub enum TryParse<T> {
Parsed(T),
Unparsed(Value),
NotPresent
}
impl<'de, T: DeserializeOwned> Deserialize<'de> for TryParse<T> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
match Option::<Value>::deserialize(deserializer)? {
None => Ok(TryParse::NotPresent),
Some(value) => match T::deserialize(&value) {
Ok(t) => Ok(TryParse::Parsed(t)),
Err(_) => Ok(TryParse::Unparsed(value)),
},
}
}
}
impl <T> TryParse<T> {
//pub fn is_ok(self) -> bool { ---> Use get().is_ok(), built into result
// match self {
// Self::Parsed(_t) => true,
// _ => false,
// }
//}
pub fn is_absent(self) -> bool {
match self {
Self::NotPresent => true,
_ => false,
}
}
pub fn is_invalid(self) -> bool {
match self {
Self::Unparsed(_) => true,
_ => false,
}
}
pub fn get(&self) -> Result<&T, String> {
match self {
Self::Parsed(t) => Ok(t),
Self::Unparsed(v) => Err(format!("Unable to Parse {:?}", v)),
Self::NotPresent => Err("Parameter not Present".to_string())
}
}
// pub fn get_direct(&self) -> &T {
// match self {
// Self::Parsed(t) => t,
// _ => panic!("Can't get this value!"),
// }
// }
}
match &nested.a.get().unwrap()[1].c.get.expect("Missing C Parameter").e{
Parsed(val) => {println!("Got value of E: {}", val)},
Unparsed(val) => {println!("Invalid Type: {:?}", val)}
NotPresent => {println!("Param E Not Found")},
};
//Note the use of '&' at the beginning because we need to borrow a reference to it
I know I need to change my mindset to use the rust way of thinking, and I am completely open to other suggestions if they can demonstrate some working code.
tl;dr Is it possible to extend std::result::Result to add my own variant that signals "things are Okay but also..." and keep impl Result methods like is_ok()?
I want to extend Result to signal additional states that a function caller can use for special cases.
use std::result::Result
use std::io::Error;
/// Extend Result to also signal "things are okay but check on things"
enum ResultExt<T, E> {
Result<T, E>,
OkButCheckThings(T),
}
pub fn do_stuff() -> ResultExt<u64, Error> {
// ...
}
pub fn main() -> {
let var = match do_stuff() {
Ok(val) => { val },
Err(err) => { 0 },
OkButCheckThings(val) => { check_things(); val },
}
dbg!(var);
}
It's possible to plainly extend an Enum. But I would also like to use the underlying Result<T, E> functions like is_ok.
let var2 = do_stuff();
if var2.is_ok() {
println!("It is totally Ok, nothing to check!");
}
I created a rust playground example that successfully extends Result<T, E> but the extended enum cannot use functions like is_ok().
The real-world use-case is a function that calls std::io::Read may need to "modify" the returned Result to signal additional states beyond Ok and Err. But I want these various "meta states" to be captured by one enum, as opposed to returning various other bool flags (I want to avoid return signature with (Result<T>, bool, bool). This would allow one clean match statement of all possible states; Ok, Err, "Okay but...", "Err but ...", etc..
There is no current way of "extending" and enum perse.
But it could be simply solved by embedding your own enum type into the result itself.
Simple example, similar to yours:
use std::fmt::Display;
enum StuffToCheck<T> {
Ok(T),
CheckThis(T),
}
impl<T> StuffToCheck<T>
where
T: Display + Copy,
{
pub fn check_things(&self) -> T {
match self {
Self::Ok(val) => {
*val
}
Self::CheckThis(val) => {
println!("Checking stuff for {}", val);
*val
}
}
}
}
fn do_stuff() -> ResultExt<u64> {
Ok(StuffToCheck::CheckThis(10))
}
type ResultExt<T> = Result<StuffToCheck<T>, std::io::Error>;
fn main() {
let var = match do_stuff() {
Ok(result) => result.check_things(),
Err(_err) => 0,
};
dbg!(var);
}
Playground
You could even use nested pattern matching:
...
match do_stuff() {
Err(e) => {//handle error}
Ok(StuffToCheck::Ok(value)) => { value },
Ok(StuffToCheck::CheckThis(value)) => {
check_things(value);
value
}
}
...
I think this is an instance of the X-Y problem. You can use the built-in result, you just need a different error type, that returns an option: Some(partial_result) or None.
For example you have function parse, that can attempt to adjust for a malformed input, but report the error.
pub fn parse(b: &str) -> Result<&str, CustomParseError> {
// Do something that might fail,
if failed(){
return CustomParseError::new(None)
} else if partially_failed() {
return CustomParseError::new(Some(partial_result))
} else {
return completeResult
}
}
This way you have a clean code path where nothing failed, and all of your assumptions are correct, and if it's not => instead of unwrapping, you match and check which case you have. This is vastly superior, because the error often contains enough information for you to reconstruct both what went wrong, and what could be done to fix it.
I'm trying to implement an linked list for learning purposes and a feature I'm implementing now is fn pop_back which is to pop data in the last location in my linked list instance. RefCell, Rc and Weak are mainly used to store data into the list.
Here is my code (fn pop_back is at the bottom of the code) :
use std::cell::RefCell;
use std::rc::{Rc, Weak};
#[derive(Debug)]
pub struct DbNode<T> {
data: T,
next: Option<Rc<RefCell<DbNode<T>>>>,
prev: Option<Weak<RefCell<DbNode<T>>>>,
}
#[derive(Debug)]
pub struct DbList<T> {
first: Option<Rc<RefCell<DbNode<T>>>>,
last: Option<Weak<RefCell<DbNode<T>>>>,
}
impl<T> DbList<T> {
pub fn new() -> Self {
DbList {
first: None,
last: None,
}
}
pub fn push_front(&mut self, data: T) {
match self.first.take() {
Some(e) => {
let new_front = Rc::new(RefCell::new(DbNode {
data,
next: Some(e.clone()),
prev: None,
}));
let mut me = e.borrow_mut();
me.prev = Some(Rc::downgrade(&new_front));
self.first = Some(new_front);
},
None => {
let new_data = Rc::new(RefCell::new(DbNode {
data,
next: None,
prev: None,
}));
self.last = Some(Rc::downgrade(&new_data));
self.first = Some(new_data);
},
}
}
pub fn push_back(&mut self, data: T) {
match self.last.take() {
Some(l) => {
let new_back = Rc::new(RefCell::new(DbNode {
data,
next: None,
prev: Some(l.clone()),
}));
let st = Weak::upgrade(&l).unwrap();
let mut ml = st.borrow_mut();
self.last = Some(Rc::downgrade(&new_back));
ml.next = Some(new_back);
},
None => {
let new_data = Rc::new(RefCell::new(DbNode {
data,
next: None,
prev: None,
}));
self.last = Some(Rc::downgrade(&new_data));
self.first = Some(new_data);
},
}
}
pub fn pop_front(&mut self) -> Option<T> {
match self.first.take() {
Some(first) => {
match Rc::try_unwrap(first) {
Ok(refc) => {
let inner = refc.into_inner();
self.first = inner.next;
if let None = self.first {
self.last = None;
};
Some(inner.data)
},
Err(_) => None,
}
},
None => None,
}
}
pub fn pop_back(&mut self) -> Option<T> {
match self.last.take() {
Some(last) => {
// todo: try_unwrap goes to err: the 'prev' in the 'last' holding the reference of this?
match Rc::try_unwrap(Weak::upgrade(&last).unwrap()) {
Ok(refc) => {
let inner = refc.into_inner();
self.last = inner.prev;
Some(inner.data)
},
Err(_) => None,
}
},
None => None,
}
}
}
the fn pop_back should return the last DbNode if possible, and set the 'next' DbNode in the previous DbNode of the existing 'last' to the 'new last'. So I need to unwrap the existing to obtain the previous DbNode, which is going to be the new last. But Rc::try_unwrap goes to Err. I guess this is because the existing last itself is an Weak, so it already has one strong reference and the reference count increases with Rc::try_unwrap(Weak::upgrade(&last).unwrap()). I'm not 100% sure of my guess.
What should I do for it?
Completed
I've done this based on the approach suggested by #Masklinn. In addition to the approach, before Rc::try_unwrap, I just have to drop an Rc held by the 'first' field in DbList when the list has only one DbNode left, since the 'prev' field has None when only one DbNode is left in the list. It meets the same error I faced first, without dropping the 'first'.
Here is the final code on fn pop_back written:
pub fn pop_back(&mut self) -> Option<T> {
match self.last.take() {
Some(last) => {
let last = Weak::upgrade(&last).unwrap();
if Rc::ptr_eq(self.first.as_ref().unwrap(), &last) {
self.first = None;
} else {
let prev = Weak::upgrade(last.borrow().prev.as_ref().unwrap());
prev.as_ref().unwrap().borrow_mut().next = None;
self.last = Some(Rc::downgrade(prev.as_ref().unwrap()));
}
match Rc::try_unwrap(last) {
Ok(iv) => Some(iv.into_inner().data),
Err(_) => None,
}
},
None => None,
}
}
I guess this is because the existing last itself is an Weak, so it already has one strong reference and the reference count increases
This scheme of using weak references is really weird (that's not really what they're for), but here what you need to do is:
take from last()
upgrade last(), creating the second Rc
follow its prev() link to the second-to-last
set that as the new last
take from second-to-last's next, that's the first / existing Rc
drop either the upgraded value or the one you got from second-to-last, they're both strong references to the former last, this will leave you with a refcount of 1
which means you can unwrap it
You can't unwrap the Rc before the last step, because it will always have two strong refs before that.
Something along the lines of this:
pub fn pop_back(&mut self) -> Option<T> {
self.last.take().and_then(|last| {
// get a strong reference of last
let last = Weak::upgrade(&last).expect("Last element of the list was already deallocated.");
// get a strong reference of second-to-last
let prev = last.borrow().prev.as_ref().and_then(Weak::upgrade).expect("Previous-to-last element of the list was already deallocated");
// remove the old last from the new last
prev.borrow_mut().next = None;
// set second to last as the new last
self.last = Some(Rc::downgrade(&prev));
// extract the old last's payload and return it
Rc::try_unwrap(last).ok().map(|v| v.into_inner().data)
})
}
I swapped setting the new last and updating its next because that way all the things which must succeed (should only panic if the data structure is in an incoherent state) will run before we perform the first new mutation. Then we do all the mutation using in ways which should not be failable, so we should have no "panic hole".
I also just set its next to None directly, since we already have a strong reference on last we just care that the old one gets destroyed.
This question already has answers here:
How to convert a String into a &'static str
(4 answers)
Closed 7 years ago.
I'm trying to read input from the user, and then use it as the URL for the POP3 library. When converting the String that I get to a string slice, it doesn't live long enough to be used. This is strange to me for two reasons:
Because everything that uses the POP3 object is inside the same block, so the lifetime of the str slice should be that of the entire block, which would cover everything
I've tried almost every different code configuration I could think of, and to no avail, I get the same error every time.
extern crate pop3;
extern crate smtp;
extern crate openssl;
extern crate libc;
use openssl::ssl::{SslContext, SslMethod};
use pop3::POP3Stream;
use pop3::POP3Result::{POP3Stat, POP3List, POP3Message};
mod readline;
use readline::*;
fn main() {
let place = match readline("URL: ") { // Problem line
Some(input) => { // Problem line
let place: &'static str = &input[..]; // Problem line
let mut email_socket = match POP3Stream::connect(place, 995, Some(SslContext::new(SslMethod::Sslv23).unwrap())) { // Problem line
Ok(s) => s,
Err(e) => panic!("{}", e)
};
match readline("Username: ") {
Some(username) => {
match readline("Password: ") {
Some(password) => { email_socket.login(&*username, &*password); },
None => println!("Please enter a password.")
}
},
None => println!("Please enter a username.")
};
let stat = email_socket.stat();
match stat {
POP3Stat {num_email,
mailbox_size} => println!("num_email: {}, mailbox_size:{}", num_email, mailbox_size),
e => println!("There was an error signing into your server."),
}
let list_all = email_socket.list(None);
match list_all {
POP3List {emails_metadata} => {
for i in emails_metadata.iter() {
println!("message_id: {}, message_size: {}", i.message_id, i.message_size);
}
},
_ => println!("There was an error listing your messages."),
}
let message_25 = email_socket.retr(25);
match message_25 {
POP3Message{raw} => {
for i in raw.iter() {
println!("{}", i);
}
},
_ => println!("There was an error getting your 25th message."),
}
email_socket.quit();
},
None => { println!("Please enter a URL for your server."); }
};
}
The Problem
Your problem boils down to the use of static since the keyword basically says "keep this object around forever". This means that the lifetime of place, without a doubt, will live long after input — forever vs the scope of the block.
fn get() -> Option<String> {
Some("hello world".to_owned())
}
fn main() {
let data = match get() {
Some(input) => { let place : &'static str = &input[..]; },
None => { }
};
}
In the above we try to make place a static reference to a str, other other words; a reference that exists for the entire duration of our program. input on the other hand will definitely not exist for this amount of time, and therefor we get an error diagnostic.
<anon>:7:54: 7:59 error: `input` does not live long enough
<anon>:7 Some(input) => { let place : &'static str = &input[..]; },
The Solution
Remove the use of static, effectively saying that the lifetime of place is that of the block (which is a subset of the lifetime associated with input).
fn get() -> Option<String> {
Some("hello world".to_owned())
}
fn main() {
let data = match get() {
Some(input) => { let place : &str = &input[..]; },
None => { }
};
}
Further Digging
As it turns out, POP3Stream::connect accepts a &'static str as its first argument; this is really bad design since it will only accept string-literals.
impl Pop3Stream {
pub fn connect(host: &'static str, ...) -> Result<POP3Stream> {
...
}
}
https://github.com/mattnenterprise/rust-pop3/blob/master/src/pop3.rs
You can, however, hack your way around the issue by intentionally leaking the resource—effectively making it live "forever". Please note the usage of unsafe, and keep in mind that this is—by language design—considered to be just that.
fn get () -> Option<String> {
Some("hello world".to_owned ())
}
fn connect (host : &'static str) {
/* ... */
}
fn main() {
let data = match get() {
Some(input) => {
let place : &'static str = unsafe {
use std::mem; let x = mem::transmute(&input as &str);
mem::forget (x); x
};
connect(place);
},
None => { }
};
}