问:
Deserialization of a json model with @JsonProperty annotation changed attributes with builder pattern
I am writing a shared object ItineraryDataEntry that is getting exported in a library other projects use.
Model has a lot of attributes, so I am using a builder pattern approach.
Both me and QA relay on the same object for deserialization but are seeing different input (database returns json as set of field vars, and I am returning transformed json keys from api with a more readable format).

BE

1) I am deserializing an object that is saved in an airline database as a json.
Then I am transforming this object's keys with for example @JsonProperty("origin") for field02 and returning ItineraryDataEntry as a part of a complex structured json from a Spring controller endpoint.
With this part I have no issues.

QA

2) QA team is importing mentioned library and wants to deserialize a response from my API to this same ItineraryDataEntry object. This is a problem as Jackson doesn't know how to map for example response property ("origin") back to field02. Solution on their side is for me to add @JsonProperty("origin") annotation to the builder variables.

!

But adding annotation mention in 2) breaks the deserialization then on my part as I am deserializing a json that is different from what is QA team expecting. I need deserialization working on my part for db tests as well.

How would I achieve to still use a single class with a builder pattern and both different inputs would deserialize properly?
Can I kindly ask for your support, a kind member of this excellent community?

```<code>import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.io.Serializable;

/**
 * Model for Itinerary data item.
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "ItineraryDataEntry")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonDeserialize(builder = ItineraryDataEntry.ItineraryDataEntryBuilder.class)
public class ItineraryDataEntry implements Serializable {

  @ApiModelProperty(value = "Item type", example = "pnr", allowableValues = "pnr,leg")
  @JsonProperty("type")
  private String type;

  @ApiModelProperty(value = "Item field01", example = "62SVBP")
  @JsonProperty("legNumber")
  private String field01;

  @ApiModelProperty(value = "Item field02", example = "MASON JAMES MR.")
  @JsonProperty("origin")
  private String field02;

  @ApiModelProperty(value = "Item field03", example = "194375957326594")
  @JsonProperty("destination")
  private String field03;

  @ApiModelProperty(value = "Item field04", example = "AIRLINE NAME")
  @JsonProperty("carrier")
  private String field04;

  @ApiModelProperty(value = "Item field05", example = "Y")
  @JsonProperty("fareBasisCode")
  private String field05;

  @ApiModelProperty(value = "Item field06", example = "TRAVEL AGENT NAME")
  @JsonProperty("serviceClass")
  private String field06;

  @JsonIgnore
  private String field07;

  @ApiModelProperty(value = "Item field08", example = "050918")
  @JsonProperty("flightDate")
  private String field08;

  @JsonIgnore
  private String field09;

  @JsonIgnore
  private String field10;

  @ApiModelProperty(value = "Item field11", example = "1115")
  @JsonProperty("departureTime")
  private String field11;

  @JsonIgnore
  private String field12;

  @JsonIgnore
  private String field13;

  @JsonIgnore
  private String field14;

  public String getType() {
    return type;
  }

  public void setType(final String type) {
    this.type = type;
  }

  public String getField01() {
    return field01;
  }

  public void setField01(final String field01) {
    this.field01 = field01;
  }

  public String getField02() {
    return field02;
  }

  public void setField02(final String field02) {
    this.field02 = field02;
  }

  public String getField03() {
    return field03;
  }

  public void setField03(final String field03) {
    this.field03 = field03;
  }

  public String getField04() {
    return field04;
  }

  public void setField04(final String field04) {
    this.field04 = field04;
  }

  public String getField05() {
    return field05;
  }

  public void setField05(final String field05) {
    this.field05 = field05;
  }

  public String getField06() {
    return field06;
  }

  public void setField06(final String field06) {
    this.field06 = field06;
  }

  public String getField08() {
    return field08;
  }

  public void setField08(final String field08) {
    this.field08 = field08;
  }

  public String getField11() {
    return field11;
  }

  public void setField11(final String field11) {
    this.field11 = field11;
  }

  public String getField07() {
    return field07;
  }

  public void setField07(final String field07) {
    this.field07 = field07;
  }

  public String getField09() {
    return field09;
  }

  public void setField09(final String field09) {
    this.field09 = field09;
  }

  public String getField10() {
    return field10;
  }

  public void setField10(final String field10) {
    this.field10 = field10;
  }

  public String getField12() {
    return field12;
  }

  public void setField12(final String field12) {
    this.field12 = field12;
  }

  public String getField13() {
    return field13;
  }

  public void setField13(final String field13) {
    this.field13 = field13;
  }

  public String getField14() {
    return field14;
  }

  public void setField14(final String field14) {
    this.field14 = field14;
  }

  public ItineraryDataEntry(final ItineraryDataEntryBuilder builder) {
    this.type = builder.type;
    this.field01 = builder.field01;
    this.field02 = builder.field02;
    this.field03 = builder.field03;
    this.field04 = builder.field04;
    this.field05 = builder.field05;
    this.field06 = builder.field06;
    this.field07 = builder.field07;
    this.field08 = builder.field08;
    this.field09 = builder.field09;
    this.field10 = builder.field10;
    this.field11 = builder.field11;
    this.field12 = builder.field12;
    this.field13 = builder.field13;
    this.field14 = builder.field14;
  }

  public ItineraryDataEntry() {
  }

  /**
   * The type Itinerary data entry builder.
   */
  @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "")
  public static class ItineraryDataEntryBuilder {

    private String type;

    private String field01;

    private String field02;

    private String field03;

    private String field04;

    private String field05;

    private String field06;

    private String field07;

    private String field08;

    private String field09;

    private String field10;

    private String field11;

    private String field12;

    private String field13;

    private String field14;

    public ItineraryDataEntryBuilder type(final String param) {
      this.type = param;
      return this;
    }

    public ItineraryDataEntryBuilder field01(final String param) {
      this.field01 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field02(final String param) {
      this.field02 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field03(final String param) {
      this.field03 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field04(final String param) {
      this.field04 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field05(final String param) {
      this.field05 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field06(final String param) {
      this.field06 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field07(final String param) {
      this.field07 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field08(final String param) {
      this.field08 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field09(final String param) {
      this.field09 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field10(final String param) {
      this.field10 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field11(final String param) {
      this.field11 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field12(final String param) {
      this.field12 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field13(final String param) {
      this.field13 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field14(final String param) {
      this.field14 = param;
      return this;
    }

    public ItineraryDataEntryBuilder() {
      // prevent init.
    }

    public ItineraryDataEntry build() {
      return new ItineraryDataEntry(this);
    }
  }
}
</code>```

Edit: A not ideal solution

I've introduced additional variables thanks to @Coder suggestion.
This mean we can use the same model, and the object is serialized/deserialized like intended.
QA debug
I've put @JsonIgnore annotations on this variables so that response model is not changed, but deserialization now works on both sides.

```<code>...
  @JsonIgnore
  private String legNumber;

  @JsonIgnore
  private String origin;

  @JsonIgnore
  private String destination;

  public String getLegNumber() {
    return legNumber;
  }

  public void setLegNumber(final String legNumber) {
    this.legNumber = legNumber;
  }

  public String getOrigin() {
    return origin;
  }

  public void setOrigin(final String origin) {
    this.origin = origin;
  }

  public String getDestination() {
    return destination;
  }

  public void setDestination(final String destination) {
    this.destination = destination;
  }
...
</code>```

Builder part

```<code>  public ItineraryDataEntry(final ItineraryDataEntryBuilder builder) {
    this.type = builder.type;
    this.field01 = builder.field01;
    this.field02 = builder.field02;
    this.field03 = builder.field03;
    this.field04 = builder.field04;
    this.field05 = builder.field05;
    this.field06 = builder.field06;
    this.field07 = builder.field07;
    this.field08 = builder.field08;
    this.field09 = builder.field09;
    this.field10 = builder.field10;
    this.field11 = builder.field11;
    this.field12 = builder.field12;
    this.field13 = builder.field13;
    this.field14 = builder.field14;
    this.legNumber = builder.legNumber;
    this.origin = builder.origin;
    this.destination = builder.destination;
    this.carrier = builder.carrier;
    this.fareBasisCode = builder.fareBasisCode;
    this.serviceClass = builder.serviceClass;
    this.flightDate = builder.flightDate;
    this.departureTime = builder.departureTime;
  }
...

    public ItineraryDataEntryBuilder origin(final String param) {
      this.origin = param;
      return this;
    }

    public ItineraryDataEntryBuilder destination(final String param) {
      this.destination = param;
      return this;
    }

    public ItineraryDataEntryBuilder carrier(final String param) {
      this.carrier = param;
      return this;
    }
...
</code>```

答:
I think your question has the answer in itself.

I am deserializing an object that is saved in an airline database as a json. Then I am transforming this object's keys

You cannot do it in one step and share the same model and perform 2 different deserializations on it. That beats the purpose of model reuse.

Instead, I would suggest having 2 models. One to deserialize into a structure that you could commonly share across teams/projects. Another to map it to a meaningful object like an ItineraryDataEntry that will have type, origin, destination, etc.. You can then write a separate method in your controller to transform the deserialized object in your meaningful ItineraryDataEntry.

I am assuming that your model is deeper than what you have mentioned. In that case, I would suggest exploring Orika library.

Body:
I am writing a shared object ItineraryDataEntry that is getting exported in a library other projects use.
Model has a lot of attributes, so I am using a builder pattern approach.
Both me and QA relay on the same object for deserialization but are seeing different input (database returns json as set of field vars, and I am returning transformed json keys from api with a more readable format).

BE

1) I am deserializing an object that is saved in an airline database as a json.
Then I am transforming this object's keys with for example @JsonProperty("origin") for field02 and returning ItineraryDataEntry as a part of a complex structured json from a Spring controller endpoint.
With this part I have no issues.

QA

2) QA team is importing mentioned library and wants to deserialize a response from my API to this same ItineraryDataEntry object. This is a problem as Jackson doesn't know how to map for example response property ("origin") back to field02. Solution on their side is for me to add @JsonProperty("origin") annotation to the builder variables.

!

But adding annotation mention in 2) breaks the deserialization then on my part as I am deserializing a json that is different from what is QA team expecting. I need deserialization working on my part for db tests as well.

How would I achieve to still use a single class with a builder pattern and both different inputs would deserialize properly?
Can I kindly ask for your support, a kind member of this excellent community?

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.io.Serializable;

/**
 * Model for Itinerary data item.
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "ItineraryDataEntry")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonDeserialize(builder = ItineraryDataEntry.ItineraryDataEntryBuilder.class)
public class ItineraryDataEntry implements Serializable {

  @ApiModelProperty(value = "Item type", example = "pnr", allowableValues = "pnr,leg")
  @JsonProperty("type")
  private String type;

  @ApiModelProperty(value = "Item field01", example = "62SVBP")
  @JsonProperty("legNumber")
  private String field01;

  @ApiModelProperty(value = "Item field02", example = "MASON JAMES MR.")
  @JsonProperty("origin")
  private String field02;

  @ApiModelProperty(value = "Item field03", example = "194375957326594")
  @JsonProperty("destination")
  private String field03;

  @ApiModelProperty(value = "Item field04", example = "AIRLINE NAME")
  @JsonProperty("carrier")
  private String field04;

  @ApiModelProperty(value = "Item field05", example = "Y")
  @JsonProperty("fareBasisCode")
  private String field05;

  @ApiModelProperty(value = "Item field06", example = "TRAVEL AGENT NAME")
  @JsonProperty("serviceClass")
  private String field06;

  @JsonIgnore
  private String field07;

  @ApiModelProperty(value = "Item field08", example = "050918")
  @JsonProperty("flightDate")
  private String field08;

  @JsonIgnore
  private String field09;

  @JsonIgnore
  private String field10;

  @ApiModelProperty(value = "Item field11", example = "1115")
  @JsonProperty("departureTime")
  private String field11;

  @JsonIgnore
  private String field12;

  @JsonIgnore
  private String field13;

  @JsonIgnore
  private String field14;

  public String getType() {
    return type;
  }

  public void setType(final String type) {
    this.type = type;
  }

  public String getField01() {
    return field01;
  }

  public void setField01(final String field01) {
    this.field01 = field01;
  }

  public String getField02() {
    return field02;
  }

  public void setField02(final String field02) {
    this.field02 = field02;
  }

  public String getField03() {
    return field03;
  }

  public void setField03(final String field03) {
    this.field03 = field03;
  }

  public String getField04() {
    return field04;
  }

  public void setField04(final String field04) {
    this.field04 = field04;
  }

  public String getField05() {
    return field05;
  }

  public void setField05(final String field05) {
    this.field05 = field05;
  }

  public String getField06() {
    return field06;
  }

  public void setField06(final String field06) {
    this.field06 = field06;
  }

  public String getField08() {
    return field08;
  }

  public void setField08(final String field08) {
    this.field08 = field08;
  }

  public String getField11() {
    return field11;
  }

  public void setField11(final String field11) {
    this.field11 = field11;
  }

  public String getField07() {
    return field07;
  }

  public void setField07(final String field07) {
    this.field07 = field07;
  }

  public String getField09() {
    return field09;
  }

  public void setField09(final String field09) {
    this.field09 = field09;
  }

  public String getField10() {
    return field10;
  }

  public void setField10(final String field10) {
    this.field10 = field10;
  }

  public String getField12() {
    return field12;
  }

  public void setField12(final String field12) {
    this.field12 = field12;
  }

  public String getField13() {
    return field13;
  }

  public void setField13(final String field13) {
    this.field13 = field13;
  }

  public String getField14() {
    return field14;
  }

  public void setField14(final String field14) {
    this.field14 = field14;
  }

  public ItineraryDataEntry(final ItineraryDataEntryBuilder builder) {
    this.type = builder.type;
    this.field01 = builder.field01;
    this.field02 = builder.field02;
    this.field03 = builder.field03;
    this.field04 = builder.field04;
    this.field05 = builder.field05;
    this.field06 = builder.field06;
    this.field07 = builder.field07;
    this.field08 = builder.field08;
    this.field09 = builder.field09;
    this.field10 = builder.field10;
    this.field11 = builder.field11;
    this.field12 = builder.field12;
    this.field13 = builder.field13;
    this.field14 = builder.field14;
  }

  public ItineraryDataEntry() {
  }

  /**
   * The type Itinerary data entry builder.
   */
  @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "")
  public static class ItineraryDataEntryBuilder {

    private String type;

    private String field01;

    private String field02;

    private String field03;

    private String field04;

    private String field05;

    private String field06;

    private String field07;

    private String field08;

    private String field09;

    private String field10;

    private String field11;

    private String field12;

    private String field13;

    private String field14;

    public ItineraryDataEntryBuilder type(final String param) {
      this.type = param;
      return this;
    }

    public ItineraryDataEntryBuilder field01(final String param) {
      this.field01 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field02(final String param) {
      this.field02 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field03(final String param) {
      this.field03 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field04(final String param) {
      this.field04 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field05(final String param) {
      this.field05 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field06(final String param) {
      this.field06 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field07(final String param) {
      this.field07 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field08(final String param) {
      this.field08 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field09(final String param) {
      this.field09 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field10(final String param) {
      this.field10 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field11(final String param) {
      this.field11 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field12(final String param) {
      this.field12 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field13(final String param) {
      this.field13 = param;
      return this;
    }

    public ItineraryDataEntryBuilder field14(final String param) {
      this.field14 = param;
      return this;
    }

    public ItineraryDataEntryBuilder() {
      // prevent init.
    }

    public ItineraryDataEntry build() {
      return new ItineraryDataEntry(this);
    }
  }
}

Edit: A not ideal solution

I've introduced additional variables thanks to @Coder suggestion.
This mean we can use the same model, and the object is serialized/deserialized like intended.
QA debug
I've put @JsonIgnore annotations on this variables so that response model is not changed, but deserialization now works on both sides.

...
  @JsonIgnore
  private String legNumber;

  @JsonIgnore
  private String origin;

  @JsonIgnore
  private String destination;

  public String getLegNumber() {
    return legNumber;
  }

  public void setLegNumber(final String legNumber) {
    this.legNumber = legNumber;
  }

  public String getOrigin() {
    return origin;
  }

  public void setOrigin(final String origin) {
    this.origin = origin;
  }

  public String getDestination() {
    return destination;
  }

  public void setDestination(final String destination) {
    this.destination = destination;
  }
...

Builder part

  public ItineraryDataEntry(final ItineraryDataEntryBuilder builder) {
    this.type = builder.type;
    this.field01 = builder.field01;
    this.field02 = builder.field02;
    this.field03 = builder.field03;
    this.field04 = builder.field04;
    this.field05 = builder.field05;
    this.field06 = builder.field06;
    this.field07 = builder.field07;
    this.field08 = builder.field08;
    this.field09 = builder.field09;
    this.field10 = builder.field10;
    this.field11 = builder.field11;
    this.field12 = builder.field12;
    this.field13 = builder.field13;
    this.field14 = builder.field14;
    this.legNumber = builder.legNumber;
    this.origin = builder.origin;
    this.destination = builder.destination;
    this.carrier = builder.carrier;
    this.fareBasisCode = builder.fareBasisCode;
    this.serviceClass = builder.serviceClass;
    this.flightDate = builder.flightDate;
    this.departureTime = builder.departureTime;
  }
...

    public ItineraryDataEntryBuilder origin(final String param) {
      this.origin = param;
      return this;
    }

    public ItineraryDataEntryBuilder destination(final String param) {
      this.destination = param;
      return this;
    }

    public ItineraryDataEntryBuilder carrier(final String param) {
      this.carrier = param;
      return this;
    }
...


来源: stackexchange

问:
Android Revoke Permissions when App is running - Can I recover the App
I have just moved my target SDK to v9.

I have hit the issue where when I have my app running, I open the settings and revoke one of the permissions. When I then bring my app to the foreground it restarts and tries to restore the app, however it fails to restore properly.

My understanding is the behaviour should be the same as rotating the device. However in this case my app can recover correctly.

What the behaviour is when revoking permission when the app is running? Should the app just terminate and start from the beginning, or is it possible to recover?

答:
My understanding the behaviour should be the same as rotating the device.

No.

Can someone tell me what the behaviour is when revoking a permission when the app is running.

Your app's processes are terminated. Android will start a fresh process for your app when the user returns to it. Android may attempt to restart the last activity the user was in, depending on the timing of all of these events.

In general, the behavior is the same as if the user left your app for a while (say, 20 minutes), Android terminated the process in the background, and then the user returned to it.

Should the app just terminate and the just start from the beginning, or is it possible to recover.

We cannot answer that, as the details will depend on the app. Ideally, your app can "recover", but it will require you to design the app to be able to deal with a fresh process from every activity.

ContentLicense: CC BY-SA 4.0


问:
size() option is missing using Selenium webdriver through Java
have been following some classes to improve my automation skills with Selenium Webdrive. I don't have size() method as an option when trying to count the numbers of links inside a page.

Am I missing some jars? Import libraries?

```<code>java public static void main(String[] args) throws InterruptedException {
        System.setProperty("webdriver.chrome.driver", "/Users/Follo/Dropbox/Chrome Drivers/chromedriver");
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        // options.addArguments("--headless");
        WebDriver driver = new ChromeDriver(options);
        driver.get("URL");
        WebElement link = driver.findElement(By.tagName("a"));
        link.size()
        // .size do not appear as an option in the dropdown menu
        System.out.println(link.size());
        driver.quit();
    }
}
</code>```

答:
Use "findElements" instead of "findElement". It returns list of elements so you can iterate through them.

The difference is that findElement returns first matched element and findElements return list of all matched elements

Body:
have been following some classes to improve my automation skills with Selenium Webdrive. I don't have size() method as an option when trying to count the numbers of links inside a page.

Am I missing some jars? Import libraries?

java public static void main(String[] args) throws InterruptedException {
        System.setProperty("webdriver.chrome.driver", "/Users/Follo/Dropbox/Chrome Drivers/chromedriver");
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        // options.addArguments("--headless");
        WebDriver driver = new ChromeDriver(options);
        driver.get("URL");
        WebElement link = driver.findElement(By.tagName("a"));
        link.size()
        // .size do not appear as an option in the dropdown menu
        System.out.println(link.size());
        driver.quit();
    }
}


问:
How to create a clean four-column, left-aligned, layout using justify-content: space-between
I am trying to create a display blog post component with Flexbox that primarily uses justify-content: space-between. In a 4-column layout, it looks great when there are 4 posts to fill the row. The issue is when there are not 4 posts, but 2 or 3. At this point, the posts get spread out and it just looks sloppy. I want to use flexbox without any JavaScript, and I want to be able to have the layout be fully responsive. So at other breakpoints the column layout will drop to 3, 2, or even 1.

One of the things that I found that works great is adding an :after pseudo element to the wrapper with a set width that will fill in the empty space. The problem with that is it is not dynamic enough and will not work properly if I have a different number of post then the one I planned for.

For example: If I have 2 posts, each at 25% width, and then a pseudo element at 50% width, everything looks great. Once I have 3 posts it is not so great because the 50% pseudo element now needs to be 25%. Finally, if there is 4 I wouldn't need a pseudo element at all.

I am trying to work with using some of the SASS selectors, but for some reason when I try to target the parent with my :after element, it targets something else way up the DOM tree.

.content {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;

    .entry:nth-child( 2 ):last-of-type {
        :after & {
            content: "";
            flex-grow: 0;
            width: 50%;
        }
    }
    .entry:nth-child( 3 ):last-of-type {
        :after & {
            content: "";
            flex-grow: 0;
            width: 50%;
        }
    }
}
```

At this point I expected the :after element to target the parent class "content" but it doesn't. I also didn't think about how I would adjust it to be more dynamic and be able to handle multiple rows. I guess I could just do the math and make it something like .entry:nth-child( 3n+4 ):last-of-type {}, but I haven't even gotten there yet.

答:
Here is a grid solution in Code Pen

For this to work in your query template it would look like this:

```<code><div class="post-grid>
    //while loop here
    <div class="each-post">
        <img src="<?php get_the_post_thumbnail() ?>">
        <h2><?php get_the_title() ?></h2>
        <p><?php get_the_excerpt() ?></p>
    </div>
    // end loop here
</div>

</code>```

Body:
I am trying to create a display blog post component with Flexbox that primarily uses justify-content: space-between. In a 4-column layout, it looks great when there are 4 posts to fill the row. The issue is when there are not 4 posts, but 2 or 3. At this point, the posts get spread out and it just looks sloppy. I want to use flexbox without any JavaScript, and I want to be able to have the layout be fully responsive. So at other breakpoints the column layout will drop to 3, 2, or even 1.

One of the things that I found that works great is adding an :after pseudo element to the wrapper with a set width that will fill in the empty space. The problem with that is it is not dynamic enough and will not work properly if I have a different number of post then the one I planned for.

For example: If I have 2 posts, each at 25% width, and then a pseudo element at 50% width, everything looks great. Once I have 3 posts it is not so great because the 50% pseudo element now needs to be 25%. Finally, if there is 4 I wouldn't need a pseudo element at all.

I am trying to work with using some of the SASS selectors, but for some reason when I try to target the parent with my :after element, it targets something else way up the DOM tree.

.content {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;

    .entry:nth-child( 2 ):last-of-type {
        :after & {
            content: "";
            flex-grow: 0;
            width: 50%;
        }
    }
    .entry:nth-child( 3 ):last-of-type {
        :after & {
            content: "";
            flex-grow: 0;
            width: 50%;
        }
    }
}

At this point I expected the :after element to target the parent class "content" but it doesn't. I also didn't think about how I would adjust it to be more dynamic and be able to handle multiple rows. I guess I could just do the math and make it something like .entry:nth-child( 3n+4 ):last-of-type {}, but I haven't even gotten there yet.

Body:
Here is a grid solution in Code Pen

For this to work in your query template it would look like this:

<div class="post-grid>
    //while loop here
    <div class="each-post">
        <img src="<?php get_the_post_thumbnail() ?>">
        <h2><?php get_the_title() ?></h2>
        <p><?php get_the_excerpt() ?></p>
    </div>
    // end loop here
</div>


问:
Variables values in remotely executed complex bash commands
I want to run a complex list of commands on a remote host. I could solve easily by creating another script with such commands and then have my other script call it (with or without copying it to the remote host), but I do not want to. My issue is that I have some variables that are fixed for the whole script and then I have the for-loop variable. I can get one of the two to be properly evaluated on the remote host, but noth both. All I've found on similar issues is talks about using note quotes, " or ' around different elements. Nothing I've tried worked on both the fixed (to be expanded before ssh) and the loop variables (to be expanded remotely) at the same time (highlight for you, @Inian, since you can't fucking read the full question before marking it as duplicate of something it's not a duplicate of).

fixed_value="blue"

ssh remote_host << "EOF"
    value_list="VALUE1 VALUE2"
    for i in $value_list; do
        echo "executing $i"
        my_program -arg1 $i -arg2 "$fixed_value"
    done
EOF
```

<p>What I expect is to run my_program (which is a binary on the remote host) with two arguments, one is fixed and is actually passed as an input to the local script, the other is read from a list of fixed values, so that, in the example, I should end up executing on remote host the following:</p>

<pre class="lang-sh prettyprint-override"><code>my_program -arg1 VALUE1 -arg2 blue
my_program -arg1 VALUE2 -arg2 blue
</code>```

I probably need a way to 'pass values' to the script being executed in the remote host, or force evaluation of $fixed_value before the command is sent (which I tried to do by using quotes, but it didn't work), without preventing the evaluation of $i from being done on the remote host. Because all I get by switching around the quotes (or removing them, or changing them) is either:

my_program -arg1 -arg2 blue
my_program -arg1 -arg2 blue
```

<p>or</p>

<pre class="lang-sh prettyprint-override"><code>my_program -arg1 VALUE1 -arg2
my_program -arg1 VALUE2 -arg2
</code>```

答:
#!/bin/bash

fixed_value="blue"
qq='"'

ssh remote_host bash -c "
  value_list='VALUE1 VALUE2'
  for i in \$value_list; do
    echo ${qq}executing \$i$qq
    my_program -arg1 \$i -arg2 '$fixed_value'
  done
"
```

I've wrapped the command in a bash -c "…" command. Because you still need some double-quotes and because I've come to distrust escaped quotes, I created a $qq variable to represent the double-quote character. Variables passed from the server side ($qq and $fixed_value) are unescaped so their values are passed to the server. Variables for server-side evaluation ($value_list and $i) are escaped so they are interpreted by the remote bash call.

The exit code of this client-side script will be the exit code from ssh, which should be dictated by the exit code from the final iteration of my_program (unless ssh itself fails or is terminated).

Body:
I want to run a complex list of commands on a remote host. I could solve easily by creating another script with such commands and then have my other script call it (with or without copying it to the remote host), but I do not want to. My issue is that I have some variables that are fixed for the whole script and then I have the for-loop variable. I can get one of the two to be properly evaluated on the remote host, but noth both. All I've found on similar issues is talks about using note quotes, " or ' around different elements. Nothing I've tried worked on both the fixed (to be expanded before ssh) and the loop variables (to be expanded remotely) at the same time (highlight for you, @Inian, since you can't fucking read the full question before marking it as duplicate of something it's not a duplicate of).

fixed_value="blue"

ssh remote_host << "EOF"
    value_list="VALUE1 VALUE2"
    for i in $value_list; do
        echo "executing $i"
        my_program -arg1 $i -arg2 "$fixed_value"
    done
EOF

What I expect is to run my_program (which is a binary on the remote host) with two arguments, one is fixed and is actually passed as an input to the local script, the other is read from a list of fixed values, so that, in the example, I should end up executing on remote host the following:

my_program -arg1 VALUE1 -arg2 blue
my_program -arg1 VALUE2 -arg2 blue

I probably need a way to 'pass values' to the script being executed in the remote host, or force evaluation of $fixed_value before the command is sent (which I tried to do by using quotes, but it didn't work), without preventing the evaluation of $i from being done on the remote host. Because all I get by switching around the quotes (or removing them, or changing them) is either:

my_program -arg1 -arg2 blue
my_program -arg1 -arg2 blue

or

my_program -arg1 VALUE1 -arg2
my_program -arg1 VALUE2 -arg2

Body:
#!/bin/bash

fixed_value="blue"
qq='"'

ssh remote_host bash -c "
  value_list='VALUE1 VALUE2'
  for i in \$value_list; do
    echo ${qq}executing \$i$qq
    my_program -arg1 \$i -arg2 '$fixed_value'
  done
"

I've wrapped the command in a bash -c "…" command. Because you still need some double-quotes and because I've come to distrust escaped quotes, I created a $qq variable to represent the double-quote character. Variables passed from the server side ($qq and $fixed_value) are unescaped so their values are passed to the server. Variables for server-side evaluation ($value_list and $i) are escaped so they are interpreted by the remote bash call.

The exit code of this client-side script will be the exit code from ssh, which should be dictated by the exit code from the final iteration of my_program (unless ssh itself fails or is terminated).


问:
Data is duplicating using onSnapshot
I am adding data to Cloud firestore using a bootstrap modal
I want a table to update the data when the modal is closed

HTML for modal buttons

```<code><div class="modal-footer">

    <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
    <button id="submitStudent" type="button" class="btn btn-primary" data-dismiss="modal">Save changes</button>
</div>
</code>```

Javascript

```<code>$( document ).ready(function(){

    //call the firebase.app namespace and store it to the the constant app
    const app = firebase.app();
    //log detail to console.
    // not required but does allo the testing to see if the app is working
    console.log(app);
    //load the firebase db into the constant DB
    const db = firebase.firestore();

//JQUERY FOR GETTING A STUDENT DETAILS AND OUTPUTTING TO TABLE:

        db.collection("students").onSnapshot(function(querySnapshot) {

        querySnapshot.forEach(function(doc) {

            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
            let student = doc.data();
            // pull the student data into the table, the escape characters between each set of data denote a new unit
            // currently this is handed pulled from the DB, however it would be better to use a for loop

            $('#overallDashboard > tbody:last-child').append(

                    '<tr> \
                        <th scope="row">'+doc.id+'</th> \
                         <td>'+student.first_name+'</td> \
                         <td>'+student.last_name+'</td> \
                         \
                         <td>'+student.UnitGrades.IT1.CG+'</td> \
                         <td>'+student.UnitGrades.IT1.PG+'</td> \
                         <td>'+student.UnitGrades.IT1.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT2.CG+'</td> \
                         <td>'+student.UnitGrades.IT2.PG+'</td> \
                         <td>'+student.UnitGrades.IT2.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT3.CG+'</td> \
                         <td>'+student.UnitGrades.IT3.PG+'</td> \
                         <td>'+student.UnitGrades.IT3.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT6.CG+'</td> \
                         <td>'+student.UnitGrades.IT6.PG+'</td> \
                         <td>'+student.UnitGrades.IT6.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT8.CG+'</td> \
                         <td>'+student.UnitGrades.IT8.PG+'</td> \
                         <td>'+student.UnitGrades.IT8.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT9.CG+'</td> \
                         <td>'+student.UnitGrades.IT9.PG+'</td> \
                         <td>'+student.UnitGrades.IT9.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT12.CG+'</td> \
                         <td>'+student.UnitGrades.IT12.PG+'</td> \
                         <td>'+student.UnitGrades.IT12.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT13.CG+'</td> \
                         <td>'+student.UnitGrades.IT13.PG+'</td> \
                         <td>'+student.UnitGrades.IT13.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT15.CG+'</td> \
                         <td>'+student.UnitGrades.IT15.PG+'</td> \
                         <td>'+student.UnitGrades.IT15.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT17.CG+'</td> \
                         <td>'+student.UnitGrades.IT17.PG+'</td> \
                         <td>'+student.UnitGrades.IT17.TG+'</td> \
                         \
                         <td>'+student.UnitGrades.IT21.CG+'</td> \
                         <td>'+student.UnitGrades.IT21.PG+'</td> \
                         <td>'+student.UnitGrades.IT21.TG+'</td> \
                         \
                         <td>Calc</td> \
                         <td>Calc</td> \
                         <td>Calc</td> \
                     </tr>'

                     );//close append

    }); //end for each loop
});//end onsnapshot

    // JQUERY CODE FOR ADDING A STUDENT

    // form for submitting function
    $("#submitStudent").click(function (event) {

        const db = firebase.firestore();
        console.log(db);

        //search document IDs in database
        let student = db.collection("students").doc($("#addStudentNumber").val());

            // add students to the DB
            student.get().then(function(doc) {
                if (doc.exists) {
                    console.log("Document already exists:", doc.data());

                } else {
                    // doc.data() will be undefined in this case
                    console.log("No such document!");

                    student.set({
                    "first_name": $("#addStudentFirstName").val(),
                    "last_name": $("#addStudentLastName").val(),
                    "DOB": $("#addStudentDOB").val(),
                    "completion_year": $("#addStudentCompletionYear").val(),
                    "student_number": $("#addStudentNumber").val(),
                    "student_email": $("#addStudentEmail").val(),
                    "UnitGrades":{
                        "IT1": {
                            "id":"IT1",
                            "name":"Fundamentals of IT",
                            "type":"Exam",
                            "GLH":90,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT2": {
                            "id":"IT2",
                            "name":"Global Information",
                            "type":"Exam",
                            "GLH":90,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT3": {
                            "id":"IT3",
                            "name":"Cyber Security",
                            "type":"Exam",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT6": {
                            "id":"IT6",
                            "name":"Appilication Design",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT8": {
                            "id":"IT8",
                            "name":"Project Management",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT9": {
                            "id":"IT9",
                            "name":"Product Development",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT12": {
                            "id":"IT12",
                            "name":"Mobile Technology",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT13": {
                            "id":"IT13",
                            "name":"Social Media and Digital Marketing",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT15": {
                            "id":"IT15",
                            "name":"Games Design and Prototyping",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT17": {
                            "id":"IT17",
                            "name":"Internet of Everything",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT21": {
                            "id":"IT21",
                            "name":"Web Design and Prototyping",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        }
                    }
                    })
                    .then(function() {
                        console.log("Document successfully written!");

                    })
                    .catch(function(error) {
                        console.error("Error writing document: ", error);
                    });
                }

                }).catch(function(error) {
                    console.log("Error getting document: ", error);
                });

                // outputData();

                db.collection("students").get().then(function(querySnapshot) {
                    querySnapshot.forEach(function(doc) {
                        // doc.data() is never undefined for query doc snapshots
                        console.log(doc.id, " => ", doc.data());

                });
                    })
                    .catch(function(error) {
                        console.log("Error getting documents: ", error);
            });

        }) //close submit form click function

//close document read function
    });
</code>```

I expect the table to show the new document that has been added

However all of the data in the database is appending to the bottom of the current data, I only want the new document to be shown in the page, preferably in order of the student forename.

Update

Using the response from Frank van Puffelen I have resolved this

I created a new html variable with a blank div inside
I then used .add to add the code for each iteration of the for loop as previously written.

I then used .html to call the variable html and update the page code.

```<code>db.collection("students").onSnapshot(function(querySnapshot) {

                        let html = $("<div></div>");

                        querySnapshot.forEach(function(doc) {

                            let student = doc.data();

                            html = html.add($('<tr> \
                                        <th scope="row">'+doc.id+'</th> \
                                         <td>'+student.first_name+'</td> \
                                         <td>'+student.last_name+'</td> \
...
</code>```

```<code>$('#overallDashboard > tbody:last-child').html(html);
</code>```

答:
You have this code that listens for data and changes in the database:

```<code>db.collection("students").onSnapshot(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
        let student = doc.data();

        $('#overallDashboard > tbody:last-child').append(
            ...
</code>```

Keep in mind that onSnapshot gets called with all data in the collection. So when you first connect to Firestore, and whenever the data changes, you get all documents from students and add them to #overallDashboard. This means that the first time, you end up with all students. Say there are 3 students, you end up with a table with:

```<code>student 1
student 2
student 3
</code>```

Now when there's a change, you add the complete data to the end of the table. So you end up with the original content and the changed content. Say that you're adding an additional student document, you end up with:

```<code>student 1 // first time onSnapshot got called
student 2
student 3
student 1 // second time onSnapshot got called
student 2
student 3
student 4
</code>```

And when you then for example remove the first student, you end up with:

```<code>student 1 // first time onSnapshot got called
student 2
student 3
student 1 // second time onSnapshot got called
student 2
student 3
student 4
student 2 // third time onSnapshot got called
student 3
student 4
</code>```

There are two solutions to the problem:

Clear out the table every time onSnapshot is called.

Determine the exact change that was made to the data, and update the HTML for that.

While the second approach is more efficient, it also is a bit more involved. So instead I'll show the simple approach below, which is to clear out the HTML in the table every time onSnapshot gets called:

```<code>db.collection("students").onSnapshot(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
        let student = doc.data();

        $('#overallDashboard > tbody:last-child').html(
            ...
</code>```

Title: Data is duplicating using onSnapshot

Body:
I am adding data to Cloud firestore using a bootstrap modal
I want a table to update the data when the modal is closed

HTML for modal buttons

    <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
    <button id="submitStudent" type="button" class="btn btn-primary" data-dismiss="modal">Save changes</button>

Javascript

$( document ).ready(function(){

    //call the firebase.app namespace and store it to the the constant app
    const app = firebase.app();
    //log detail to console.
    // not required but does allo the testing to see if the app is working
    console.log(app);
    //load the firebase db into the constant DB
    const db = firebase.firestore();

//JQUERY FOR GETTING A STUDENT DETAILS AND OUTPUTTING TO TABLE:

        db.collection("students").onSnapshot(function(querySnapshot) {

        querySnapshot.forEach(function(doc) {

            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
            let student = doc.data();
            // pull the student data into the table, the escape characters between each set of data denote a new unit
            // currently this is handed pulled from the DB, however it would be better to use a for loop

            $('#overallDashboard > tbody:last-child').append(

                    '
 \
                        '+doc.id+'	 \
                         '+student.first_name+'	 \
                         '+student.last_name+'	 \
                         \
                         '+student.UnitGrades.IT1.CG+'	 \
                         '+student.UnitGrades.IT1.PG+'	 \
                         '+student.UnitGrades.IT1.TG+'	 \
                         \
                         '+student.UnitGrades.IT2.CG+'	 \
                         '+student.UnitGrades.IT2.PG+'	 \
                         '+student.UnitGrades.IT2.TG+'	 \
                         \
                         '+student.UnitGrades.IT3.CG+'	 \
                         '+student.UnitGrades.IT3.PG+'	 \
                         '+student.UnitGrades.IT3.TG+'	 \
                         \
                         '+student.UnitGrades.IT6.CG+'	 \
                         '+student.UnitGrades.IT6.PG+'	 \
                         '+student.UnitGrades.IT6.TG+'	 \
                         \
                         '+student.UnitGrades.IT8.CG+'	 \
                         '+student.UnitGrades.IT8.PG+'	 \
                         '+student.UnitGrades.IT8.TG+'	 \
                         \
                         '+student.UnitGrades.IT9.CG+'	 \
                         '+student.UnitGrades.IT9.PG+'	 \
                         '+student.UnitGrades.IT9.TG+'	 \
                         \
                         '+student.UnitGrades.IT12.CG+'	 \
                         '+student.UnitGrades.IT12.PG+'	 \
                         '+student.UnitGrades.IT12.TG+'	 \
                         \
                         '+student.UnitGrades.IT13.CG+'	 \
                         '+student.UnitGrades.IT13.PG+'	 \
                         '+student.UnitGrades.IT13.TG+'	 \
                         \
                         '+student.UnitGrades.IT15.CG+'	 \
                         '+student.UnitGrades.IT15.PG+'	 \
                         '+student.UnitGrades.IT15.TG+'	 \
                         \
                         '+student.UnitGrades.IT17.CG+'	 \
                         '+student.UnitGrades.IT17.PG+'	 \
                         '+student.UnitGrades.IT17.TG+'	 \
                         \
                         '+student.UnitGrades.IT21.CG+'	 \
                         '+student.UnitGrades.IT21.PG+'	 \
                         '+student.UnitGrades.IT21.TG+'	 \
                         \
                         Calc	 \
                         Calc	 \
                         Calc	 \

'

                     );//close append

    }); //end for each loop
});//end onsnapshot

    // JQUERY CODE FOR ADDING A STUDENT

    // form for submitting function
    $("#submitStudent").click(function (event) {

        const db = firebase.firestore();
        console.log(db);

        //search document IDs in database
        let student = db.collection("students").doc($("#addStudentNumber").val());

            // add students to the DB
            student.get().then(function(doc) {
                if (doc.exists) {
                    console.log("Document already exists:", doc.data());

                } else {
                    // doc.data() will be undefined in this case
                    console.log("No such document!");

                    student.set({
                    "first_name": $("#addStudentFirstName").val(),
                    "last_name": $("#addStudentLastName").val(),
                    "DOB": $("#addStudentDOB").val(),
                    "completion_year": $("#addStudentCompletionYear").val(),
                    "student_number": $("#addStudentNumber").val(),
                    "student_email": $("#addStudentEmail").val(),
                    "UnitGrades":{
                        "IT1": {
                            "id":"IT1",
                            "name":"Fundamentals of IT",
                            "type":"Exam",
                            "GLH":90,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT2": {
                            "id":"IT2",
                            "name":"Global Information",
                            "type":"Exam",
                            "GLH":90,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT3": {
                            "id":"IT3",
                            "name":"Cyber Security",
                            "type":"Exam",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT6": {
                            "id":"IT6",
                            "name":"Appilication Design",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT8": {
                            "id":"IT8",
                            "name":"Project Management",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT9": {
                            "id":"IT9",
                            "name":"Product Development",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT12": {
                            "id":"IT12",
                            "name":"Mobile Technology",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT13": {
                            "id":"IT13",
                            "name":"Social Media and Digital Marketing",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT15": {
                            "id":"IT15",
                            "name":"Games Design and Prototyping",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT17": {
                            "id":"IT17",
                            "name":"Internet of Everything",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        },
                        "IT21": {
                            "id":"IT21",
                            "name":"Web Design and Prototyping",
                            "type":"CWK",
                            "GLH":60,
                            "CG": "F",
                            "PG": "F",
                            "TG": "F"
                        }
                    }
                    })
                    .then(function() {
                        console.log("Document successfully written!");

                    })
                    .catch(function(error) {
                        console.error("Error writing document: ", error);
                    });
                }

                }).catch(function(error) {
                    console.log("Error getting document: ", error);
                });

                // outputData();

                db.collection("students").get().then(function(querySnapshot) {
                    querySnapshot.forEach(function(doc) {
                        // doc.data() is never undefined for query doc snapshots
                        console.log(doc.id, " => ", doc.data());

                });
                    })
                    .catch(function(error) {
                        console.log("Error getting documents: ", error);
            });

        }) //close submit form click function

//close document read function
    });

I expect the table to show the new document that has been added

However all of the data in the database is appending to the bottom of the current data, I only want the new document to be shown in the page, preferably in order of the student forename.

Update

Using the response from Frank van Puffelen I have resolved this

I created a new html variable with a blank div inside
I then used .add to add the code for each iteration of the for loop as previously written.

I then used .html to call the variable html and update the page code.

db.collection("students").onSnapshot(function(querySnapshot) {

                        let html = $("

");

                        querySnapshot.forEach(function(doc) {

                            let student = doc.data();

                            html = html.add($('
 \
                                        '+doc.id+'	 \
                                         '+student.first_name+'	 \
                                         '+student.last_name+'	 \
...

$('#overallDashboard > tbody:last-child').html(html);

Body:
You have this code that listens for data and changes in the database:

db.collection("students").onSnapshot(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
        let student = doc.data();

        $('#overallDashboard > tbody:last-child').append(
            ...

Keep in mind that onSnapshot gets called with all data in the collection. So when you first connect to Firestore, and whenever the data changes, you get all documents from students and add them to #overallDashboard. This means that the first time, you end up with all students. Say there are 3 students, you end up with a table with:

student 1
student 2
student 3

Now when there's a change, you add the complete data to the end of the table. So you end up with the original content and the changed content. Say that you're adding an additional student document, you end up with:

student 1 // first time onSnapshot got called
student 2
student 3
student 1 // second time onSnapshot got called
student 2
student 3
student 4

And when you then for example remove the first student, you end up with:

student 1 // first time onSnapshot got called
student 2
student 3
student 1 // second time onSnapshot got called
student 2
student 3
student 4
student 2 // third time onSnapshot got called
student 3
student 4

There are two solutions to the problem:

Clear out the table every time onSnapshot is called.

Determine the exact change that was made to the data, and update the HTML for that.

While the second approach is more efficient, it also is a bit more involved. So instead I'll show the simple approach below, which is to clear out the HTML in the table every time onSnapshot gets called:

db.collection("students").onSnapshot(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
        let student = doc.data();

        $('#overallDashboard > tbody:last-child').html(
            ...


问:
How to disable creating/copying obj outside a Factory-Method?
I have a class, that has very heavy payload, so that it is very expensive to create/copy/move an instance of this class.
Since they will not change after the app has finished initialization, there is no need to create temporary objects of this class anywere. I only need to cache objects in a container(std::map), and offer a "const reference" when needed.

The thing that must be emphasized is that I'm seeking a solution which can avoid double-create or unnecessary copy a object before add it into the container(I don't think a solution likes one @getsoubl proposed can resolve the problem, because it does not eliminate doulbe-creating or unnecessary copying).

So I want to arrange the constructor method into "private/protected" section of the class body, so as to forbid any of creating/copying/moving outside of the "Factory-Method". Following is my original solution:

```<code>class MyClass {
public:
   // methods of the class
   static const MyClass & findObject( int iKey ) {
      auto pair = mapObjects.try_emplace( iKey, iKey );
      if ( pair.second )
         cout << "New object has been created" << endl;

      return pair.first->second;
   };

   // deleted
   MyClass() = delete;
   MyClass( MyClass & ) = delete;
   MyClass( MyClass && ) = delete;
   MyClass( const MyClass & ) = delete;
   MyClass( const MyClass && ) = delete;
   MyClass & operator=( MyClass & ) = delete;
   MyClass & operator=( MyClass && ) = delete;
   MyClass & operator=( const MyClass & ) = delete;
   MyClass & operator=( const MyClass && ) = delete;

private:
   // vars of the class
   static map<int, MyClass> mapObjects;

   // vars of instance
   string some_heavy_payload;

   // methods of instance
   MyClass( int iKey ) :
     some_heavy_payload( std::to_string( iKey ) ) {};
};

map<int, MyClass> MyClass::mapObjects;

int main() {
   const MyClass & obj = MyClass::findObject( 1 );
   return EXIT_SUCCESS;
};
</code>```

But I'm put into a contradiction that the "std::try-emplace" can NOT also call the constructor of MyClass.
The compiler reports: "error: ‘MyClass::MyClass(int)’ is private within this context".

So I tried the solution 2:

```<code>class MyClass {
public:
   // methods of the class
   static const MyClass & findObject( int iKey ) {
      if ( mapObjects.find( iKey ) == mapObjects.cend() )
         mapObjects[iKey] = MyClass( iKey );

      return mapObjects[iKey];
   };

   // deleted
   MyClass() = delete;
   MyClass( MyClass & ) = delete;
   MyClass( MyClass && ) = delete;
   MyClass( const MyClass & ) = delete;
   MyClass( const MyClass && ) = delete;
   MyClass & operator=( MyClass & ) = delete;
   MyClass & operator=( const MyClass & ) = delete;
   MyClass & operator=( const MyClass && ) = delete;

private:
   // vars of the class
   static map<int, MyClass> mapObjects;

   // vars of instance
   string some_heavy_payload;

   // methods of instance
   MyClass( int iKey ) {
      some_heavy_payload = std::to_string( iKey );
   };
   MyClass & operator=( MyClass && src ) {
      some_heavy_payload = std::move( src.some_heavy_payload );
      return *this;
   };
};

map<int, MyClass> MyClass::mapObjects;

int main() {
   const MyClass & obj = MyClass::findObject( 1 );

   return EXIT_SUCCESS;
};
</code>```

This time I got a error: "use of deleted function ‘MyClass::MyClass()’".
I guess that is resulted by "[]" operator of std::map, because it tries to call the default constructor of MyClass.

How can I get it done?

答:
If you want to lock creation down, simply pass a key to everyone allowed in!</p>

```<code>class MyClass {
    class Key {
        Key() = default;
        friend class MyClass;
    };
    MyClass(MyClass const&) = delete;
    MyClass& operator=(MyClass const&) = delete;
    static map<int, MyClass> mapObjects;
public:
    static MyClass const& findObject(int iKey) {
        auto [iter, created] = mapObjects.try_emplace(iKey, Key(), iKey );
        if (created)
            std::cout << "New object has been created\n";
        return iter->second;
    };

    MyClass(Key, int iKey)
    : some_heavy_payload(std::to_string(iKey))
    {}
private:
    string some_heavy_payload;
};
</code>```

Body:
I have a class, that has very heavy payload, so that it is very expensive to create/copy/move an instance of this class.
Since they will not change after the app has finished initialization, there is no need to create temporary objects of this class anywere. I only need to cache objects in a container(std::map), and offer a "const reference" when needed.

The thing that must be emphasized is that I'm seeking a solution which can avoid double-create or unnecessary copy a object before add it into the container(I don't think a solution likes one @getsoubl proposed can resolve the problem, because it does not eliminate doulbe-creating or unnecessary copying).

So I want to arrange the constructor method into "private/protected" section of the class body, so as to forbid any of creating/copying/moving outside of the "Factory-Method". Following is my original solution:

class MyClass {
public:
   // methods of the class
   static const MyClass & findObject( int iKey ) {
      auto pair = mapObjects.try_emplace( iKey, iKey );
      if ( pair.second )
         cout << "New object has been created" << endl;

      return pair.first->second;
   };

   // deleted
   MyClass() = delete;
   MyClass( MyClass & ) = delete;
   MyClass( MyClass && ) = delete;
   MyClass( const MyClass & ) = delete;
   MyClass( const MyClass && ) = delete;
   MyClass & operator=( MyClass & ) = delete;
   MyClass & operator=( MyClass && ) = delete;
   MyClass & operator=( const MyClass & ) = delete;
   MyClass & operator=( const MyClass && ) = delete;

private:
   // vars of the class
   static map<int, MyClass> mapObjects;

   // vars of instance
   string some_heavy_payload;

   // methods of instance
   MyClass( int iKey ) :
     some_heavy_payload( std::to_string( iKey ) ) {};
};

map<int, MyClass> MyClass::mapObjects;

int main() {
   const MyClass & obj = MyClass::findObject( 1 );
   return EXIT_SUCCESS;
};

But I'm put into a contradiction that the "std::try-emplace" can NOT also call the constructor of MyClass.
The compiler reports: "error: ‘MyClass::MyClass(int)’ is private within this context".

So I tried the solution 2:

class MyClass {
public:
   // methods of the class
   static const MyClass & findObject( int iKey ) {
      if ( mapObjects.find( iKey ) == mapObjects.cend() )
         mapObjects[iKey] = MyClass( iKey );

      return mapObjects[iKey];
   };

   // deleted
   MyClass() = delete;
   MyClass( MyClass & ) = delete;
   MyClass( MyClass && ) = delete;
   MyClass( const MyClass & ) = delete;
   MyClass( const MyClass && ) = delete;
   MyClass & operator=( MyClass & ) = delete;
   MyClass & operator=( const MyClass & ) = delete;
   MyClass & operator=( const MyClass && ) = delete;

private:
   // vars of the class
   static map<int, MyClass> mapObjects;

   // vars of instance
   string some_heavy_payload;

   // methods of instance
   MyClass( int iKey ) {
      some_heavy_payload = std::to_string( iKey );
   };
   MyClass & operator=( MyClass && src ) {
      some_heavy_payload = std::move( src.some_heavy_payload );
      return *this;
   };
};

map<int, MyClass> MyClass::mapObjects;

int main() {
   const MyClass & obj = MyClass::findObject( 1 );

   return EXIT_SUCCESS;
};

This time I got a error: "use of deleted function ‘MyClass::MyClass()’".
I guess that is resulted by "[]" operator of std::map, because it tries to call the default constructor of MyClass.

How can I get it done?

Body:
If you want to lock creation down, simply pass a key to everyone allowed in!

class MyClass {
    class Key {
        Key() = default;
        friend class MyClass;
    };
    MyClass(MyClass const&) = delete;
    MyClass& operator=(MyClass const&) = delete;
    static map<int, MyClass> mapObjects;
public:
    static MyClass const& findObject(int iKey) {
        auto [iter, created] = mapObjects.try_emplace(iKey, Key(), iKey );
        if (created)
            std::cout << "New object has been created\n";
        return iter->second;
    };

    MyClass(Key, int iKey)
    : some_heavy_payload(std::to_string(iKey))
    {}
private:
    string some_heavy_payload;
};


问:
Filter top n largest groups in data.frame
For the example data:

```<code>set.seed(2222)
example_data <- data.frame(col1 = 1:15,
                           col2 = 16:30,
                           group = sample(1:3, 15, replace = TRUE))

   col1 col2 group
1     1   16     2
2     2   17     1
3     3   18     3
4     4   19     2
5     5   20     3
6     6   21     1
7     7   22     3
8     8   23     1
9     9   24     3
10   10   25     1
11   11   26     2
12   12   27     2
13   13   28     2
14   14   29     3
15   15   30     3
</code>```

I want to find the top n groups with the most number of records.

Let's say I want to get the top 2 groups with the most number of records. In the data, this would be group 3 and 2:

```<code>example_data %>%
  group_by(group) %>%
  summarise(n = n())

# A tibble: 3 x 2
  group     n
  <int> <int>
1     1     4
2     2     5
3     3     6
</code>```

The expected output is:

```<code>   col1 col2 group
1     1   16     2
2     3   18     3
3     4   19     2
4     5   20     3
5     7   22     3
6     9   24     3
7    11   26     2
8    12   27     2
9    13   28     2
10   14   29     3
11   15   30     3
</code>```

答:
We can use table to calculate frequency for each group, sort them in decreasing order, subset the top 2 entries and filter the respective groups.

```<code>library(dplyr)

example_data %>%
   filter(group %in% names(sort(table(group), decreasing = TRUE)[1:2]))

#   col1 col2 group
#1     1   16     2
#2     3   18     3
#3     4   19     2
#4     5   20     3
#5     7   22     3
#6     9   24     3
#7    11   26     2
#8    12   27     2
#9    13   28     2
#10   14   29     3
#11   15   30     3
</code>```

Also you can directly use this in base R subset

```<code>subset(example_data, group %in% names(sort(table(group), decreasing = TRUE)[1:2]))
</code>```

Body:
For the example data:

set.seed(2222)
example_data <- data.frame(col1 = 1:15,
                           col2 = 16:30,
                           group = sample(1:3, 15, replace = TRUE))

   col1 col2 group
1     1   16     2
2     2   17     1
3     3   18     3
4     4   19     2
5     5   20     3
6     6   21     1
7     7   22     3
8     8   23     1
9     9   24     3
10   10   25     1
11   11   26     2
12   12   27     2
13   13   28     2
14   14   29     3
15   15   30     3

I want to find the top n groups with the most number of records.

Let's say I want to get the top 2 groups with the most number of records. In the data, this would be group 3 and 2:

example_data %>%
  group_by(group) %>%
  summarise(n = n())

# A tibble: 3 x 2
  group     n
  <int> <int>
1     1     4
2     2     5
3     3     6

The expected output is:

   col1 col2 group
1     1   16     2
2     3   18     3
3     4   19     2
4     5   20     3
5     7   22     3
6     9   24     3
7    11   26     2
8    12   27     2
9    13   28     2
10   14   29     3
11   15   30     3

Body:
We can use table to calculate frequency for each group, sort them in decreasing order, subset the top 2 entries and filter the respective groups.

library(dplyr)

example_data %>%
   filter(group %in% names(sort(table(group), decreasing = TRUE)[1:2]))

#   col1 col2 group
#1     1   16     2
#2     3   18     3
#3     4   19     2
#4     5   20     3
#5     7   22     3
#6     9   24     3
#7    11   26     2
#8    12   27     2
#9    13   28     2
#10   14   29     3
#11   15   30     3

Also you can directly use this in base R subset

subset(example_data, group %in% names(sort(table(group), decreasing = TRUE)[1:2]))


问:
Store if and else expression in database and execute the expression in javascript or node.js. How to achieve this?
I want to store an expression in database and execute it in node.js. how i will achieve this? please help.

stored expression is below:

```<code>if(10>15){return 0;}else{return 1;}
</code>```

答:
If you do not want to use eval, you can create a Function instance as below.</p>

```<code>var myFuncString = "if(10>15){return 0;}else{return 'santosh';}"
var myfunc = new Function(myFuncString);
myfunc();
</code>```

Body:
I want to store an expression in database and execute it in node.js. how i will achieve this? please help.

stored expression is below:

if(10>15){return 0;}else{return 1;}

Body:
If you do not want to use eval, you can create a Function instance as below.

var myFuncString = "if(10>15){return 0;}else{return 'santosh';}"
var myfunc = new Function(myFuncString);
myfunc();


问:
getline() doesn't read accented characters correctly
I'm trying to get accented characters from user using getline() command, but it does not print them correctly.

I tried to include some libraries as locale, but it was in vain.

Here's my code:

```<code>#include <iostream>
#include <cstdlib>
#include <string>
#include <locale>

using namespace std;

class Pers {
public:
    string name;
    int age;
    string weapon;
};

int main()
{
    setlocale(LC_ALL, "");
    Pers pers;

    cout << "Say the name of your character: ";
    getline(cin, pers.name);
    cout << pers.name;
}
</code>```

When I type: Mark Coração, this is what I get:

How do I fix it?

答:
There are 2 levels in a same problem. The problem is that you are using characters outside the ASCII charset. The 2 levels are:

how they are converted to narrow characters on input

how they will be displayed on output

Windows console is a rather disturbing application in that respect: it is able to internaly process UCS2 characters that is any unicode character in the Basic Multilingual Plane, said differently any character with a code point of at most 0xFFFF. On input into narrow characters, it tries to map any character not represented in the current charset to what it thinks is closer, on output, it just outputs the value of each byte in its current charset. So the most reliable way is to ensure that the current locale has a correct collating sequence and that the console has a correct code page (charset in Windows language). After seeing the displayed output, I assume that you are using the code page 437 which contains semi-graphics character but few non ascii ones.

As you only need Western European characters, I would advise you to use the code page 1252. It is a Windows variant of the standard Latin1 or ISO-8859-1 charset (characters with codepoint of at most 0xFF).

So if possible you should try to configure the system in a non english  west eurapean language (Portugues would be fine, but French seems to be enough, so I would assume that Spanish would go too).

And you must configure the console in an correct code page: chcp 1252.

If it is not enough (I cannot currently test anything), you could try to use wide character (wstring, wcin, wcout). But without changing code page from 437, the console would not display accented character.

Body:
I'm trying to get accented characters from user using getline() command, but it does not print them correctly.

I tried to include some libraries as locale, but it was in vain.

Here's my code:

#include <iostream>
#include <cstdlib>
#include <string>
#include <locale>

using namespace std;

class Pers {
public:
    string name;
    int age;
    string weapon;
};

int main()
{
    setlocale(LC_ALL, "");
    Pers pers;

    cout << "Say the name of your character: ";
    getline(cin, pers.name);
    cout << pers.name;
}

When I type: Mark Coração, this is what I get:

How do I fix it?