问:
How to create an instance method based on this object data?
I have some data inside this variable and I want to know how could I write an method to give me the sum of the items price.

Model names and their associations:

```<code>Order
- belongs_to :customer
- has_many :item_orders
- has_many :items, :through => :item_orders
- accepts_nested_attributes_for :item_orders, :allow_destroy => true, :reject_if => lambda { |a| a['item_id'].blank? }

Item
- has_many :item_orders, :dependent => :destroy
- has_many :orders, :through => :item_orders
- accepts_nested_attributes_for :item_orders, :allow_destroy => true

ItemOrder
- belongs_to :item
- belongs_to :order
</code>```

doing:

```<code><%= debug @order.items %>

# returns me

- !ruby/object:Item
  attributes:
  id: 31
  title: Golden Ring 2
  price: 13445.0
  labour_cost: 500.0
  item_type_id: 10
  created_at: 2011-08-13 10:53:24.000000000Z
  updated_at: 2011-08-18 06:10:36.000000000Z
  photo: golden_ring.jpg
  changed_attributes: {}
  previously_changed: {}
  attributes_cache: {}
  marked_for_destruction: false
  destroyed: false
  readonly: false
  new_record: false
- !ruby/object:Item
 attributes:
  id: 32
  title: Special Pendant
  price: 171.67
  labour_cost: 120.0
  item_type_id: 20
  created_at: 2011-08-13 11:09:43.000000000Z
  updated_at: 2011-08-14 06:03:02.000000000Z
  photo: prd_194_48cd9b21771dd.jpg
  changed_attributes: {}
  previously_changed: {}
  attributes_cache: {}
  marked_for_destruction: false
  destroyed: false
  readonly: false
  new_record: false
</code>```

So, I want to write a method in the Order model class to make possible writes something like this on the view.

```<code> <%= @order.items.total_price %>
</code>```

The total_price method will sum all the item prices and multiply by the quantity that contains in @order.items.

My doubt is: from inside the method, how could I have access to the items collection to perform the sum operation.

```<code>def total_price
  self.item_order.each do |i| {
     result += i.quantity * i.items.price
  }
end
</code>```

EDIT: I totally forgot to mention that I have to consider the quantity also to make this math.

答: <%= @order.items.inject(0) {|sum, item| sum + item.price} %>

Body:
I have some data inside this variable and I want to know how could I write an method to give me the sum of the items price.

Model names and their associations:

Order
- belongs_to :customer
- has_many :item_orders
- has_many :items, :through => :item_orders
- accepts_nested_attributes_for :item_orders, :allow_destroy => true, :reject_if => lambda { |a| a['item_id'].blank? }

Item
- has_many :item_orders, :dependent => :destroy
- has_many :orders, :through => :item_orders
- accepts_nested_attributes_for :item_orders, :allow_destroy => true

ItemOrder
- belongs_to :item
- belongs_to :order

doing:

<%= debug @order.items %>

# returns me

- !ruby/object:Item
  attributes:
  id: 31
  title: Golden Ring 2
  price: 13445.0
  labour_cost: 500.0
  item_type_id: 10
  created_at: 2011-08-13 10:53:24.000000000Z
  updated_at: 2011-08-18 06:10:36.000000000Z
  photo: golden_ring.jpg
  changed_attributes: {}
  previously_changed: {}
  attributes_cache: {}
  marked_for_destruction: false
  destroyed: false
  readonly: false
  new_record: false
- !ruby/object:Item
 attributes:
  id: 32
  title: Special Pendant
  price: 171.67
  labour_cost: 120.0
  item_type_id: 20
  created_at: 2011-08-13 11:09:43.000000000Z
  updated_at: 2011-08-14 06:03:02.000000000Z
  photo: prd_194_48cd9b21771dd.jpg
  changed_attributes: {}
  previously_changed: {}
  attributes_cache: {}
  marked_for_destruction: false
  destroyed: false
  readonly: false
  new_record: false

So, I want to write a method in the Order model class to make possible writes something like this on the view.

 <%= @order.items.total_price %>

The total_price method will sum all the item prices and multiply by the quantity that contains in @order.items.

My doubt is: from inside the method, how could I have access to the items collection to perform the sum operation.

def total_price
  self.item_order.each do |i| {
     result += i.quantity * i.items.price
  }
end

EDIT: I totally forgot to mention that I have to consider the quantity also to make this math.


来源: stackexchange

答:
You can get the idxmin/idxmax per group, then use the values to slice the original dataset:

```<code># get the indices of min/max per group, then flatten as array
idx = df.groupby('user_id')['datetime'].agg(['idxmin', 'idxmax']).values.ravel()
# array([0, 4, 5, 8])

# slice
df.loc[idx]
</code>```

output:

```<code>        user_id  length            datetime
0  d8366132199       20 2021-03-31 17:55:44
4  d8366132199       80 2021-06-28 18:55:49
5  e8172920273       10 2021-03-28 18:55:44
8  e8172920273       90 2021-05-26 18:55:47
</code>```

ContentLicense: CC BY-SA 4.0

Title: Get rows of first and last datetime records based on a column

Body:
I have a df with several columns and can't figure out in Python how to get only the rows with the first and last date/time (columns is in pandas datetime64[ns] Dtype) entry for each id. And also how to create a new df with the datetime difference in days?

Here's a df slice:

user_id
length
datetime

d8366132199
20
2021-03-31 17:55:44

d8366132199
40
2021-05-12 13:55:48

d8366132199
10
2021-04-09 16:55:47

d8366132199
70
2021-06-25 17:58:47

d8366132199
80
2021-06-28 18:55:49

e8172920273
10
2021-03-28 18:55:44

e8172920273
50
2021-03-30 18:55:45

e8172920273
60
2021-05-26 18:55:46

e8172920273
90
2021-05-26 18:55:47

Expected output:

user_id
length
datetime

d8366132199
20
2021-03-31 17:55:44

d8366132199
80
2021-06-28 18:55:49

e8172920273
10
2021-03-28 18:55:44

e8172920273
90
2021-05-26 18:55:47

New df with datetime difference, expected output:

user_id
date_diff

d8366132199
276

e8172920273
60

Many thanks!

Body:
You can get the idxmin/idxmax per group, then use the values to slice the original dataset:

# get the indices of min/max per group, then flatten as array
idx = df.groupby('user_id')['datetime'].agg(['idxmin', 'idxmax']).values.ravel()
# array([0, 4, 5, 8])

# slice
df.loc[idx]

output:

        user_id  length            datetime
0  d8366132199       20 2021-03-31 17:55:44
4  d8366132199       80 2021-06-28 18:55:49
5  e8172920273       10 2021-03-28 18:55:44
8  e8172920273       90 2021-05-26 18:55:47


问:
Using sql:column function in xpath in values method
I have two tables:

One called @settings with xml values

Another called @nodesToFind with a list of nodes to extract from the xml values in the first table

I want to get a list of the values for each NodePath for each RowId.

This query uses the sql:column function in the xpath of the values method on the Settings column but it returns the NodePath itself instead of the value:

```<code>declare @settings table (RowId int identity, Settings xml)
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>1-1a1</Setting1a1></Settings1a><Setting1b>1-1b</Setting1b><Setting1c>1-1c</Setting1c></Settings1><Settings2><Setting2a>1-2a</Setting2a></Settings2></settings>')
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>2-1a1</Setting1a1></Settings1a><Setting1b>2-1b</Setting1b><Setting1c>2-1c</Setting1c></Settings1><Settings2><Setting2a>2-2a</Setting2a></Settings2></settings>')
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>3-1a1</Setting1a1></Settings1a><Setting1b>3-1b</Setting1b><Setting1c>3-1c</Setting1c></Settings1><Settings2><Setting2a>3-2a</Setting2a></Settings2></settings>')

declare @nodesToFind table (NodePath varchar(max))
insert @nodesToFind (NodePath) values ('/Settings/Settings1/Settings1a/Setting1a1')
insert @nodesToFind (NodePath) values ('/Settings/Settings1/Setting1b')
insert @nodesToFind (NodePath) values ('/Settings/Settings1/Setting1c')
insert @nodesToFind (NodePath) values ('/Settings/Settings2/Setting2a')

select
    S.RowId,
    NTF.NodePath,
    S.Settings.value('(sql:column("NodePath"))[1]', 'varchar(max)')
from @settings S
cross apply @nodesToFind NTF
</code>```

The result is this:

```<code>RowId  NodePath                                   Value
-----  -----------------------------------------  -----------------------------------------
1      /Settings/Settings1/Settings1a/Setting1a1  /Settings/Settings1/Settings1a/Setting1a1
2      /Settings/Settings1/Settings1a/Setting1a1  /Settings/Settings1/Settings1a/Setting1a1
3      /Settings/Settings1/Settings1a/Setting1a1  /Settings/Settings1/Settings1a/Setting1a1
1      /Settings/Settings1/Setting1b              /Settings/Settings1/Setting1b
2      /Settings/Settings1/Setting1b              /Settings/Settings1/Setting1b
3      /Settings/Settings1/Setting1b              /Settings/Settings1/Setting1b
1      /Settings/Settings1/Setting1c              /Settings/Settings1/Setting1c
2      /Settings/Settings1/Setting1c              /Settings/Settings1/Setting1c
3      /Settings/Settings1/Setting1c              /Settings/Settings1/Setting1c
1      /Settings/Settings2/Setting2a              /Settings/Settings2/Setting2a
2      /Settings/Settings2/Setting2a              /Settings/Settings2/Setting2a
3      /Settings/Settings2/Setting2a              /Settings/Settings2/Setting2a
</code>```

What is wrong with the S.Settings.value('(sql:column("NodePath"))[1]', 'varchar(max)') line?

答:
The XQuery you are trying to use is effectively being run dynaimcally. Unfortunately, you cannot use dynamic XQuery in SQL Server. Each XQuery must be static.

What you could do in your specific situation, is to break up each node predicate into separate columns. Then in the XQuery you can descend to the relevant node by checking each column. For example:

declare @settings table (RowId int identity, Settings xml)
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>1-1a1</Setting1a1></Settings1a><Setting1b>1-1b</Setting1b><Setting1c>1-1c</Setting1c></Settings1><Settings2><Setting2a>1-2a</Setting2a></Settings2></settings>')
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>2-1a1</Setting1a1></Settings1a><Setting1b>2-1b</Setting1b><Setting1c>2-1c</Setting1c></Settings1><Settings2><Setting2a>2-2a</Setting2a></Settings2></settings>')
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>3-1a1</Setting1a1></Settings1a><Setting1b>3-1b</Setting1b><Setting1c>3-1c</Setting1c></Settings1><Settings2><Setting2a>3-2a</Setting2a></Settings2></settings>')

declare @nodesToFind table (NodePath1 nvarchar(max), NodePath2 nvarchar(max), NodePath3 nvarchar(max), NodePath4 nvarchar(max))
insert @nodesToFind (NodePath1, NodePath2, NodePath3, NodePath4) values ('settings','Settings1','Settings1a','Setting1a1')
insert @nodesToFind (NodePath1, NodePath2, NodePath3, NodePath4) values ('settings','Settings1','Setting1b',null)
insert @nodesToFind (NodePath1, NodePath2, NodePath3, NodePath4) values ('settings','Settings1','Setting1c',null)
insert @nodesToFind (NodePath1, NodePath2, NodePath3, NodePath4) values ('settings','Settings2','Setting2a',null)

select
    S.RowId,
    NTF.*,
    S.Settings.value('((
        for $i1 in *[local-name() = sql:column("NodePath1")]
        return
            if (empty(sql:column("NodePath2")))
            then $i1
            else for $i2 in ($i1/*[local-name() = sql:column("NodePath2")])
                 return
                     if (empty(sql:column("NodePath3")))
                     then $i2
                     else for $i3 in $i2/*[local-name() = sql:column("NodePath3")]
                          return
                              if (empty(sql:column("NodePath4")))
                              then $i3
                              else $i3/*[local-name() = sql:column("NodePath4")]
    )/text())[1]', 'varchar(max)')
from @settings S
cross join @nodesToFind NTF
```

db<>fiddle

As you can see, it is made significantly more complex (and probably slow) by the fact that there are multiple possible node levels. If you can restrict it to only one level of node then you can remove the if else sections.

Body:
I have two tables:

One called @settings with xml values

Another called @nodesToFind with a list of nodes to extract from the xml values in the first table

I want to get a list of the values for each NodePath for each RowId.

This query uses the sql:column function in the xpath of the values method on the Settings column but it returns the NodePath itself instead of the value:

declare @settings table (RowId int identity, Settings xml)
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>1-1a1</Setting1a1></Settings1a><Setting1b>1-1b</Setting1b><Setting1c>1-1c</Setting1c></Settings1><Settings2><Setting2a>1-2a</Setting2a></Settings2></settings>')
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>2-1a1</Setting1a1></Settings1a><Setting1b>2-1b</Setting1b><Setting1c>2-1c</Setting1c></Settings1><Settings2><Setting2a>2-2a</Setting2a></Settings2></settings>')
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>3-1a1</Setting1a1></Settings1a><Setting1b>3-1b</Setting1b><Setting1c>3-1c</Setting1c></Settings1><Settings2><Setting2a>3-2a</Setting2a></Settings2></settings>')

declare @nodesToFind table (NodePath varchar(max))
insert @nodesToFind (NodePath) values ('/Settings/Settings1/Settings1a/Setting1a1')
insert @nodesToFind (NodePath) values ('/Settings/Settings1/Setting1b')
insert @nodesToFind (NodePath) values ('/Settings/Settings1/Setting1c')
insert @nodesToFind (NodePath) values ('/Settings/Settings2/Setting2a')

select
    S.RowId,
    NTF.NodePath,
    S.Settings.value('(sql:column("NodePath"))[1]', 'varchar(max)')
from @settings S
cross apply @nodesToFind NTF

The result is this:

RowId  NodePath                                   Value
-----  -----------------------------------------  -----------------------------------------
1      /Settings/Settings1/Settings1a/Setting1a1  /Settings/Settings1/Settings1a/Setting1a1
2      /Settings/Settings1/Settings1a/Setting1a1  /Settings/Settings1/Settings1a/Setting1a1
3      /Settings/Settings1/Settings1a/Setting1a1  /Settings/Settings1/Settings1a/Setting1a1
1      /Settings/Settings1/Setting1b              /Settings/Settings1/Setting1b
2      /Settings/Settings1/Setting1b              /Settings/Settings1/Setting1b
3      /Settings/Settings1/Setting1b              /Settings/Settings1/Setting1b
1      /Settings/Settings1/Setting1c              /Settings/Settings1/Setting1c
2      /Settings/Settings1/Setting1c              /Settings/Settings1/Setting1c
3      /Settings/Settings1/Setting1c              /Settings/Settings1/Setting1c
1      /Settings/Settings2/Setting2a              /Settings/Settings2/Setting2a
2      /Settings/Settings2/Setting2a              /Settings/Settings2/Setting2a
3      /Settings/Settings2/Setting2a              /Settings/Settings2/Setting2a

What is wrong with the S.Settings.value('(sql:column("NodePath"))[1]', 'varchar(max)') line?

Body:
The XQuery you are trying to use is effectively being run dynaimcally. Unfortunately, you cannot use dynamic XQuery in SQL Server. Each XQuery must be static.

What you could do in your specific situation, is to break up each node predicate into separate columns. Then in the XQuery you can descend to the relevant node by checking each column. For example:

declare @settings table (RowId int identity, Settings xml)
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>1-1a1</Setting1a1></Settings1a><Setting1b>1-1b</Setting1b><Setting1c>1-1c</Setting1c></Settings1><Settings2><Setting2a>1-2a</Setting2a></Settings2></settings>')
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>2-1a1</Setting1a1></Settings1a><Setting1b>2-1b</Setting1b><Setting1c>2-1c</Setting1c></Settings1><Settings2><Setting2a>2-2a</Setting2a></Settings2></settings>')
insert @settings (Settings) values ('<settings><Settings1><Settings1a><Setting1a1>3-1a1</Setting1a1></Settings1a><Setting1b>3-1b</Setting1b><Setting1c>3-1c</Setting1c></Settings1><Settings2><Setting2a>3-2a</Setting2a></Settings2></settings>')

declare @nodesToFind table (NodePath1 nvarchar(max), NodePath2 nvarchar(max), NodePath3 nvarchar(max), NodePath4 nvarchar(max))
insert @nodesToFind (NodePath1, NodePath2, NodePath3, NodePath4) values ('settings','Settings1','Settings1a','Setting1a1')
insert @nodesToFind (NodePath1, NodePath2, NodePath3, NodePath4) values ('settings','Settings1','Setting1b',null)
insert @nodesToFind (NodePath1, NodePath2, NodePath3, NodePath4) values ('settings','Settings1','Setting1c',null)
insert @nodesToFind (NodePath1, NodePath2, NodePath3, NodePath4) values ('settings','Settings2','Setting2a',null)

select
    S.RowId,
    NTF.*,
    S.Settings.value('((
        for $i1 in *[local-name() = sql:column("NodePath1")]
        return
            if (empty(sql:column("NodePath2")))
            then $i1
            else for $i2 in ($i1/*[local-name() = sql:column("NodePath2")])
                 return
                     if (empty(sql:column("NodePath3")))
                     then $i2
                     else for $i3 in $i2/*[local-name() = sql:column("NodePath3")]
                          return
                              if (empty(sql:column("NodePath4")))
                              then $i3
                              else $i3/*[local-name() = sql:column("NodePath4")]
    )/text())[1]', 'varchar(max)')
from @settings S
cross join @nodesToFind NTF

db<>fiddle

As you can see, it is made significantly more complex (and probably slow) by the fact that there are multiple possible node levels. If you can restrict it to only one level of node then you can remove the if else sections.


问:
Add Plugin to Kibana in docker-compose.yml
I have to add the Vega plugin to kibana. I am using docker-compose for it.

This is original source of docker-compose.yml.

```<code>version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic

  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic

  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic

  kib01:
    image: docker.elastic.co/kibana/kibana:7.16.3
    container_name: kib01
    ports:
      - 5601:5601
    environment:
      ELASTICSEARCH_URL: http://es01:9200
      ELASTICSEARCH_HOSTS: '["http://es01:9200","http://es02:9200","http://es03:9200"]'
    networks:
      - elastic

volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local

networks:
  elastic:
    driver: bridge
</code>```

This is working well.

And I added the following command to kibana image. I've found this article while several times of exploring.

```<code>command: sh -c './bin/kibana-plugin install https://github.com/nyurik/kibana-vega-vis/releases/download/v1.2.0/vega_vis-1.2.0--for-Kibana-6.2.0.zip && exec /usr/local/bin/kibana-docker'
</code>```

The result is the following.

```<code>version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic

  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic

  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic

  kib01:
    image: docker.elastic.co/kibana/kibana:7.16.3
    container_name: kib01
    command: sh -c './bin/kibana-plugin install https://github.com/nyurik/kibana-vega-vis/releases/download/v1.2.0/vega_vis-1.2.0--for-Kibana-6.2.0.zip && exec /usr/local/bin/kibana-docker'
    ports:
      - 5601:5601
    environment:
      ELASTICSEARCH_URL: http://es01:9200
      ELASTICSEARCH_HOSTS: '["http://es01:9200","http://es02:9200","http://es03:9200"]'
    networks:
      - elastic

volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local

networks:
  elastic:
    driver: bridge
</code>```

This is not working. Here is the result.

Also, http://localhost:5601 is not running.

How can I add the vega plugin to kibana image?

答:
Build your own Kibana docker image on top of the official one

Here is Elastic's version: https://github.com/elastic/dockerfiles/blob/8.0/kibana/Dockerfile

It will be something like:

```<code>FROM docker.elastic.co/elasticsearch/elasticsearch:7.16.3
COPY /path/to/vega_vis-1.2.0--for-Kibana-6.2.0.zip /some/path
RUN sh -c '/some/path/bin/kibana-plugin install...
</code>```

and then

docker build -t my_awesome_kibana .

Body:
I have to add the Vega plugin to kibana. I am using docker-compose for it.

This is original source of docker-compose.yml.

version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic

  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic

  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic

  kib01:
    image: docker.elastic.co/kibana/kibana:7.16.3
    container_name: kib01
    ports:
      - 5601:5601
    environment:
      ELASTICSEARCH_URL: http://es01:9200
      ELASTICSEARCH_HOSTS: '["http://es01:9200","http://es02:9200","http://es03:9200"]'
    networks:
      - elastic

volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local

networks:
  elastic:
    driver: bridge

This is working well.

And I added the following command to kibana image. I've found this article while several times of exploring.

command: sh -c './bin/kibana-plugin install https://github.com/nyurik/kibana-vega-vis/releases/download/v1.2.0/vega_vis-1.2.0--for-Kibana-6.2.0.zip && exec /usr/local/bin/kibana-docker'

The result is the following.

version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic

  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic

  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic

  kib01:
    image: docker.elastic.co/kibana/kibana:7.16.3
    container_name: kib01
    command: sh -c './bin/kibana-plugin install https://github.com/nyurik/kibana-vega-vis/releases/download/v1.2.0/vega_vis-1.2.0--for-Kibana-6.2.0.zip && exec /usr/local/bin/kibana-docker'
    ports:
      - 5601:5601
    environment:
      ELASTICSEARCH_URL: http://es01:9200
      ELASTICSEARCH_HOSTS: '["http://es01:9200","http://es02:9200","http://es03:9200"]'
    networks:
      - elastic

volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local

networks:
  elastic:
    driver: bridge

This is not working. Here is the result.

Also, http://localhost:5601 is not running.

How can I add the vega plugin to kibana image?

Body:
Build your own Kibana docker image on top of the official one

Here is Elastic's version: https://github.com/elastic/dockerfiles/blob/8.0/kibana/Dockerfile

It will be something like:

FROM docker.elastic.co/elasticsearch/elasticsearch:7.16.3
COPY /path/to/vega_vis-1.2.0--for-Kibana-6.2.0.zip /some/path
RUN sh -c '/some/path/bin/kibana-plugin install...

and then

docker build -t my_awesome_kibana .


问:
How can I debug my add-in when WordEditor's Content property is crashing Outlook?
I have folder full of *.msg files saved from Outlook and I'm trying to convert them to Word.

There is a loop that loads each *.msg as MailItem and saves them.

    public static ConversionResult ConvertEmailsToWord(this Outlook.Application app, string source, string target)
    {
        var word = new Word.Application();

        var emailCounter = 0;
        var otherCounter = 0;

        var directoryTree = new PhysicalDirectoryTree();
        foreach (var node in directoryTree.Walk(source))
        {
            foreach (var fileName in node.FileNames)
            {
                var currentFile = Path.Combine(node.DirectoryName, fileName);
                var branch = Regex.Replace(node.DirectoryName, $"^{Regex.Escape(source)}", string.Empty).Trim('\\');

                Debug.Print($"Processing file: {currentFile}");

                // This is an email. Convert it to Word.
                if (Regex.IsMatch(fileName, @"\.msg$"))
                {
                    if (app.Session.OpenSharedItem(currentFile) is MailItem item)
                    {
                        if (item.SaveAs(word, Path.Combine(target, branch), fileName))
                        {
                            emailCounter++;
                        }
                        item.Close(SaveMode: OlInspectorClose.olDiscard);
                    }
                }
                // This is some other file. Copy it as is.
                else
                {
                    Directory.CreateDirectory(Path.Combine(target, branch));
                    File.Copy(currentFile, Path.Combine(target, branch, fileName), true);
                    otherCounter++;
                }
            }
        }

        word.Quit(SaveChanges: false);

        return new ConversionResult
        {
            EmailCount = emailCounter,
            OtherCount = otherCounter
        };
    }
```
<p>The save method looks likes this:</p>
<pre class="lang-cs prettyprint-override"><code>    public static bool SaveAs(this MailItem mail, Word.Application word, string path, string name)
    {
        Directory.CreateDirectory(path);

        name = Path.Combine(path, $"{Path.GetFileNameWithoutExtension(name)}.docx");
        if (File.Exists(name))
        {
            return false;
        }

        var copy = mail.GetInspector.WordEditor as Word.Document;
        copy.Content.Copy();

        var doc = word.Documents.Add();
        doc.Content.Paste();
        doc.SaveAs2(FileName: name);
        doc.Close();

        return true;
    }
</code>```

It works for most *.msg files but there are some that crash Outlook when I call copy.Content on a Word.Document.

I know you cannot tell me what is wrong with it (or maybe you do?) so I'd like to findit out by myself but the problem is that I am not able to catch the exception. Since a simple try\catch didn't work I tried it with AppDomain.CurrentDomain.UnhandledException this this didn't catch it either.

Are there any other ways to debug it?

The mail that doesn't let me get its content inside a loop doesn't cause any troubles when I open it in a new Outlook window and save it with the same method.

答: Do you actually need to use Inspector.WordEditor? You can save the message in a format supported by Word (such as MHTML) using OOM alone by calling MailItem.Save(..., olMHTML) and open the file in Word programmatically to save it in the DOCX format.

Body:
I have folder full of *.msg files saved from Outlook and I'm trying to convert them to Word.

There is a loop that loads each *.msg as MailItem and saves them.

    public static ConversionResult ConvertEmailsToWord(this Outlook.Application app, string source, string target)
    {
        var word = new Word.Application();

        var emailCounter = 0;
        var otherCounter = 0;

        var directoryTree = new PhysicalDirectoryTree();
        foreach (var node in directoryTree.Walk(source))
        {
            foreach (var fileName in node.FileNames)
            {
                var currentFile = Path.Combine(node.DirectoryName, fileName);
                var branch = Regex.Replace(node.DirectoryName, $"^{Regex.Escape(source)}", string.Empty).Trim('\\');

                Debug.Print($"Processing file: {currentFile}");

                // This is an email. Convert it to Word.
                if (Regex.IsMatch(fileName, @"\.msg$"))
                {
                    if (app.Session.OpenSharedItem(currentFile) is MailItem item)
                    {
                        if (item.SaveAs(word, Path.Combine(target, branch), fileName))
                        {
                            emailCounter++;
                        }
                        item.Close(SaveMode: OlInspectorClose.olDiscard);
                    }
                }
                // This is some other file. Copy it as is.
                else
                {
                    Directory.CreateDirectory(Path.Combine(target, branch));
                    File.Copy(currentFile, Path.Combine(target, branch, fileName), true);
                    otherCounter++;
                }
            }
        }

        word.Quit(SaveChanges: false);

        return new ConversionResult
        {
            EmailCount = emailCounter,
            OtherCount = otherCounter
        };
    }

The save method looks likes this:

    public static bool SaveAs(this MailItem mail, Word.Application word, string path, string name)
    {
        Directory.CreateDirectory(path);

        name = Path.Combine(path, $"{Path.GetFileNameWithoutExtension(name)}.docx");
        if (File.Exists(name))
        {
            return false;
        }

        var copy = mail.GetInspector.WordEditor as Word.Document;
        copy.Content.Copy();

        var doc = word.Documents.Add();
        doc.Content.Paste();
        doc.SaveAs2(FileName: name);
        doc.Close();

        return true;
    }

It works for most *.msg files but there are some that crash Outlook when I call copy.Content on a Word.Document.

I know you cannot tell me what is wrong with it (or maybe you do?) so I'd like to findit out by myself but the problem is that I am not able to catch the exception. Since a simple try\catch didn't work I tried it with AppDomain.CurrentDomain.UnhandledException this this didn't catch it either.

Are there any other ways to debug it?

The mail that doesn't let me get its content inside a loop doesn't cause any troubles when I open it in a new Outlook window and save it with the same method.


问:
How to assert Map contains Map with entry
I have a unit test that needs to check for a nested map value.  I can get my assertion to work by pulling out the entry and matching the underlying Map, but I was looking for a clear way to show what the assertion is doing.  Here is a very simplified test:

```<code>import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasEntry;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

public class MapContainsMapTest {
    @Test
    public void testMapHasMap() {
        Map<String, Object> outerMap = new HashMap<String, Object>();
        Map<String, Object> nestedMap = new HashMap<String, Object>();
        nestedMap.put("foo", "bar");
        outerMap.put("nested", nestedMap);

        // works but murky
        assertThat((Map<String, Object>) outerMap.get("nested"), hasEntry("foo", "bar"));
        // fails but clear
        assertThat(outerMap, hasEntry("nested", hasEntry("foo", "bar")));
    }
}
</code>```

It seems the problem is the outer map is being compared using hasEntry(K key, V value) while what I want to use is hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher).  I am not sure how to coerce the assertion to use the second form.

Thanks in advance.

答:
Try like this :</p>
```<code>        assertThat(nestedMap).contains(Map.entry("foo", "bar"));
        assertThat(outerMap).contains(Map.entry("nested", nestedMap));
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have a unit test that needs to check for a nested map value.  I can get my assertion to work by pulling out the entry and matching the underlying Map, but I was looking for a clear way to show what the assertion is doing.  Here is a very simplified test:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasEntry;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

public class MapContainsMapTest {
    @Test
    public void testMapHasMap() {
        Map<String, Object> outerMap = new HashMap<String, Object>();
        Map<String, Object> nestedMap = new HashMap<String, Object>();
        nestedMap.put("foo", "bar");
        outerMap.put("nested", nestedMap);

        // works but murky
        assertThat((Map<String, Object>) outerMap.get("nested"), hasEntry("foo", "bar"));
        // fails but clear
        assertThat(outerMap, hasEntry("nested", hasEntry("foo", "bar")));
    }
}

It seems the problem is the outer map is being compared using hasEntry(K key, V value) while what I want to use is hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher).  I am not sure how to coerce the assertion to use the second form.

Thanks in advance.

Body:
Try like this :

        assertThat(nestedMap).contains(Map.entry("foo", "bar"));
        assertThat(outerMap).contains(Map.entry("nested", nestedMap));


问:
ASP.NET MVC / JqGrid : Is the JSON Id processed and recoverable?
I'm using a JqGrid in multiselect mode and recover the user's selection. The JqGrid is defined as follow :

```<code>$("#StatusList").jqGrid({
         url: '@Url.Action("UpdateStatusList", "Inventory")',
         datatype: 'json',
         mtype: 'GET',
         colNames: ['Status', 'statusId'],
         colModel: [
          { name: 'Status', index: 'Status', align: 'left', sortable: false },
          { name: 'statusId', index: 'statusId', hidden: true}]
});
</code>```

I don't have any issue for all the communication between the server and the client. Everything works fine. But I feel like I am duplicating data when filling the JqGrid with this function that sends the JSON data :

```<code>  public ActionResult UpdateStatusList()
  {
     var jsonData = new
     {
        rows = (from status in DatabaseInMemory.WoodStatus.GetEntities()
                select new
                {
                   i = status.ID,
                   cell = new string[] { status.Name,
                              status.ID.ToString() }
                }).ToArray()
     };
     return Json(jsonData, JsonRequestBehavior.AllowGet);
  }
</code>```

As you can see the id is passed two times :
  - for the JSON Id.
  - for the hidden column that helps me recover the id from the grid.

Back to the client, the JSON Id is not hold in the selarrrow property. This property holds ids based on position in the grid. I'm using it to get the selected data, and recover the real ids.

Is JqGrid processes and hold the id passed through JSON data, or is it lost and an hidden column is always needed to keep track of the rows?

答: You should change i = status.ID to id = status.ID.

Body:
I'm using a JqGrid in multiselect mode and recover the user's selection. The JqGrid is defined as follow :

$("#StatusList").jqGrid({
         url: '@Url.Action("UpdateStatusList", "Inventory")',
         datatype: 'json',
         mtype: 'GET',
         colNames: ['Status', 'statusId'],
         colModel: [
          { name: 'Status', index: 'Status', align: 'left', sortable: false },
          { name: 'statusId', index: 'statusId', hidden: true}]
});

I don't have any issue for all the communication between the server and the client. Everything works fine. But I feel like I am duplicating data when filling the JqGrid with this function that sends the JSON data :

  public ActionResult UpdateStatusList()
  {
     var jsonData = new
     {
        rows = (from status in DatabaseInMemory.WoodStatus.GetEntities()
                select new
                {
                   i = status.ID,
                   cell = new string[] { status.Name,
                              status.ID.ToString() }
                }).ToArray()
     };
     return Json(jsonData, JsonRequestBehavior.AllowGet);
  }

As you can see the id is passed two times :
  - for the JSON Id.
  - for the hidden column that helps me recover the id from the grid.

Back to the client, the JSON Id is not hold in the selarrrow property. This property holds ids based on position in the grid. I'm using it to get the selected data, and recover the real ids.

Is JqGrid processes and hold the id passed through JSON data, or is it lost and an hidden column is always needed to keep track of the rows?


问:
How to use Python3.10 on Ubuntu?
I have installed Python 3.10 from deadsnakes on my Ubuntu 20.04 machine.

How to use it? python3 --version returns Python 3.8.10 and python3.10 -m venv venv returns error (I've installed python3-venv as well).

答: So I was having the exact same problem. I figured out that I actually had to run "sudo apt-get install python3.10-full" instead of just "sudo apt-get install python3.10". I was then able to create a python3.10 virtual environment by executing "python3.10 -m venv virt".</p>

Title: How to use Python3.10 on Ubuntu?


问:
Node.js MySQL - Error: connect ECONNREFUSED
I use Node.js server side. I tried my code on localhost and everything works fine. I bought a server and installed Apache and node.js on it and test my web application there. I correctly changed the MySQL connection configurations from localhost to the server configurations.

I test my web application with this configuration:

```<code>var mysql      = require('mysql');
var mysqlConnection;
function new_mysqlConnection() {
    mysqlConnection = mysql.createConnection({
      host     : 'myurl.at',
      user     : 'myusername',
      database : 'mydatabase',
      password : 'mypassword'
    });
}
</code>```

I start the node.js server with:

```<code>$ node server.js
</code>```

When I load the page, it's correctly displayed, but when Node.js try to connect to the database I always got the following error:

```<code>Error: connect ECONNREFUSED
    at errnoException (net.js:905:11)
    at Object.afterConnect [as oncomplete] (net.js:896:19)
    --------------------
    at Protocol._enqueue (/var/www/node_modules/mysql/lib/protocol/Protocol.js:135:48)
    at Protocol.handshake (/var/www/node_modules/mysql/lib/protocol/Protocol.js:52:41)
    at Connection.connect (/var/www/node_modules/mysql/lib/Connection.js:119:18)
    at reconnectDb (/var/www/server.js:319:18)
    at app.get.email (/var/www/server.js:109:2)
    at Layer.handle [as handle_request] (/var/www/node_modules/express/lib/router/layer.js:82:5)
    at trim_prefix (/var/www/node_modules/express/lib/router/index.js:302:13)
    at /var/www/node_modules/express/lib/router/index.js:270:7
    at Function.proto.process_params (/var/www/node_modules/express/lib/router/index.js:321:12)
    at next (/var/www/node_modules/express/lib/router/index.js:261:10)
</code>```

答:
if using using express and MySQL. port should be same as your MySQL port.

The default MySQL port is 3306.

```<code>let defaultPORT = 3306;
var express = require('express');
var app = express();
var mysql  = require('mysql');
var connection = mysql.createConnection({
    host     : 'localhost',
    user     : 'yourMYSQLUser',
    password : 'yourMYSQLPassword'
});
connection.connect();

connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
    if (error) throw error;
    console.log('The solution is: ', results[0].solution);
});

var server = app.listen( defaultPORT, function() {
    console.log( defaultPORT)
});
</code>```

Body:
I use Node.js server side. I tried my code on localhost and everything works fine. I bought a server and installed Apache and node.js on it and test my web application there. I correctly changed the MySQL connection configurations from localhost to the server configurations.

I test my web application with this configuration:

var mysql      = require('mysql');
var mysqlConnection;
function new_mysqlConnection() {
    mysqlConnection = mysql.createConnection({
      host     : 'myurl.at',
      user     : 'myusername',
      database : 'mydatabase',
      password : 'mypassword'
    });
}

I start the node.js server with:

$ node server.js

When I load the page, it's correctly displayed, but when Node.js try to connect to the database I always got the following error:

Error: connect ECONNREFUSED
    at errnoException (net.js:905:11)
    at Object.afterConnect [as oncomplete] (net.js:896:19)
    --------------------
    at Protocol._enqueue (/var/www/node_modules/mysql/lib/protocol/Protocol.js:135:48)
    at Protocol.handshake (/var/www/node_modules/mysql/lib/protocol/Protocol.js:52:41)
    at Connection.connect (/var/www/node_modules/mysql/lib/Connection.js:119:18)
    at reconnectDb (/var/www/server.js:319:18)
    at app.get.email (/var/www/server.js:109:2)
    at Layer.handle [as handle_request] (/var/www/node_modules/express/lib/router/layer.js:82:5)
    at trim_prefix (/var/www/node_modules/express/lib/router/index.js:302:13)
    at /var/www/node_modules/express/lib/router/index.js:270:7
    at Function.proto.process_params (/var/www/node_modules/express/lib/router/index.js:321:12)
    at next (/var/www/node_modules/express/lib/router/index.js:261:10)

Body:
if using using express and MySQL. port should be same as your MySQL port.

The default MySQL port is 3306.

let defaultPORT = 3306;
var express = require('express');
var app = express();
var mysql  = require('mysql');
var connection = mysql.createConnection({
    host     : 'localhost',
    user     : 'yourMYSQLUser',
    password : 'yourMYSQLPassword'
});
connection.connect();

connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
    if (error) throw error;
    console.log('The solution is: ', results[0].solution);
});

var server = app.listen( defaultPORT, function() {
    console.log( defaultPORT)
});


问:
ldap_bind always returning true
I'm attempting to implement LDAP user authentification however for some reason no matter what the input is, ldap_bind always returns true. Whether the input is gibberish, empty, or legitimate

```<code>$ds = ldap_connect($ldaphost)
      or die("Could not connect to $ds");

if($bind = ldap_bind($ds,$username, $password))
{
  // login successful
}
else {
  // error message
}
</code>```

any ideas?

note: using the code below produces the same issue:

```<code>$bind = ldap_bind($ds,$username, $password);

if($bind)
{
  // login successful
}
else {
  // error message
}
</code>```

Thanks in advance!

答:
Gagola, the function ldap_bind occurs at the server side. so once the webserver's os user binded to the ldap server, next queries return true.
the solution is simple as unbinding it just after binding it.
here is an example.</p>
```<code><?php
function ad_auth( $server, $username, $password ){
    $ldap = @ldap_connect( $server );
    if ( @ldap_bind( $ldap, $username, $password ) ){
            ldap_unbind( $ldap );
            return true;
            }
    else
            return false;
    }
?>
</code>```

Title: ldap_bind always returning true

Body:
I'm attempting to implement LDAP user authentification however for some reason no matter what the input is, ldap_bind always returns true. Whether the input is gibberish, empty, or legitimate

$ds = ldap_connect($ldaphost)
      or die("Could not connect to $ds");

if($bind = ldap_bind($ds,$username, $password))
{
  // login successful
}
else {
  // error message
}

any ideas?

note: using the code below produces the same issue:

$bind = ldap_bind($ds,$username, $password);

if($bind)
{
  // login successful
}
else {
  // error message
}

Thanks in advance!

Body:
Gagola, the function ldap_bind occurs at the server side. so once the webserver's os user binded to the ldap server, next queries return true.
the solution is simple as unbinding it just after binding it.
here is an example.

<?php
function ad_auth( $server, $username, $password ){
    $ldap = @ldap_connect( $server );
    if ( @ldap_bind( $ldap, $username, $password ) ){
            ldap_unbind( $ldap );
            return true;
            }
    else
            return false;
    }
?>


问:
Are there any downsides to choosing not to join threads in Rust?
I have a program that uses multiple threads to brute force the decryption of some encrypted string. The main thread has a channel, and the sender is cloned and sent to each thread. When a thread finds an answer, it sends it to the receiver which is in the main thread.

In this program I am not joining the threads, instead I use the blocking call sender.recv() to suspend the main thread until a single other thread finishes.

My hope is, once this call finishes, the main thread will return and all the other worker threads will be terminated.

Is this a poor design choice? Are there drawbacks of not having some  condition in the other threads which would cause them to return when the solution has been discovered? Is it okay/safe to rely on the compiler to clean up my threads before they've technically finished?

答:
Assuming there's no cleanup to be done, what you've done is mostly harmless. I'm assuming your worker thread looks something like this right now.

```<code>fn my_thread() {
  // ... lots of hard work ...
  channel.send(my_result);
}
</code>```

and if that's the case, then "I received the result" and "the other thread is terminated" are very similar events, and the difference of "this function returned" is probably irrelevant. But suppose someone comes along and changes the code to look like this.

```<code>fn my_thread() {
  // ... lots of hard work ...
  channel.send(my_result);
  do_cleanup_stuff();
}
</code>```

Now do_cleanup_stuff() might not get a chance to run, if your main thread terminates before my_thread does. If that cleanup function is important, that could cause problems. And it could be more subtle than that. If any local variable in my_thread holds a file handle or an open TCP stream or any other object with a nontrivial Drop implementation, that value may not get a chance to Drop properly if you don't join the thread.

So it's probably best practice to join everything, even if it's just a final step at the end of your main.

Body:
Assuming there's no cleanup to be done, what you've done is mostly harmless. I'm assuming your worker thread looks something like this right now.

fn my_thread() {
  // ... lots of hard work ...
  channel.send(my_result);
}

and if that's the case, then "I received the result" and "the other thread is terminated" are very similar events, and the difference of "this function returned" is probably irrelevant. But suppose someone comes along and changes the code to look like this.

fn my_thread() {
  // ... lots of hard work ...
  channel.send(my_result);
  do_cleanup_stuff();
}

Now do_cleanup_stuff() might not get a chance to run, if your main thread terminates before my_thread does. If that cleanup function is important, that could cause problems. And it could be more subtle than that. If any local variable in my_thread holds a file handle or an open TCP stream or any other object with a nontrivial Drop implementation, that value may not get a chance to Drop properly if you don't join the thread.

So it's probably best practice to join everything, even if it's just a final step at the end of your main.


问:
csrf_token() is empty in l5-swagger and couldn't do any request except GET request
csrf_token() is empty in l5-swagger and couldn't do any request except GET because the header is missing and always getting 419 error code

I have tried to request it from postman and it works. but in swagger it didn't. I have taken a look from this link (laravel 5 csrf_token value is Empty) but I still have no idea how to solve my problem.

How can I get the csrf_token inside my l5-swagger view?

答:
None of these worked for me in Laravel 8.70.1.

What worked for me was to disable the EnsureFrontendRequestsAreStateful::class in both my local and dev (no public access) environments. Then in my deployment process (TeamCity & OctoDeploy) to both staging and production, the commented EnsureFrontendRequestsAreStateful::class is uncommented.

Swagger is disabled as part of the deployment process to both the staging and prod environments. If you are building a SPA you need the EnsureFrontendRequestsAreStateful class.

In summary, disabling the EnsureFrontendRequestsAreStateful::class should solve the problem, but make sure you put it back in both your staging and production environments.

File to edit is in /app/Http/Kernel.php

```<code>   //\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:60,1',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\AuthGates::class,

        ],
</code>```

Body:
None of these worked for me in Laravel 8.70.1.

What worked for me was to disable the EnsureFrontendRequestsAreStateful::class in both my local and dev (no public access) environments. Then in my deployment process (TeamCity & OctoDeploy) to both staging and production, the commented EnsureFrontendRequestsAreStateful::class is uncommented.

Swagger is disabled as part of the deployment process to both the staging and prod environments. If you are building a SPA you need the EnsureFrontendRequestsAreStateful class.

In summary, disabling the EnsureFrontendRequestsAreStateful::class should solve the problem, but make sure you put it back in both your staging and production environments.

File to edit is in /app/Http/Kernel.php

   //\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:60,1',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\AuthGates::class,

        ],


问:
How can I make a menu "sticky" to the top when I scroll to it for the first time?
Good morning all,

I have this website I'm working on.  It has several pages but, I want the menu to be STICKY once you scroll to it and it comes into view for the first time.

This is a template but, when you keep scrolling, the menu scrolls up and out of view.

Here's the menu code and the link to the site:  http://wtr2022.webparity.net

```<code>        <section class="menu-wrap flex-md-column-reverse d-md-flex">
            <nav class="navbar navbar-expand-lg navbar-dark ftco_navbar bg-dark ftco-navbar-light" id="ftco-navbar">
                <div class="container">

                    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#ftco-nav" aria-controls="ftco-nav" aria-expanded="false" aria-label="Toggle navigation">
                        <span class="fa fa-bars"></span> Menu
                    </button>
                    <div class="collapse navbar-collapse" id="ftco-nav">
                        <ul class="navbar-nav mr-auto">
                            <li class="nav-item active"><a href="index.html" class="nav-link">Home</a></li>
                            <li class="nav-item"><a href="about.html" class="nav-link">About</a></li>
                            <li class="nav-item"><a href="services.html" class="nav-link">Services</a></li>
                            <li class="nav-item"><a href="project.html" class="nav-link">Project</a></li>
                            <li class="nav-item"><a href="blog.html" class="nav-link">Blog</a></li>
                            <li class="nav-item"><a href="contact.html" class="nav-link">Contact</a></li>
                        </ul>
                    </div>
                </div>
            </nav>
            <!-- END nav -->
       ....
       </section>
</code>```

UPDATE: I tried adding the following CODE from here: Bootstrap Navbar fixed on scrollY > 50, sticky but it doesn't work.  You'll find this code under js/wtr-custom.js

```<code>        document.addEventListener("DOMContentLoaded", function () {
            window.addEventListener('scroll', function () {
                if (window.scrollY > 50) {
                    document.getElementById('ftco-navbar').classList.add('fixed-top');
                    // add padding top to show content behind navbar
                    navbar_height = document.querySelector('.navbar').offsetHeight;
                    document.body.style.paddingTop = navbar_height + 'px';
                } else {
                    document.getElementById('ftco-navbar').classList.remove('fixed-top');
                    // remove padding top from body
                    document.body.style.paddingTop = '0';
                }
            });
        });
        // DOMContentLoaded  end
</code>```

Thank you...

答:
The sticky element is not magically sticky throughout the whole page when it sticks; instead it takes into consideration its "parent" container's bounds and is "sticky" only within them. Once you scroll past that parent container and it is out of your viewport, the sticky element will also be out of the viewport.

The "menu code", i.e. the  element you have is all right and would stick if you placed it differently in your layout.
The problem seems to be that the sticky navbar is inside the
 container, so the sticky navbar only sticks "within" that section. But as soon as you'll scroll past that section, your navbar will be out of sight, too.

I assume you want it to start sticking after scrolling past that first uppper-most
. You can try placing your navbar outside your
 element, so that its direct "parent" container is the  element and see what happens.
I think that should do the trick in your example. :)

For a more in-depth read on sticky elements, have a look here:
https://elad.medium.com/css-position-sticky-how-it-really-works-54cd01dc2d46

UPDATE:
First of all, I actually think that the javascript snippet you posted after your update won't be needed at all. Unless I'm misunderstanding, I think you're aiming for quite standard sticky behaviour that should work out-of-the-box. Therefore I'd ditch that javascript for now. :)

Basically, what you should aim for is NOT to put the sticky navbar inside an element/section of the page that you intend to scroll past.
This is a oversimplified version of the site I see in your example:

```<code><body>
  <section>
    This is the slider section
    <sticky-element />
  </section>
  <section>
    This is the "We've been in Serving our Community for nearly 50 years!" section
  </section>
  ...
</body>
</code>```

The adjustment needed would be to get that sticky navbar out from any container/section than you are intending to scroll past at some point.

```<code><body>
  <section>
    This is the slider section
  </section>
  <sticky-element />
  <section>
    This is the "We've been in Serving our Community for nearly 50 years!" section
  </section>
  ...
</body>
</code>```

This way it would be still rendered below the first slider-section, but would start sticking once you scroll past it.

Body:
Good morning all,

I have this website I'm working on.  It has several pages but, I want the menu to be STICKY once you scroll to it and it comes into view for the first time.

This is a template but, when you keep scrolling, the menu scrolls up and out of view.

Here's the menu code and the link to the site:  http://wtr2022.webparity.net

                    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#ftco-nav" aria-controls="ftco-nav" aria-expanded="false" aria-label="Toggle navigation">
                         Menu
                    </button>

Home

About

Services

Project

Blog

Contact

       ....

UPDATE: I tried adding the following CODE from here: Bootstrap Navbar fixed on scrollY > 50, sticky but it doesn't work.  You'll find this code under js/wtr-custom.js

        document.addEventListener("DOMContentLoaded", function () {
            window.addEventListener('scroll', function () {
                if (window.scrollY > 50) {
                    document.getElementById('ftco-navbar').classList.add('fixed-top');
                    // add padding top to show content behind navbar
                    navbar_height = document.querySelector('.navbar').offsetHeight;
                    document.body.style.paddingTop = navbar_height + 'px';
                } else {
                    document.getElementById('ftco-navbar').classList.remove('fixed-top');
                    // remove padding top from body
                    document.body.style.paddingTop = '0';
                }
            });
        });
        // DOMContentLoaded  end

Thank you...

Body:
The sticky element is not magically sticky throughout the whole page when it sticks; instead it takes into consideration its "parent" container's bounds and is "sticky" only within them. Once you scroll past that parent container and it is out of your viewport, the sticky element will also be out of the viewport.

The "menu code", i.e. the <nav> element you have is all right and would stick if you placed it differently in your layout.
The problem seems to be that the sticky navbar is inside the <section> container, so the sticky navbar only sticks "within" that section. But as soon as you'll scroll past that section, your navbar will be out of sight, too.

I assume you want it to start sticking after scrolling past that first uppper-most <section>. You can try placing your navbar outside your <section> element, so that its direct "parent" container is the <body> element and see what happens.
I think that should do the trick in your example. :)

For a more in-depth read on sticky elements, have a look here:
https://elad.medium.com/css-position-sticky-how-it-really-works-54cd01dc2d46

UPDATE:
First of all, I actually think that the javascript snippet you posted after your update won't be needed at all. Unless I'm misunderstanding, I think you're aiming for quite standard sticky behaviour that should work out-of-the-box. Therefore I'd ditch that javascript for now. :)

Basically, what you should aim for is NOT to put the sticky navbar inside an element/section of the page that you intend to scroll past.
This is a oversimplified version of the site I see in your example:

<body>
  <section>
    This is the slider section
    <sticky-element />
  </section>
  <section>
    This is the "We've been in Serving our Community for nearly 50 years!" section
  </section>
  ...
</body>

The adjustment needed would be to get that sticky navbar out from any container/section than you are intending to scroll past at some point.

<body>
  <section>
    This is the slider section
  </section>
  <sticky-element />
  <section>
    This is the "We've been in Serving our Community for nearly 50 years!" section
  </section>
  ...
</body>

This way it would be still rendered below the first slider-section, but would start sticking once you scroll past it.


问:
Exception error when trying to pass down URL from a for loop into a API query
```<code>import requests
import json

api_url = "https://api.taxes.info.net/taxes/%s/rate?page=1"

list =[
{"state": "Ohio",
"state": "California",
"state": "Georgia"}
      ]

for i in list:
   state_name = i.get("state")
   urls = api_url % state_name
print(urls) returns: >>>>> https://api.taxes.info.net/taxes/Ohio/rate?page=1 https://api.taxes.info.net/taxes/California/rate?page=1 https://api.taxes.info.net/taxes/Georgia/rate?page=1

    for url in urls:
        response = requests.get(url, headers={"Accept": "state.api+jsonv3", "Authorization": "password1234")

 Getting error message: >>>>> requests.exceptions.MissingSchema: Invalid URL 'h': No schema supplied. Perhaps you meant http://h?

</code>```

I'm trying to pass down the urls stored in my first for loop and pass it down to my API request. I'm fairly new to programming so any suggestions or pointers would be greatly appreciated. I did confirm my indentation is correct in my second for loop.

答:
TL;DR The reason you are getting this error is because urls is a string and not a list (might I suggest renaming it to url). This means the second for loop is unnecessary!

If you would like a more in depth response:

If you set the variables urls to a string (let's say https://api.taxes.info.net/taxes/Georgia/rate?page=1) you don't need to iterate through it. In fact you can just pass that string to requests.get like so:

for i in list:
   state_name = i.get("state")
   urls = api_url % state_name

   # This works fine.
   response = requests.get(urls, headers={"Accept": "state.api+jsonv3", "Authorization": "password1234"})
```
<h5>Now you may be wondering why you are getting the error <code>Invalid URL 'h': No schema supplied. </code></h5>
<p>This is because in python you <em>can</em> actually iterate through a string (which is what you are doing).</p>
<pre class="lang-py prettyprint-override"><code>for l in "https://google.com":
    print(l)
</code>```

This will print every letter in https://google.com in order. So when you pass in the first letter of your URL to the requests module, it gets confused because h is not a URL (first letter of https://api.taxes.info.net/taxes/Georgia/rate?page=1)

In conclusion

Instead of iterating through a string, you should just pass that string to requests.get directly

Hope this helped at least a little.

This is my first stack overflow answer so any feedback is welcome!

Body:
import requests
import json

api_url = "https://api.taxes.info.net/taxes/%s/rate?page=1"

list =[
{"state": "Ohio",
"state": "California",
"state": "Georgia"}
      ]

for i in list:
   state_name = i.get("state")
   urls = api_url % state_name
print(urls) returns: >>>>> https://api.taxes.info.net/taxes/Ohio/rate?page=1 https://api.taxes.info.net/taxes/California/rate?page=1 https://api.taxes.info.net/taxes/Georgia/rate?page=1

    for url in urls:
        response = requests.get(url, headers={"Accept": "state.api+jsonv3", "Authorization": "password1234")

 Getting error message: >>>>> requests.exceptions.MissingSchema: Invalid URL 'h': No schema supplied. Perhaps you meant http://h?

I'm trying to pass down the urls stored in my first for loop and pass it down to my API request. I'm fairly new to programming so any suggestions or pointers would be greatly appreciated. I did confirm my indentation is correct in my second for loop.

Body:
TL;DR The reason you are getting this error is because urls is a string and not a list (might I suggest renaming it to url). This means the second for loop is unnecessary!

If you would like a more in depth response:

If you set the variables urls to a string (let's say https://api.taxes.info.net/taxes/Georgia/rate?page=1) you don't need to iterate through it. In fact you can just pass that string to requests.get like so:

for i in list:
   state_name = i.get("state")
   urls = api_url % state_name

   # This works fine.
   response = requests.get(urls, headers={"Accept": "state.api+jsonv3", "Authorization": "password1234"})

Now you may be wondering why you are getting the error Invalid URL 'h': No schema supplied.

This is because in python you can actually iterate through a string (which is what you are doing).

for l in "https://google.com":
    print(l)

This will print every letter in https://google.com in order. So when you pass in the first letter of your URL to the requests module, it gets confused because h is not a URL (first letter of https://api.taxes.info.net/taxes/Georgia/rate?page=1)

In conclusion

Instead of iterating through a string, you should just pass that string to requests.get directly

Hope this helped at least a little.

This is my first stack overflow answer so any feedback is welcome!


问:
Do all STL containers return their elements by reference?
I am learning STL these days and I was wondering if STL containers return by reference?

e.g:

```<code>vector.first();
map[key];
*vector.begin();
Or any possible return that ends with element (or value type) of container
</code>```

e.g:

```<code>std::vector<int> elements;
elements.push_back(20);
elements[0]=60; // this will also change the value
elements.front() = 23; // even the functions also behave same way like subscript operator
</code>```

is this the case with all containers? or there are some points to consider which I didn't show?

答:
All the types of containers (sequence, associative) are designed to provide a consistent interface (where possible). It makes learning them relatively easy and using them even easier (as long as you've learnt them properly! ;) )

So for example, operator[] for all containers will return a reference to the entity indexed (in the case of the associate containers, it will be created first). For the sequence containers this raises an interesting point about bounds checking - but that's a different story. Similarly, if you take any other common operation (insert etc.) will have a similar interface. Your favourite reference will typically provide all the information you need.

Body:
I am learning STL these days and I was wondering if STL containers return by reference?

e.g:

vector.first();
map[key];
*vector.begin();
Or any possible return that ends with element (or value type) of container

e.g:

std::vector<int> elements;
elements.push_back(20);
elements[0]=60; // this will also change the value
elements.front() = 23; // even the functions also behave same way like subscript operator

is this the case with all containers? or there are some points to consider which I didn't show?


问:
.htaccess drupal 7 RedirectMatch or RewriteRule nothing seams to work
I'm having some real issues getting a redirect to work in .htaccess with drupal 7.

I have links like this:

```<code>example.com/vid/category/filter?subcat_filter_depth=125
</code>```

and I need them to go to: (on same domain)

```<code>example.com/vid/category/filter?type=All&subcat_filter_depth=125
</code>```

after = the number may be different like 67 or 32 etc. meaning that can be any number and whatever number is at the end of the original link needs to also be at the end of the new link.

I think the fact that the link is pretty much the same path just different filter is what is causing the issue as even the Drupal redirect url module will not allow it at an attempt to add them one at a time as they occur.

here is everything I've tried:

```<code>RedirectMatch 301 ^/vid/category/filter?subcat_filter_depth=(.*) /vid/category/filter?type=All&subcat_filter_depth=$1

RewriteRule ^(.*)/vid/category/filter?subcat_filter_depth=(.*) $1/vid/category/filter?type=All&subcat_filter_depth=$2 [R=301]

RedirectMatch ^/vid/category/filter?subcat_filter_depth=(.*) ^/vid/category/filter?type=All&subcat_filter_depth=$1

RedirectMatch 301 ^(.*)/filter?subcat_filter_depth=(.*) ^$1/filter?type=All&subcat_filter_depth=$2

RedirectMatch ^/(.*)/filter?subcat_filter_depth=(.*) ^/$1/filter?type=All&subcat_filter_depth=$2

RewriteRule "^/(.*)/filter?subcat_filter_depth=(.*)" "^/$1/filter?type=All&subcat_filter_depth=$2"
</code>```

mod_rewrite is on and there is an AllowOverride pathed/to/the/.htaccess file under <Directory> inside <VirtualHost> in the 000-default.conf running on Debian Apache ..pretty much latest versions.

I know mod_rewrite is working because if I add a bad rule or rewrite with a syntax error I get error 500 response page.

I've searched and tried just about everything I can think of and nothing seems to work.

Any help getting this sorted and functioning would be greatly appreciated!

答:
I was able to come up with a solution that worked prior to the answer (above) I marked as correct as my solution isn't quite as elegant.

I did realize after a bit of more research I needed to use a RewriteCond with %{QUERY_STRING} for what I was trying to achieve.

Again not as elegant as the answer above...but here is my code:

```<code>RewriteCond %{REQUEST_URI} ^/vid/category/filter [NC]
RewriteCond %{QUERY_STRING} ^(.*)=(.*)
RewriteRule (.*) /vid/category/filter?type=All&subcat_filter_depth=%2 [R=301,L]
</code>```

This actual kept the url in the browser as it was input (/var/category/filter?subcat_filter_depth=) but showed the page as if it was opened with the proper filter for type=ALL and produced no errors both in browser and in Drupal dblog.

The above solution is more useful in explanation alone and gave me much better understanding of how to break up a URL and put it back together with modifications especially when dealing with strings that have variables that change like unique ID's.

Body:
I'm having some real issues getting a redirect to work in .htaccess with drupal 7.

I have links like this:

example.com/vid/category/filter?subcat_filter_depth=125

and I need them to go to: (on same domain)

example.com/vid/category/filter?type=All&subcat_filter_depth=125

after = the number may be different like 67 or 32 etc. meaning that can be any number and whatever number is at the end of the original link needs to also be at the end of the new link.

I think the fact that the link is pretty much the same path just different filter is what is causing the issue as even the Drupal redirect url module will not allow it at an attempt to add them one at a time as they occur.

here is everything I've tried:

RedirectMatch 301 ^/vid/category/filter?subcat_filter_depth=(.*) /vid/category/filter?type=All&subcat_filter_depth=$1

RewriteRule ^(.*)/vid/category/filter?subcat_filter_depth=(.*) $1/vid/category/filter?type=All&subcat_filter_depth=$2 [R=301]

RedirectMatch ^/vid/category/filter?subcat_filter_depth=(.*) ^/vid/category/filter?type=All&subcat_filter_depth=$1

RedirectMatch 301 ^(.*)/filter?subcat_filter_depth=(.*) ^$1/filter?type=All&subcat_filter_depth=$2

RedirectMatch ^/(.*)/filter?subcat_filter_depth=(.*) ^/$1/filter?type=All&subcat_filter_depth=$2

RewriteRule "^/(.*)/filter?subcat_filter_depth=(.*)" "^/$1/filter?type=All&subcat_filter_depth=$2"

mod_rewrite is on and there is an AllowOverride pathed/to/the/.htaccess file under <Directory> inside <VirtualHost> in the 000-default.conf running on Debian Apache ..pretty much latest versions.

I know mod_rewrite is working because if I add a bad rule or rewrite with a syntax error I get error 500 response page.

I've searched and tried just about everything I can think of and nothing seems to work.

Any help getting this sorted and functioning would be greatly appreciated!

Body:
I was able to come up with a solution that worked prior to the answer (above) I marked as correct as my solution isn't quite as elegant.

I did realize after a bit of more research I needed to use a RewriteCond with %{QUERY_STRING} for what I was trying to achieve.

Again not as elegant as the answer above...but here is my code:

RewriteCond %{REQUEST_URI} ^/vid/category/filter [NC]
RewriteCond %{QUERY_STRING} ^(.*)=(.*)
RewriteRule (.*) /vid/category/filter?type=All&subcat_filter_depth=%2 [R=301,L]

This actual kept the url in the browser as it was input (/var/category/filter?subcat_filter_depth=) but showed the page as if it was opened with the proper filter for type=ALL and produced no errors both in browser and in Drupal dblog.

The above solution is more useful in explanation alone and gave me much better understanding of how to break up a URL and put it back together with modifications especially when dealing with strings that have variables that change like unique ID's.


问:
How to get $refs using Composition API in Vue3?
I am trying to get $refs in Vue 3 using Composition API. This is my template that has two child components and I need to get reference to one child component instance:

```<code><template>
    <comp-foo />
    <comp-bar ref="table"/>
</template>
</code>```

In my code I use Template Refs: ref is a special attribute, that allows us to obtain a direct reference to a specific DOM element or child component instance after it's mounted.

If I use Options API then I don't have any problems:

```<code>  mounted() {
    console.log("Mounted - ok");
    console.log(this.$refs.table.temp());
  }
</code>```

However, using Composition API I get error:

```<code>setup() {
    const that: any = getCurrentInstance();
    onMounted(() => {
      console.log("Mounted - ok");
      console.log(that.$refs.table.temp());//ERROR that.$refs is undefined
    });
    return {};
  }
</code>```

Could anyone say how to do it using Composition API?

答:
If you want, you can use getCurrentInstance() in the parent component like this code:

<template>
    <MyCompo ref="table"></MyCompo>
</template>

```
</div>
</div>
</p>
<p>And this is the code of child component (here I called it <code>MyCompo</code>):</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-html lang-html prettyprint-override"><code><template>
    <h1>this is MyCompo component</h1>
</template>

<script>
export default {

    setup(props, ctx) {

        const tempMethod = () => {
            console.log("temporary method");
        }

        return {
            tempMethod
        }
    },
}
</script></code>```

Body:
I am trying to get $refs in Vue 3 using Composition API. This is my template that has two child components and I need to get reference to one child component instance:

<template>
    <comp-foo />
    <comp-bar ref="table"/>
</template>

In my code I use Template Refs: ref is a special attribute, that allows us to obtain a direct reference to a specific DOM element or child component instance after it's mounted.

If I use Options API then I don't have any problems:

  mounted() {
    console.log("Mounted - ok");
    console.log(this.$refs.table.temp());
  }

However, using Composition API I get error:

setup() {
    const that: any = getCurrentInstance();
    onMounted(() => {
      console.log("Mounted - ok");
      console.log(that.$refs.table.temp());//ERROR that.$refs is undefined
    });
    return {};
  }

Could anyone say how to do it using Composition API?

Body:
If you want, you can use getCurrentInstance() in the parent component like this code:

<template>
    <MyCompo ref="table"></MyCompo>
</template>

<script>
import MyCompo from "@/components/MyCompo.vue"
import { ref, onMounted, getCurrentInstance } from 'vue'
export default {
    components : {
        MyCompo
    },

    setup(props, ctx) {

        onMounted(() => {
          getCurrentInstance().ctx.$refs.table.tempMethod()

        });
    }
}
</script>

And this is the code of child component (here I called it MyCompo):

<template>
    <h1>this is MyCompo component</h1>
</template>

<script>
export default {

    setup(props, ctx) {

        const tempMethod = () => {
            console.log("temporary method");
        }

        return {
            tempMethod
        }
    },
}
</script>


问:
Why when I set the body to position: relative, I get unexpected behavior
Any css masters know why this is happening? Or can explain it?  The p is being hoisted to behave like it is inside the div by adding position relative to body. I know position:static happens to the body by default, but when I set it to relative, the p tag behaves like it is nested inside the div tag. Anyone knows why this behavior is happening?

body {
    background-color: purple;
    margin: 0px;
    padding: 0px;
    position: relative;

}

div {
    background-color: red;
    height: 100px;
    position: relative;
    margin:0px;
    padding: 0px;

}

p {
    background-color: blue;
    position: absolute;
    bottom: 0px;
    margin:0px;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><!DOCTYPE html>
<html>
  <body>
        <div>
        <!-- it behaves like if it was here -->
        </div>
        <p>Hello World</p>
  </body>
</html></code>```

答:
The p is positioned at the bottom of its containing block

If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way:

...

If there is no such ancestor, the containing block is the initial containing block.

and the "initial containing block" is

The containing block in which the root element lives is a rectangle called the initial containing block. For continuous media, it has the dimensions of the viewport and is anchored at the canvas origin; it is the page area for paged media.

So without position:relative on body, the element is placed at the bottom of the screen. with position:relative at the bottom of the body.

add border to the body element to see its boundary. The coloration is confusing you due to another feature which is background propagation

body {
  background-color: purple;
  margin: 0px;
  padding: 0px;
  position: relative;
  border:2px solid green;
}

div {
  background-color: red;
  height: 100px;
  position: relative;
  margin: 0px;
  padding: 0px;
}

p {
  background-color: blue;
  position: absolute;
  bottom: 0px;
  margin: 0px;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><!DOCTYPE html>
<html>

<body>
  <div>
    <!-- it behaves like if it was here -->
  </div>
  <p>Hello World</p>
</body>

</html></code>```

Body:
Any css masters know why this is happening? Or can explain it?  The p is being hoisted to behave like it is inside the div by adding position relative to body. I know position:static happens to the body by default, but when I set it to relative, the p tag behaves like it is nested inside the div tag. Anyone knows why this behavior is happening?

body {
    background-color: purple;
    margin: 0px;
    padding: 0px;
    position: relative;

}

div {
    background-color: red;
    height: 100px;
    position: relative;
    margin:0px;
    padding: 0px;

}

p {
    background-color: blue;
    position: absolute;
    bottom: 0px;
    margin:0px;
}

<!DOCTYPE html>

Hello World

Body:
The p is positioned at the bottom of its containing block

If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way:

...

If there is no such ancestor, the containing block is the initial containing block.

and the "initial containing block" is

The containing block in which the root element lives is a rectangle called the initial containing block. For continuous media, it has the dimensions of the viewport and is anchored at the canvas origin; it is the page area for paged media.

So without position:relative on body, the element is placed at the bottom of the screen. with position:relative at the bottom of the body.

add border to the body element to see its boundary. The coloration is confusing you due to another feature which is background propagation

body {
  background-color: purple;
  margin: 0px;
  padding: 0px;
  position: relative;
  border:2px solid green;
}

div {
  background-color: red;
  height: 100px;
  position: relative;
  margin: 0px;
  padding: 0px;
}

p {
  background-color: blue;
  position: absolute;
  bottom: 0px;
  margin: 0px;
}

<!DOCTYPE html>
<html>

<body>
  <div>
    <!-- it behaves like if it was here -->
  </div>
  <p>Hello World</p>
</body>

</html>