En el código aquí, he creado un nuevo Cliente llamado "mcycleowner" y lo asigné a una dirección de entrada. Sin embargo, también quiero asignarlo a la entrada _license para que se pueda consultar la información del cliente con una dirección Eth o un número de matrícula.
Para hacerlo, creé un nuevo Cliente "mcyclelicenses", y la función addLicense toma las mismas entradas que newMcycleOwner (excepto la dirección), solo que este Cliente está asignado a _license. Esta función se activa dentro de la función "newMcycleOwner" para que tanto los clientes como las asignaciones se creen simultáneamente.
Sin embargo, hacerlo de esta manera significa tener dos registros de la información de cada cliente, lo que parece una pérdida de espacio, y también cada vez que se necesite cambiar la información del cliente, se tendrá que cambiar en dos lugares. ¿Hay una mejor manera de hacer esto?
// < ---------------------- MOTORCYLCES ---------------------- >
mapping (address => Customer) mcycleowners;
address[] public mcycleownerAdds;
function newMcycleOwner(address _address, string _custname, string _color, string _make, uint32 _year, string _license) onlyMember public {
Customer storage mcycleowner = mcycleowners[_address];
mcycleowner.custname = _custname;
mcycleowner.color = _color;
mcycleowner.make = _make;
mcycleowner.year = _year;
mcycleowner.license = _license;
mcycleownerAdds.push(_address);
addLicense(_custname, _color, _make, _year, _license);
}
function getMcycleAdds() public view returns(address[]) {
return mcycleownerAdds;
}
function getMcycleByAdd(address _address) public view returns(string, string) {
return (mcycleowners[_address].custname, mcycleowners[_address].license);
}
function countMcycle() public view returns(uint) {
return mcycleownerAdds.length;
}
// <---------- CREATION OF NEW MAP SO WE CAN QUERY BY LICENSE ---------->
//This seems to create two instances of each customer. Replace with a better method.
mapping (string => Customer) mcyclelicenses;
function addLicense(string _custname, string _color, string _make, uint32 _year, string _license) onlyMember public {
Customer storage mcyclelicense = mcyclelicenses[_license];
mcyclelicense.custname = _custname;
mcyclelicense.color = _color;
mcyclelicense.make = _make;
mcyclelicense.year = _year;
}
function getMcycleByLic(string _license) public view returns(string, string, string, uint32) {
return (mcyclelicenses[_license].custname, mcyclelicenses[_license].color, mcyclelicenses[_license].make, mcyclelicenses[_license].year);
}
Una manera fácil de hacerlo podría ser guardar la información de los clientes dentro de una matriz y usar la asignación para almacenar los índices de la matriz, de modo que acceda directamente al índice a través de la asignación y use este índice para acceder directamente a la matriz.
Aquí un ejemplo
pragma solidity ^0.4.23;
contract ContractX {
struct Customer {
string name;
string license;
/* other infos */
}
mapping (address => uint) addressIndexes;
mapping (string => uint) licenseIndexes;
Customer[] customers;
uint customerCount;
function addNewItem(address _address, string _name, string _license) public {
customers.push(Customer(_name, _license));
addressIndexes[_address] = customerCount;
licenseIndexes[_license] = customerCount;
customerCount++;
}
function getByAddress(address _address) public view returns(string, string) {
return (
customers[addressIndexes[_address]].name,
customers[addressIndexes[_address]].license
);
}
function getByLicense(string _license) public view returns(string, string) {
return (
customers[licenseIndexes[_license]].name,
customers[licenseIndexes[_license]].license
);
}
}
Por lo tanto, la información del cliente se ha guardado solo una vez y solo realiza un seguimiento del índice de matriz en el mapeo para que pueda usarlo más tarde para acceder directamente al cliente que necesita.
Otra solución podría ser usar el Customer
como un subcontrato, luego crear el contrato cuando agregue la información de su cliente y almacenar la dirección de este nuevo contrato en sus asignaciones. Pero eso abre otro escenario, y es posible que deba realizar varios cambios.
Simplemente puede asignar la licencia a una dirección y luego hacer dos búsquedas para eliminar la referencia de una licencia.
mapping(string => address) mcyclelicences;
function getMcycleByLic(string _license) public view returns(string, string, string, uint32) {
return (
mcycleowners[mcyclelicenses[_license]].custname,
mcycleowners[mcyclelicenses[_license]].color,
mcycleowners[mcyclelicenses[_license]].make,
mcycleowners[mcyclelicenses[_license]].year
);
}
CreadoAMadman