4

I need to access books array of Student contract in ClassRoom contract.

If i write as function readStudentStruct (uint ID) constant returns (address, uint, bool,address[]) then error

Different number of arguments in return statement than in returns declaration.
        return student.StudentNames(ID);

or if written without address[] then works fine.

pragma solidity ^0.4.0;
contract Student{

    struct stu{
        address name;
        uint age;
        bool tookTest;
        address[] books;
    }

    stu public s;

    mapping(uint => stu) public StudentNames;

    function addStudent (uint ID, address _name, uint _age,address[] books) {
        StudentNames[ID] = stu(_name, _age, false, books);
    }
    function updateStudent (uint ID) {
        StudentNames[ID].tookTest = true;
    }

    function getBooks(uint ID) returns(address[]){
        return StudentNames[ID].books;
    }

}
contract ClassRoom {
    address studentAddr;

    Student student;

    function ClassRoom(address addr) {
        studentAddr = addr;
        student = Student(addr);
    }
    function updateTookTest (uint ID) {
        student.updateStudent(ID);
    }

    //working fine
    function readStudentStruct (uint ID) constant returns (address, uint, bool) {
        return student.StudentNames(ID);
    }

   //showing error
   function readStudentStruct (uint ID) constant returns (address, uint, bool,address[]) {
        return student.StudentNames(ID);
    }
}

as per struct with address array function should worked but didn't.

why books array not coming in parent contract? or any way to get books array in parent contract?

1 Answer 1

2

Main issue is we can't pass a dynamic array[] in/out of the function. We have to break it down into a fixed-sized interface.

Here's a sketch following a simple pattern with 4 entities tracked and some relationships.

  1. Class
  2. Student
  3. Books
  4. and a many-to-many for class-students

The pattern isn't complicated but working with 4 entities at a time and the joins makes for a tough introduction.

Have a look here for more illustrative code: Are there well-solved and simple storage patterns for Solidity?

You'll probably want to support a logical delete so a student can return their books. I've skipped it because it calls for a trickier pattern.

No testing. No warranty. Hopefully provides some ideas.

pragma solidity ^0.4.0;

contract School {

    struct ClassStruct {
        bytes32 title;
        bytes32 teacher;
        mapping(address => ClassStudentStruct) classStudentStructs;
        address[] studentList;
        bool isClass;
    }

    mapping(bytes32 => ClassStruct) public classStructs; // access by Id
    bytes32[] public classList; // enumerate the keys to the mapping

    struct StudentStruct {
        bytes32 name;
        bytes32[] bookList; // student has books
        mapping(bytes32 => bool) isStudentBook;
        bool isStudent;
    }

    mapping(address => StudentStruct) public studentStructs;
    address[] public studentList;

    struct BookStruct {
        bytes32 title;
        bytes32 author;
        bool isBook;
    }

    mapping(bytes32 => BookStruct) public bookStructs;
    bytes32[] public bookList;

    // many-to-many

    struct ClassStudentStruct {
        address student;
        bool tookTest;
        bool isClassStudent;
    }

    function getClassCount()   public constant returns(uint count) { return classList.length; }
    function getStudentCount() public constant returns(uint count) { return studentList.length; }
    function getBookCount()    public constant returns(uint count) { return bookList.length; }

    function newClass(bytes32 classId, bytes32 title, bytes32 teacher) returns(bool success) {
        if(classStructs[classId].isClass) throw; // duplicate key
        classStructs[classId].title = title;
        classStructs[classId].teacher = teacher;
        classStructs[classId].isClass = true;
        classList.push(classId);
        return true;
    }

    function newStudent(address studentAddress, bytes32 name) returns(bool success) {
        if(studentStructs[studentAddress].isStudent) throw;
        studentStructs[studentAddress].name = name;
        studentList.push(studentAddress);
        studentStructs[studentAddress].isStudent = true;
        studentList.push(studentAddress);
        return true;
    }

    function newBook(bytes32 bookId, bytes32 title, bytes32 author) returns(bool success) {
        if(bookStructs[bookId].isBook) throw;
        bookStructs[bookId].title = title;
        bookStructs[bookId].author = author;
        bookStructs[bookId].isBook = true;
        bookList.push(bookId);
        return true;
    }

    function addClassStuduent(bytes32 classId, address studentAddress) returns(bool success) {
        if(!studentStructs[studentAddress].isStudent) throw; // not a student
        if(!classStructs[classId].isClass) throw; // not a class
        if(classStructs[classId].classStudentStructs[studentAddress].isClassStudent) throw; // student already enrolled in this class

        ClassStudentStruct memory newStudent;
        newStudent.student = studentAddress;
        newStudent.isClassStudent = true;
        classStructs[classId].studentList.push(studentAddress);
        return true;
    }

    function addStudentBook(bytes32 bookId, address studentAddress) returns(bool success) {
        if(!bookStructs[bookId].isBook) throw;
        if(!studentStructs[studentAddress].isStudent) throw;
        if(studentStructs[studentAddress].isStudentBook[bookId]) throw;

        studentStructs[studentAddress].isStudentBook[bookId] = true;
        studentStructs[studentAddress].bookList.push(bookId);
        return true;
    }


    // logical deletes need a more intricate pattern - Last one here:
    // https://ethereum.stackexchange.com/questions/13167/are-there-well-solved-and-simple-storage-patterns-for-solidity 

    function delStudentBook(bytes32 bookId, address studentAddress) returns(bool success) {}
    function delClassStudent(bytes32 classId, address studentAddress) returns(bool success) {}

}

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.