DRUPAL: How to use Rules to create child nodes from parent and populate child fields from parent fields

Tags: 

I use the Drupal content management system as a companion to the Selenium automation tools so that I get robust reporting and data manipulation. I also use it to perform parameterized data driven test scripts. I decided to use Drupal and Selenium for an update/deployment mechanism for my testing framework ... so that if there were any updates to framework based files (including user-extensions) in our local machines c:\selenium directory, an Update node (form entry) could be created on the frameworks website. Once an Update node was created Drupals Rules module would create child nodes named "Update Status" that would capture the status of individual machines that would need to be updated. Then each of those child nodes could keep a separate status of whether or not the machine was actually updated. I can explain the actual update mechanism at a later date. This article focuses on how to get Rules to automatically create the "Update Status" nodes AFTER an "Update" node has been created, and automaticallt populate some of the field values from the "Update" node, into the multiple "Update Status" nodes. Notice, thats a one (Update) to many (Update Status) relationship.

Here are how the content types were built -

"Update" content type fields:

  • Title
  • Id (serial field)
  • Description (text area)
  • Machines (entity reference select list on taxonomy terms from Machine vocabulary, multi-select)

"Update Status" content type fields:

  • Title (auto generated with tokens)
  • Update (entity reference field back to the "Update" node that created it)
  • Id (serial field)
  • Status (text list, select list)
  • Machine (entity reference select list on taxonomy terms from Machine vocabulary, single-select)

Here is a screen shot of the Rules gui for the rule that auto-creates the "Update Status" nodes when an "Update" node is created:

Here is an export in code of the actual rule:

{ "rules_create_update_status_nodes" : {
    "LABEL" : "Create Update Status Nodes",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "ON" : { "node_insert--update" : { "bundle" : "update" } },
    "DO" : [
      { "entity_fetch" : {
          "USING" : { "type" : "node", "id" : [ "node:nid" ] },
          "PROVIDE" : { "entity_fetched" : { "entity_fetched" : "Fetched entity" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "node:field-update-machines" ] },
          "ITEM" : { "listofmachines" : "listofmachines" },
          "DO" : [
            { "entity_create" : {
                "USING" : {
                  "type" : "node",
                  "param_type" : "update_status",
                  "param_title" : "[node:field_update_id]-[listofmachines:name]",
                  "param_author" : [ "user" ]
                },
                "PROVIDE" : { "entity_created" : { "entity_created" : "Created entity" } }
              }
            },
            { "data_set" : {
                "data" : [ "entity-created:field-us-update" ],
                "value" : [ "entity-fetched" ]
              }
            },
            { "data_set" : {
                "data" : [ "entity-created:field-us-machine" ],
                "value" : [ "listofmachines" ]
              }
            },
            { "entity_save" : { "data" : [ "entity-created" ], "immediate" : "1" } }
          ]
        }
      }
    ]
  }
}

This should help me and others in the future to do similiar things. It wasn't easy trying to figure out how to make rules loop properly through a list of values, or populate the entity reference fields within a loop.