0

我正在尝试更新向量,这是我的代码。

use near_sdk::collections::Map;
use near_sdk::collections::Vector;
#[near_bindgen]
#[derive(Default, BorshDeserialize, BorshSerialize)]
pub struct ProfileDetails {
    profile_tags: Map<String, ProductList>,
}

#[near_bindgen]
#[derive(Default, BorshDeserialize, BorshSerialize, Debug)]
pub struct Product {
    product_name: String,
    product_details: String,
}

#[near_bindgen]
#[derive(Default, BorshDeserialize, BorshSerialize)]
pub struct ProductList {
    products: Vector<Product>,
}

#[near_bindgen]
impl ProfileDetails {
    pub fn set_profile(&mut self, product_name: String, product_details: String) {
        let account_id = String::from("amiyatulu.test");
        println!("{}", product_name);
        let p = Product {
            product_name,
            product_details,
        };
        let id = account_id.clone().into_bytes();
        let mut id_products = ProductList {
            products: Vector::new(id),
        };
        id_products.products.push(&p);
        self.profile_tags.insert(&account_id, &id_products);
    }

    pub fn push_product_to_profile(&mut self, product_name: String, product_details: String) {
        let account_id = String::from("amiyatulu.test");
        let p = Product {
            product_name,
            product_details,
        };
        let my_products_option = self.profile_tags.get(&account_id);
        match my_products_option {
            Some(mut my_products) => {
                my_products.products.push(&p); //It doesn't update the state
                self.profile_tags.insert(&account_id, &my_products);
                println!("Hello myproducts push");
            }
            None => println!("Can't get the profile tag"),
        }
    }

问题是这个语句不会更新区块链的状态。

my_products.products.push(&p); //It doesn't update the state

因此,我在此语句中再次插入了向量。

self.profile_tags.insert(&account_id, &my_products);

这是正确的方法吗?会不会导致 ProductList 的积向量重复存储?如何获取向量状态并更新它?

完整代码在这里

4

1 回答 1

1

在 Rust 中,结果match通常是不可变的。所以在你的例子中:

Some(mut my_products) => {

尽管拥有mut, 并不意味着它正在改变(改变)最终与self.

所以你的方法self…insert是正确的。这通常是 Rust 中的一种常见方法。Rust 中的这条规则有一些例外,可能会突出正在发生的事情。

例如,在标准集合HashMap中有get_mut(而不是get)返回一个可变引用。您可以在 Rust 文档中看到 this 返回Option<&mut V>,而HashMap 的 get 方法返回Option<&V>

现在我们可以查看NEAR Vector get方法的文档,看看get返回Option<T>的是不可变的。

再说一次,你的方法对我来说看起来不错。

在修改 Vector 方面,我相信您可能会想要使用Set 集合,但是当 StackOverflow 问题像这样改变主题时,我不喜欢它。所以下面我提供了一个测试,你可以添加它来演示我相信你正在寻找的一些 Vector 用法。

    #[test]
    pub fn modify_update_product_list() {
        let context = get_context(vec![], false);
        testing_env!(context);

        // first product
        let product_one = Product {
            product_name: "toothbrush".to_string(),
            product_details: "electric and sleek".to_string(),
        };
        let product_two = Product {
            product_name: "soap".to_string(),
            product_details: "smells like teen spirit".to_string(),
        };
        let product_three = Product {
            product_name: "shampoo".to_string(),
            product_details: "natural mint oils".to_string(),
        };

        let mut profile_detail = ProfileDetails::default();

        let mut product_list = ProductList {
            products: Vector::new(b"products".to_vec()),
        };
        println!("Corner Store: adding toothbrush and soap…");
        product_list.products.push(&product_one);
        product_list.products.push(&product_two);

        let shop_name = "Corner Store".to_string();
        profile_detail.profile_tags.insert(&shop_name, &product_list);

        // Say we come back later to the saved state
        // Get the product list from Corner Store
        match profile_detail.profile_tags.get(&shop_name) {
            Some(mut current_product_list) => {
                // add shampoo product
                println!("Corner Store: Inserting shampoo…");
                current_product_list.products.push(&product_three);
                profile_detail.profile_tags.insert(&shop_name, &current_product_list);

            },
            None => {
                // if this were outside of tests we'd have:
                // env::log(b"Didn't find shop name");
                println!("Didn't find shop name")
            }
        }

        let product_list = profile_detail.profile_tags.get(&shop_name);
        assert!(product_list.is_some()); // can also have is_none()

        println!("Corner Store: Listing products");
        for product in product_list.unwrap().products.iter() {
            println!("Corner Store: Product {:?}", product);
        }

        // Sold out of soap, remove it
        println!("Corner Store: Removing index 1, which should be soap");
        // Consider using something like Set
        // https://docs.rs/near-sdk/0.10.0/near_sdk/collections/struct.Set.html
        let current_product_list = profile_detail.profile_tags.get(&shop_name);
        assert!(current_product_list.is_some(), "Couldn't find shop");

        // Remove and get object at index 1
        let soap = current_product_list.unwrap().products.swap_remove(1);
        println!("Corner Store: Removed index 1 which was {:?}", soap);
    }
于 2020-06-07T14:41:03.520 回答