使用 near-sdk-rs 访问向量状态并更新它
Access the vector state and updating it using near-sdk-rs
我正在尝试更新矢量,这是我目前的代码。
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的product vector重复存储?如何获取矢量状态并更新它?
完整代码here
在 Rust 中,match
的结果通常是不可变的。所以在你的例子中:
Some(mut my_products) => {
虽然有 mut
,但这并不意味着它正在改变(改变)最终与 self
关联的值。
所以您使用 self…insert
的方法是正确的。这通常是 Rust 中的常见方法。 Rust 中的这条规则有例外情况,可能会突出显示正在发生的事情。
例如,在标准集合 HashMap
中有 get_mut
(与 get
相对),其中 returns 是一个可变引用。可以看到in the Rust docs that this returns Option<&mut V>
while the HashMap's get methodreturnsOption<&V>
.
现在我们可以查看 docs for the NEAR Vector get
方法,看看 get
returns Option<T>
是不可变的。
再一次,我觉得你的方法不错。
在修改 Vector 方面,我相信您可能会想改用 the Set collection,但我不喜欢 Whosebug 问题那样改变主题。因此,下面我提供了一个测试,您可以添加它来演示我相信您正在寻找的一些 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, ¤t_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);
}
我正在尝试更新矢量,这是我目前的代码。
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的product vector重复存储?如何获取矢量状态并更新它?
完整代码here
在 Rust 中,match
的结果通常是不可变的。所以在你的例子中:
Some(mut my_products) => {
虽然有 mut
,但这并不意味着它正在改变(改变)最终与 self
关联的值。
所以您使用 self…insert
的方法是正确的。这通常是 Rust 中的常见方法。 Rust 中的这条规则有例外情况,可能会突出显示正在发生的事情。
例如,在标准集合 HashMap
中有 get_mut
(与 get
相对),其中 returns 是一个可变引用。可以看到in the Rust docs that this returns Option<&mut V>
while the HashMap's get methodreturnsOption<&V>
.
现在我们可以查看 docs for the NEAR Vector get
方法,看看 get
returns Option<T>
是不可变的。
再一次,我觉得你的方法不错。
在修改 Vector 方面,我相信您可能会想改用 the Set collection,但我不喜欢 Whosebug 问题那样改变主题。因此,下面我提供了一个测试,您可以添加它来演示我相信您正在寻找的一些 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, ¤t_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);
}