'Altering Lookup Value inplace
I am currently struggling to find a way to mutate a value of a LookupMap inplace. Here is a small example that shows what I am trying to achieve.
// Aux structure
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Record {
pub i: usize,
}
impl Record {
pub fn inc(&mut self) {
self.i += 1;
}
}
// Main Contract
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Welcome {
pub records: LookupMap<String, Record>,
}
impl Default for Welcome {
fn default() -> Self {
Self {
records: LookupMap::new(b"a".to_vec()),
}
}
}
#[near_bindgen]
impl Welcome {
pub fn add_element(&mut self, key: &str) {
self.records.insert(&key.to_string(), &Record{i: 0});
}
pub fn inc_element(&mut self, key: &str) {
self.records.get(&key.to_string()).unwrap().inc();
}
}
When I run the following test, it fails:
#[test]
fn test_inc() {
// This is the function from the examples.
let context = get_context(vec![], false);
testing_env!(context);
let mut contract = Welcome::default();
let key1 = "k";
contract.add_element(key1);
// This test passes
assert_eq!(contract.records.get(&key1.to_string()).unwrap().i, 0);
// This should increment the value of the record in place
contract.records.get(&key1.to_string()).unwrap().inc();
// This test FAILS!
assert_eq!(contract.records.get(&key1.to_string()).unwrap().i, 1);
}
I am struggling to understand how can I get a mutable reference, in order to change the Record that is stored as a value on the LookupMap in place. With an Hashmap, I can use the get_mut(key) method, but here it does not seem to be the case.
Not sure if I missed anything on the docs, as I have been looking into then for a while. Thank you!
Solution 1:[1]
There might be a better way to do this but the following change makes the test pass, replace:
contract.records.get(&key1.to_string()).unwrap().inc();
with:
let mut record = contract.records.get(&key1.to_string()).unwrap_or_else(|| env::panic(b"Record not found."));
record.inc();
contract.records.insert(&key1.to_string(), &record);
I believe that because LookupMap stores its data on the NEAR blockchain you have go through the insert method to ensure that the data is persisted.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Joaquim Ley |
