How to iterate over all field collection items in an eMail body using Rules? I'm trying to write a rule (using Rules) that will send an email to users of a role. Within the body of the email, I'd like to display the contents of a nested field collection.

I've tried using what Rules gives me for data selectors, but I can't seem to put it together. Specifically, I have two field collections: field-boat-lineup and field-equip-rowers.field-equip-rowersis actually nested withinfield-boat-lineup. The contents offield-boat-lineupare consistent. That is, their fields are fixed values except forfield-equip-rowers.field-equip-rowers` is variable and can consist of up to 8 user names.

Any pointers in the direction of how to display the contents of the field collections in the body of an email? Do I need to write some PHP code to make this happen? If so, what's the critical piece I'm missing?

On a side note, I find the field collection syntax used when working with the Rules data selector somewhat confusing. Specifically, the use of what appears to be an index. For example,

[node:field-boat-lineup:0:field-equip-boat-name:title]


I see the usage of a '0','1', '2', and '3' in the above token. I'm never quite sure what to select: 0, 1, 2, or, 3. Can anyone shed some light on the purpose of the numbers?

Update:

While I understand the example shown in the existing answer, I can't seem to conceptualize how I would be able to write a Rules "loop" to display the field collections in an email. The email body of the Rules module does not seem to have the ability to "loop" over content.
Part 1: Processing field collections in a rule

Consider a configuration with a field collection like so:


The machine name of the field collection is field_treatment_details, and the number of values for it is unlimited.
This field collection has 2 fields:


a text field labeled "Doelpubliek" (Dutch for "Target audience") with machine name field_doelpubliek.
a boolean field labeled "Betalend" (Dutch for "Payable") with machine name field_betalend.

Assume a node with "some number of" field collection items, with values that look like so (with some number = 2 in this case, but that could be any number as per the "unlimited" above):


Doelpubliek=Baby with Betalend=Nee
Doelpubliek=Moeder with Betalend=Ja



Let's assume you want to display these data via a Rule, using Rules Action "Set message", and using Rules Event "Content is viewed", so that such message looks like so:


This is a demo of a node containing a field collection ...

About this demo:

The machine name of the field collection is field_treatment_details, and the number of values for it is unlimited.
This field collection has 2 fields:

- a text field labeled Doelpubliek with machine name field_doelpubliek.
- a boolean field labeled Betalend with machine name field_betalend.

Part 1: The field collection with machine name 'field_treatment_details' looks like so:

Doelpubliek: Baby
Betalend:    Nee

Doelpubliek: Moeder
Betalend:    Ja

Part 2: The result of a Rules loop that iterates for each of the field collection items (using its unique ID) ...

The unique ID of the field collection item: 2
The host entity of this field collection item: 43
Field "field_doelpubliek": Baby
Field "field_betalend": Nee

The unique ID of the field collection item: 3
The host entity of this field collection item: 43
Field "field_doelpubliek": Moeder
Field "field_betalend": Ja



Here is the Rule (in Rules export format) that produced the above "message":

{ "rules_field_collection_demo" : {
    "LABEL" : "Field Collection Demo",
    "PLUGIN" : "reaction rule",
    "ACTIVE" : false,
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "ON" : { "node_view" : [] },
    "IF" : [
      { "entity_has_field" : { "entity" : [ "node" ], "field" : "field_treatment_details" } }
    ],
    "DO" : [
      { "drupal_message" : { "message" : "\u003Ch2\u003EThis is a demo of a node containing a field collection ... \u003C\/h2\u003E\r\n\u003Chr \/\u003E\r\n\u003Cstrong\u003EAbout this demo\u003C\/strong\u003E:\u003Cbr \/\u003E\r\n\u003Cbr \/\u003E\r\nThe machine name of the field collection is \u003Cstrong\u003Efield_treatment_details\u003C\/strong\u003E, and the number of values for it is unlimited.\u003Cbr \/\u003E\r\nThis field collection has 2 fields:\u003Cbr \/\u003E\u003Cbr \/\u003E\r\n- a text field labeled \u003Cstrong\u003EDoelpubliek\u003C\/strong\u003E with machine name \u003Cstrong\u003Efield_doelpubliek\u003C\/strong\u003E.\u003Cbr \/\u003E\r\n- a boolean field labeled \u003Cstrong\u003EBetalend\u003C\/strong\u003E with machine name \u003Cstrong\u003Efield_betalend\u003C\/strong\u003E.\u003Cbr \/\u003E\u003Cbr \/\u003E\r\n\u003Chr \/\u003E\r\n\u003Cstrong\u003EPart 1\u003C\/strong\u003E: The field collection with machine name \u003Cstrong\u003E\u0027field_treatment_details\u0027\u003C\/strong\u003E looks like so:\r\n\u003Chr \/\u003E\r\n[node:field_treatment_details]\r\n \u003Chr \/\u003E\r\n\u003Cstrong\u003EPart 2\u003C\/strong\u003E: The result of a \u003Cstrong\u003ERules loop\u003C\/strong\u003E that iterates for each of the field collection items (using its unique ID) ...\r\n\u003Chr \/\u003E" } },
      { "LOOP" : {
          "USING" : { "list" : [ "node:field-treatment-details" ] },
          "ITEM" : { "treatment_details_item" : "Treatment details item" },
          "DO" : [
            { "drupal_message" : { "message" : "The unique ID of the field collection item: [treatment-details-item:item-id]\u003Cbr \/\u003E\r\nThe host entity of this field collection item: [treatment-details-item:host]\u003Cbr \/\u003E\r\nField \u0022field_doelpubliek\u0022: [treatment-details-item:field-doelpubliek]\u003Cbr \/\u003E\r\nField \u0022field_betalend\u0022: [treatment-details-item:field-betalend]\u003Cbr \/\u003E\r\n\u003Chr \/\u003E" } }
          ]
        }
      }
    ]
  }
}


Admitted, this is a slightly simplified field collection configuration (no "nesting" involved). But apart from that it is similar to what you will need to specify in your Rules logic. Here are some more details to explain the above rule:


You need (repeat: need) a Rules Condition "Entity has field" (prior to being able to use it anywhere later on in your rule), which refers to your field collection field.
The 1st Rules Action (which produces the data below "Part 1" in the message) just displays the entire field collection, simply by referring to token [node:field_treatment_details].
The 2nd Rules Action (which produces the data below "Part 2" in the message) is simply a Rules "loop", which iterates over each of the field collection items (it uses a variable that I named treatment_details_item to actually display a message for each item). You will then be able to use any of the typical tokens (in the replacement patterns) related to that variable, such as how I used them to create my message I wanted to display, i.e.:


The unique ID of the field collection item: [treatment-details-item:item-id]&lt;br /&gt;
The host entity of this field collection item: [treatment-details-item:host]&lt;br /&gt;
Field "field_doelpubliek": [treatment-details-item:field-doelpubliek]&lt;br /&gt;
Field "field_betalend": [treatment-details-item:field-betalend]&lt;br /&gt;



Notice how, in the message I wanted my rule to display, I was able to refer to my "Doelpubliek" and "Betalend" fields (part of my field collection).


Part 2: Performing a loop within

After posting Part 1 of my answer, this "Update" got added to the end of the question (after it was first posted as a comment below this answer):


  While I understand the example shown in the existing answer, I can't seem to conceptualize how I would be able to write a Rules "loop" to display the field collections in an email. The email body of the rules module does not seem to have the ability to "loop" over content.


I think you're right about 'The email body of the rules module does not seem to have the ability to "loop" over content', or at least I've never discovered anything to do so. However, if what you're looking for is not available, then just make it available ... The trick to do so is similar to what is shown in the Rules example included in my answer to "How to concatenate all token values of a list in a single field within a Rules loop?". In your case, you could make it work like so:


Populate some new Rules variable before the Rules Action to send an eMail, say you name the variable field_collection_var_for_email_body. And the value of this variable should consist of a concatenation of the appropriate values of your nested field collection.
Within the Rules Action to send an eMail, you'll be able to select the token for field_collection_var_for_email_body to include anywhere in your eMail body.


Attention: even though it should technically possible to do all this in a single rule, such rule would possibly get pretty complicated to understand/maintain. That's why if it was up to me, I'd probably implement the Rules logic (as explained in this Part 2) in a separated Rules Component, which provides ... (cfr Rules Component terminology) field_collection_var_for_email_body!!!

Voilà ...

Happying Rules-ing! ... Also with (unlimitted) field collections ... even inside the body of an eMail created with a Rules action to Send an eMail.

PS: No need to write some PHP code to make this happen ...



PPS: For the newbies out there, it should look something like this:



Note that the fields are different here, and not the same as the example/scenario provided above. 

Important: Make sure you select True for the uniqueness option in Add an item to a list, other wise this will trigger a bug that causes your fields to become empty or get readed multiple times. Once you get this bug, the only fix is to restore to a DB backup as you are not able to remove these fields even after turning off the Rule. Some more details about the bug (to avoid):


The bug causes the edit form field collection fields to disappear, while the fields do show up when viewing the node.
In another case, the bug causes the field collection field to be added over and over again. Also, when you click remove, the field doesn't get removed.