问:
FE: Unit testing window.location.href changing on button click (test fails)
I am trying to test when the window.location.href changes after a button is clicked using react-testing-library. I have seen examples online where you manually update window.location.href inside of a test case as so window.location.href = 'www.randomurl.com' and then follow it with expect(window.location.href).toEqual(www.randomurl.com). While this indeed will pass, I want to avoid this as I'd rather simulate the user actions instead of injecting the new value into the test. If I do that, even if I remove my button click (which is what will actually trigger the function call) the expect will still pass because I have anyway manually updated the window.location.href in my test

What I've opted for is having goToThisPage func (which will redirect the user) to be placed outside of my functional component. I then mock goToThisPage in my test file and in my test case check whether it has been called. I do know that the goToThisPage is being triggered  because I included a console.log and when I run my tests I see it in my terminal. Nonetheless, the test still fails. I have been playing around with both spyOn and jest.doMock/mock with no luck

component.js

```<code>import React from 'react'
import { ChildComponent } from './childcomponent';
export const goToThisPage = () => {
  const url = '/url'
  window.location.href = url;
  console.log('reached');
};

export const Component = () => {
 return (<ChildComponent goToThisPage={ goToThisPage }/>)
}

export default Component;
</code>```

Test file:

```<code>  import * as Component from './component'
  import userEvent from '@testing-library/user-event';

  jest.doMock('./component', () => ({
   goToThisPage: jest.fn(),
  }));

  describe('goToThisPage', () => {
    test('should call goToThisPage when button is clicked', async () => {
        const goToThisPageSpy = jest.spyOn(Component, 'goToThisPage');
        const { container, getByTestId } = render(<Component.Component />);

        userEvent.click(screen.getByTestId('goToThisPage')); // this is successfully triggered (test id exists in child component)
        expect(goToThisPageSpy).toHaveBeenCalled();
        // expect(Component.goToThisPage()).toHaveBeenCalled(); this will fail and say that the value must be a spy or mock so I opted for using spy above
    });
});
</code>```

Note: when I try to just do jest.mock I got this error Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
When testing out with jest.doMock the error disappeared but the actual test fails.

I am open to hear more refined ideas of solving my issue if someone believes this solution could be improved. Thanks in advance

Edit:
This is another approach I have tried out

```<code>  import { Component, goToThisPage } from './component'
  import userEvent from '@testing-library/user-event';

  describe('goToThisPage', () => {
    test('should call goToThisPage when button is clicked', async () => {
        const goToThisPageSpy = jest.spyOn(Component, 'goToThisPage');
// I am not certain what I'd put as the first value in the spy. Because `goToThisPage` is an external func of <Component/> & not part of the component
        const { container, getByTestId } = render(<Component />);

        userEvent.click(screen.getByTestId('goToThisPage'));
        expect(goToThisPageSpy).toHaveBeenCalled();
    });
});
</code>```

答:
You exporting both functions and then defining a default export of the Component itself is what's causing the problem (which is mixing up default and named exports).

Remove export default Component; and change the top import in your test file to import {Component, goToThisPage} from './component'. That said I'm not sure you even need to export goToThisPage (for the Jest test at least).

Body:
I am trying to test when the window.location.href changes after a button is clicked using react-testing-library. I have seen examples online where you manually update window.location.href inside of a test case as so window.location.href = 'www.randomurl.com' and then follow it with expect(window.location.href).toEqual(www.randomurl.com). While this indeed will pass, I want to avoid this as I'd rather simulate the user actions instead of injecting the new value into the test. If I do that, even if I remove my button click (which is what will actually trigger the function call) the expect will still pass because I have anyway manually updated the window.location.href in my test

What I've opted for is having goToThisPage func (which will redirect the user) to be placed outside of my functional component. I then mock goToThisPage in my test file and in my test case check whether it has been called. I do know that the goToThisPage is being triggered  because I included a console.log and when I run my tests I see it in my terminal. Nonetheless, the test still fails. I have been playing around with both spyOn and jest.doMock/mock with no luck

component.js

import React from 'react'
import { ChildComponent } from './childcomponent';
export const goToThisPage = () => {
  const url = '/url'
  window.location.href = url;
  console.log('reached');
};

export const Component = () => {
 return (<ChildComponent goToThisPage={ goToThisPage }/>)
}

export default Component;

Test file:

  import * as Component from './component'
  import userEvent from '@testing-library/user-event';

  jest.doMock('./component', () => ({
   goToThisPage: jest.fn(),
  }));

  describe('goToThisPage', () => {
    test('should call goToThisPage when button is clicked', async () => {
        const goToThisPageSpy = jest.spyOn(Component, 'goToThisPage');
        const { container, getByTestId } = render(<Component.Component />);

        userEvent.click(screen.getByTestId('goToThisPage')); // this is successfully triggered (test id exists in child component)
        expect(goToThisPageSpy).toHaveBeenCalled();
        // expect(Component.goToThisPage()).toHaveBeenCalled(); this will fail and say that the value must be a spy or mock so I opted for using spy above
    });
});

Note: when I try to just do jest.mock I got this error Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
When testing out with jest.doMock the error disappeared but the actual test fails.

I am open to hear more refined ideas of solving my issue if someone believes this solution could be improved. Thanks in advance

Edit:
This is another approach I have tried out

  import { Component, goToThisPage } from './component'
  import userEvent from '@testing-library/user-event';

  describe('goToThisPage', () => {
    test('should call goToThisPage when button is clicked', async () => {
        const goToThisPageSpy = jest.spyOn(Component, 'goToThisPage');
// I am not certain what I'd put as the first value in the spy. Because `goToThisPage` is an external func of <Component/> & not part of the component
        const { container, getByTestId } = render(<Component />);

        userEvent.click(screen.getByTestId('goToThisPage'));
        expect(goToThisPageSpy).toHaveBeenCalled();
    });
});


来源: stackexchange

问:
How can I frequently/automatically compare the structure of the same Database?
Does anyone know a tool that automatically compares the structure of a database and gives a report of what was changed?  If it can be integrated into a CruiseControl, even better.

By structure I also mean functions and stored procedures. Which is probably not clear at first sight ;-)

The idea was to integrate that into a cruise control server

答: For integrating into CC if the output of the tool is plaintext you can publish it as an artifact. If the output is .xml you can merge it into the log and write an xsl that will include it in the email & web pages.</p>

OwnerDisplayName: Fatboss

ContentLicense: CC BY-SA 2.5

LastEditorDisplayName: Eddie

OwnerDisplayName: Jeffrey Fredrick


问:
Has MySQL always supported shorthand validation for fields?
I am currently writing a lot of MySQL queries and noticed that I can use shorthand validation, like so:

```<code>SELECT id, content, date_added FROM table WHERE date_added
</code>```

(where date_added is a default NULL timestamp and I don't have to ask specifically if it IS NOT NULL to return all results that have a timestamp)

I just need to know if this is advised against, or if this shorthand functionality became available at a certain MySQL version, as I would like to retain backwards compatibility.
I was previously certain that this didn't work and I had to write out the whole conditional, but now I cannot confirm.

答:
I actually understand what you mean by your terms shorthand validation, thanks for pointing this out... I have used "WHERE 1" quite a bit to start off a "WHERE clause variable" in PHP, inspired by phpMyAdmin's queries which has been using that for quite a while, so maybe that answers your question at least somewhat...

This is from 2004:
http://forums.devshed.com/mysql-help-4/phpmyadmin-where-1t-112118.html

ContentLicense: CC BY-SA 3.0

Body:
I am currently writing a lot of MySQL queries and noticed that I can use shorthand validation, like so:

SELECT id, content, date_added FROM table WHERE date_added

(where date_added is a default NULL timestamp and I don't have to ask specifically if it IS NOT NULL to return all results that have a timestamp)

I just need to know if this is advised against, or if this shorthand functionality became available at a certain MySQL version, as I would like to retain backwards compatibility.
I was previously certain that this didn't work and I had to write out the whole conditional, but now I cannot confirm.


问:
Regex to match character x times at the start of string but don't match at all if it's more than that
I'm currently facing the problem that I want to match a character (%) x times but not more than that at the start of a line.
My initial thought was to do this:

```<code>^%{1,6}
</code>```

but this matches %%%%%%%

Is there a way to not make it match at all if the maximum is reached?

答:
You can use

^%{1,6}(?!%)
```

See the .NET regex demo.

Details:

^ - start of string

%{1,6} - one to six occurrences of a % char

(?!%) - a negative lookahead that fails the match if there is a % char immediately on the right.

ContentLicense: CC BY-SA 4.0

Body:
I'm currently facing the problem that I want to match a character (%) x times but not more than that at the start of a line.
My initial thought was to do this:

^%{1,6}

but this matches %%%%%%%

Is there a way to not make it match at all if the maximum is reached?

Body:
You can use

^%{1,6}(?!%)

See the .NET regex demo.

Details:

^ - start of string

%{1,6} - one to six occurrences of a % char

(?!%) - a negative lookahead that fails the match if there is a % char immediately on the right.


问:
how to set position of cursor in bottom right of textarea in textfield in flutter
I need text area cursor starting point will be bottom right
https://i.stack.imgur.com/wsS8O.jpg</p>

答:
You can set the TextField property textAlign at end,Hope this will work for you, Thanks

import 'package:flutter/material.dart';

```<code>class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: SafeArea(
                child: Center(
                    child: Container(
                        width: 290,
                        padding: EdgeInsets.all(10.0),
                        child: TextField(
                            autocorrect: true,
                            textAlign: TextAlign.end,
                            decoration: InputDecoration(
                            )))))));
  }
}
</code>```

Body:
You can set the TextField property textAlign at end,Hope this will work for you, Thanks

import 'package:flutter/material.dart';

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: SafeArea(
                child: Center(
                    child: Container(
                        width: 290,
                        padding: EdgeInsets.all(10.0),
                        child: TextField(
                            autocorrect: true,
                            textAlign: TextAlign.end,
                            decoration: InputDecoration(
                            )))))));
  }
}


问:
ABP: How to get the current user id?
I managed to display of the current user email, but how do I get the user id?

```<code>Template:
<div *ngIf="!hasLoggedIn">
   {{ (profile$ | async)?.email }}
</div>

TypeScript:
import { Profile, GetProfile, ProfileState, } from '@abp/ng.core';

export class Component implements OnInit {
   @Select(ProfileState.getProfile) //State
   profile$: Observable<Profile.Response>;  //Model

   get hasLoggedIn(): boolean {
      return this.oAuthService.hasValidAccessToken();
   }

   constructor(private oAuthService: OAuthService) {}

   ngOnInit() {
   this.store.dispatch(new GetProfile()).subscribe(); //Action
   }
}
</code>```

Inside app-routing.module.ts there is import ofApplicationLayoutComponent and inside there is a declaration of the variable currentUser $: Observable <ApplicationConfiguration.CurrentUser>; which is being used to display the user name in the navbar, and inside the ApplicationConfiguration models there is an Id, but I couldn't implement it as I did with email

Ps: Sorry for my English

答:
```<code>public async Task LinkToUser(LinkToUserInput input)
{
    var loginResult = await _logInManager.LoginAsync(input.UsernameOrEmailAddress, input.Password, input.TenancyName);

    if (loginResult.Result != AbpLoginResultType.Success)
    {
        throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(loginResult.Result, input.UsernameOrEmailAddress, input.TenancyName);
    }

    if (AbpSession.IsUser(loginResult.User))
    {
        throw new UserFriendlyException(L("YouCannotLinkToSameAccount"));
    }

    if (loginResult.User.ShouldChangePasswordOnNextLogin)
    {
        throw new UserFriendlyException(L("ChangePasswordBeforeLinkToAnAccount"));
    }

    await _userLinkManager.Link(GetCurrentUser(), loginResult.User);
}
</code>```

Title: ABP: How to get the current user id?

Body:
I managed to display of the current user email, but how do I get the user id?

Template:

   {{ (profile$ | async)?.email }}

TypeScript:
import { Profile, GetProfile, ProfileState, } from '@abp/ng.core';

export class Component implements OnInit {
   @Select(ProfileState.getProfile) //State
   profile$: Observable<Profile.Response>;  //Model

   get hasLoggedIn(): boolean {
      return this.oAuthService.hasValidAccessToken();
   }

   constructor(private oAuthService: OAuthService) {}

   ngOnInit() {
   this.store.dispatch(new GetProfile()).subscribe(); //Action
   }
}

Inside app-routing.module.ts there is import ofApplicationLayoutComponent and inside there is a declaration of the variable currentUser $: Observable <ApplicationConfiguration.CurrentUser>; which is being used to display the user name in the navbar, and inside the ApplicationConfiguration models there is an Id, but I couldn't implement it as I did with email

Ps: Sorry for my English


问:
WCF Relay already connected to a listener, but no listeners are connected?
I'm currently attempting to write two applications in C# - a client and a server - which connect to a WCF Relay I've got set up in Azure, but I'm getting a really strange error when I try to run either.

This is a brand new WCF Relay that I've set up which has no naming conflicts with anything else, but every time I try to open a connection to it as a listener with my service, it fails with this exception:

System.ServiceModel.AddressAlreadyInUseException:
Address sb://[MY_RELAY].servicebus.windows.net/[MY_WCF_RELAY] is already in use by an existing listener with different settings.

And when I try to run my client application connecting to the same relay URL, I get this exception:

System.ServiceModel.FaultException:
'50200: There are no listeners connected for the endpoint.

Kind of odd how there's already a listener connected, but at the same time no listeners are connected. I've even checked on the number of active connections to the relay, and it's never jumped past 0.

Anybody have any clue what might be going on here and how I could troubleshoot? Thanks!

答:
Please Check you might have configured a tenant with a service path of ./. Because of this, the root path was taken and then every tenant that tried to register would get the  below error "Address sb://[namespace].servicebus.windows.net/[WCF Relay name] is already in use by an existing listener with different settings" .

Try to turn off the bad endpoint then all the other endpoint will able to work again.

If you creating a WCF Relay explicitly in the portal (or with NamespaceManager.CreateRelay[Async]) for this endpoint, If so, then you need the binding's IsDynamic == false.
If you're not pre-creating the endpoint then the binding's IsDynamic must be true.


问:
Resharper: Possible null assignment to entity marked with notnull attribute
I get this warning on response.GetResponseStream()
How should I handle this?

```<code>// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
    // Get the response stream
    if (response != null)
    {
        var reader = new StreamReader(response.GetResponseStream());
        var responseString = reader.ReadToEnd();
        return responseString;
    }
}
</code>```

For clarity based on some answers misinterpreting:

This line is not where the warning is occurring:

```<code>using (var response = request.GetResponse() as HttpWebResponse)
</code>```

This line is where the warning is occurring:

```<code>var reader = new StreamReader(response.GetResponseStream());
</code>```

答:
You can use C#'s null conditional operator to get rid of the warning:

```<code>var reader = new StreamReader(response?.GetResponseStream());
</code>```

It is a syntactic sugar to avoid writing code for checking null value of a reference at runtime. Internally this code is equivalent to :

```<code>var reader = new StreamReader(response != null ? response.GetResponseStream() : null);
</code>```

Body:
I get this warning on response.GetResponseStream()
How should I handle this?

// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
    // Get the response stream
    if (response != null)
    {
        var reader = new StreamReader(response.GetResponseStream());
        var responseString = reader.ReadToEnd();
        return responseString;
    }
}

For clarity based on some answers misinterpreting:

This line is not where the warning is occurring:

using (var response = request.GetResponse() as HttpWebResponse)

This line is where the warning is occurring:

var reader = new StreamReader(response.GetResponseStream());

Body:
You can use C#'s null conditional operator to get rid of the warning:

var reader = new StreamReader(response?.GetResponseStream());

It is a syntactic sugar to avoid writing code for checking null value of a reference at runtime. Internally this code is equivalent to :

var reader = new StreamReader(response != null ? response.GetResponseStream() : null);


问:
Socket Buffer for bpf, __sk_buff
I am playing ebpf code  and got a sample like so:

```<code>int tc_ingress(struct __sk_buff *skb)
{
    void *data = (void *)(long)skb->data;
    struct ethhdr *eth = data, eth_copy; # what is this line doing?
}
</code>```

AS I am new to C and kernel, got stuck on many smaller things. Can some tell me what is this line mean?

```<code>struct ethhdr *eth = data, eth_copy;
</code>```

答:
struct ethhdr *eth = data, eth_copy;
```
<p>Is nothing special, it is a more compact version of</p>
<pre class="lang-c prettyprint-override"><code>struct ethhdr *eth = data;
struct ethhdr *eth_copy;
</code>```

So we declare two variables of the same type, but we initialize just the first one.

Title: Socket Buffer for bpf, __sk_buff

Body:
I am playing ebpf code  and got a sample like so:

int tc_ingress(struct __sk_buff *skb)
{
    void *data = (void *)(long)skb->data;
    struct ethhdr *eth = data, eth_copy; # what is this line doing?
}

AS I am new to C and kernel, got stuck on many smaller things. Can some tell me what is this line mean?

struct ethhdr *eth = data, eth_copy;

Body:
struct ethhdr *eth = data, eth_copy;

Is nothing special, it is a more compact version of

struct ethhdr *eth = data;
struct ethhdr *eth_copy;

So we declare two variables of the same type, but we initialize just the first one.


问:
Speeding up read_csv in python pandas
I am trying to parse a huge csv file (around 50 million rows) using Pandas 'read_csv' method.

Below is the code snippet I am using:

df_chunk = pd.read_csv(db_export_file, delimiter='~!#', engine='python', header=None, keep_default_na=False, na_values=[''], chunksize=10 ** 6, iterator=True)

Therafter using the pd.concat method I am getting the whole set of dataframe which is used for further processing.

Everything is working fine instead, the read operation from that csv file takes almost 6 mins to create the dataframe.

My question is that, is there any other way to make this process faster using the same module and method?

Below is the sample data presented as a csv file

155487~!#-64721487465~!#A1_NUM~!#1.000
155487~!#-45875722734~!#A32_ENG~!#This is a good facility
458448~!#-14588001153~!#T12_Timing~!#23-02-2015 14:50:30
458448~!#-10741214586~!#Q2_56!#

Thanks in advance

答:
My case and how it was solved

I had a similarly huge dataset and a custom converter was mandatory to be implemented. The pandas.read_csv() was taking ages because of the custom converter.

The solution for me was to use modin. It was simple, just had to change the import on top and everything else was done automatically.

Take a look at the page: https://github.com/modin-project/modin

Title: Speeding up read_csv in python pandas


问:
Null Pointer Exception for read properties file in Idea
after define a property file in idea 10.5 when i try to use it,compiler show me Null Pointer Exception!I try anything that i think fix it among change property file path,...
here is the code that i write:
thanks.
beginner programmer!!!</p>

```<code>public class MainDlg{
    Properties properties=new Properties();
    public MainDlg() {
        try {
            InputStream reader=MainDlg.class.getResourceAsStream("propFile");
            properties.load(reader);
</code>```

答:
probably you resources (prop files) are not put into the classes directory. In any case here is a tip ;) just before reading the property, print the following:

```<code>new java.util.File(".").getAbsolutePath()
</code>```

This should give you a good idea of what is your actual current directory
Hope this will resolve your issues. Good luck!

Body:
after define a property file in idea 10.5 when i try to use it,compiler show me Null Pointer Exception!I try anything that i think fix it among change property file path,...
here is the code that i write:
thanks.
beginner programmer!!!

public class MainDlg{
    Properties properties=new Properties();
    public MainDlg() {
        try {
            InputStream reader=MainDlg.class.getResourceAsStream("propFile");
            properties.load(reader);

Body:
probably you resources (prop files) are not put into the classes directory. In any case here is a tip ;) just before reading the property, print the following:

new java.util.File(".").getAbsolutePath()

This should give you a good idea of what is your actual current directory
Hope this will resolve your issues. Good luck!


问:
Laravel eloquent query group where clause returns wrong query
I have a MySQL query:

```<code>select * from `contents`
 where `vei_sn` = '22566'
    and `op_date` >= '2022-02-07'
    and `op_date` <= '2022-02-07'
     and not (`ecu` = 'ACM' and `ecu_sub` = 2.1 and `parameters` = 'TorqueLimit2')
order by `op_full_date` desc limit 31 offset 0
</code>```

and I want to transform it into eloquent.
I wrote this eloquent query, but it output the wrong query results:

```<code>OplogContent::query()
            ->where('vei_sn', $device->serial_number)
            ->where('op_date', '>=', $request->date_from)
            ->where('op_date', '<=', $request->date_to)
            ->where(function ($q) {
                $q->where('ecu', '!=', 'ACM')
                  ->where('ecu_sub', '!=', 2.1)
                  ->where('parameters', '!=', 'TorqueLimit2');
            });
            ->orderBy('op_full_date', 'desc')
            ->simplePaginate(30)

//// but it returns this MySQL query //////
select * from `contents`
 where `vei_sn` = '22566'
  and `op_date` >= '2022-02-07'
   and `op_date` <= '2022-02-07'
    and (`ecu` != 'ACM' and `ecu_sub` != 2.1 and `parameters` != 'TorqueLimit2')
order by `op_full_date` desc limit 31 offset 0
</code>```

How to change my eloquent query, that MySQL where grouping clause will be and not (`ecu` = 'ACM' and `ecu_sub` = 2.1 and `parameters` = 'TorqueLimit2') ?

答:
The problem is about the boolean algebra. If you use  NOT(a & b) it is equal to
NOT a | NOT b.

So this line translated to query:

and not ('ecu' = 'ACM' and 'ecu_sub' = 2.1 and 'parameters' = 'TorqueLimit2')

```<code> ->where(function ($q) {
            $q->where('ecu', '!=', 'ACM')
              ->orWhere('ecu_sub', '!=', 2.1)
              ->orWhere('parameters', '!=', 'TorqueLimit2');
        });
</code>```

Body:
I have a MySQL query:

select * from `contents`
 where `vei_sn` = '22566'
    and `op_date` >= '2022-02-07'
    and `op_date` <= '2022-02-07'
     and not (`ecu` = 'ACM' and `ecu_sub` = 2.1 and `parameters` = 'TorqueLimit2')
order by `op_full_date` desc limit 31 offset 0

and I want to transform it into eloquent.
I wrote this eloquent query, but it output the wrong query results:

OplogContent::query()
            ->where('vei_sn', $device->serial_number)
            ->where('op_date', '>=', $request->date_from)
            ->where('op_date', '<=', $request->date_to)
            ->where(function ($q) {
                $q->where('ecu', '!=', 'ACM')
                  ->where('ecu_sub', '!=', 2.1)
                  ->where('parameters', '!=', 'TorqueLimit2');
            });
            ->orderBy('op_full_date', 'desc')
            ->simplePaginate(30)

//// but it returns this MySQL query //////
select * from `contents`
 where `vei_sn` = '22566'
  and `op_date` >= '2022-02-07'
   and `op_date` <= '2022-02-07'
    and (`ecu` != 'ACM' and `ecu_sub` != 2.1 and `parameters` != 'TorqueLimit2')
order by `op_full_date` desc limit 31 offset 0

How to change my eloquent query, that MySQL where grouping clause will be and not (`ecu` = 'ACM' and `ecu_sub` = 2.1 and `parameters` = 'TorqueLimit2') ?

Body:
The problem is about the boolean algebra. If you use  NOT(a & b) it is equal to
NOT a | NOT b.

So this line translated to query:

and not ('ecu' = 'ACM' and 'ecu_sub' = 2.1 and 'parameters' = 'TorqueLimit2')

 ->where(function ($q) {
            $q->where('ecu', '!=', 'ACM')
              ->orWhere('ecu_sub', '!=', 2.1)
              ->orWhere('parameters', '!=', 'TorqueLimit2');
        });


问:
Can i pass multiple parameters to a bind variable in a SQL query in Oracle with equal to sign?
The user will select multiple pick value from screen like 100, 101, 102 etc. and those values need to be passed to the below query and generate the output for further processing.

How can I pass multiple values to a bind parameter in a query having a equal to sign?

```<code>SELECT tab1.PICKLIST_KEY icrggq_0, NULL icrggq_1, 0 icrggq_2
  FROM tab1
 WHERE dc_code = 942
   AND tab1.pick_value = :p_pick_value;
</code>```

There are hundreds of queries like this and we will not be able to modify all of them manually. Is it possible to be done by plsql procedure or function ? We are receiving the multiple values through front end Oracle Forms screen.

答:
How can I pass multiple values to a bind parameter in a query having a equal to sign?

You cannot pass multiple values and use then in a query with an equals sign to match any one of the list of values.

A bind variable is a single value so you can concatenate multiple strings into a single delimited string and pass that single string but then you will either need to match the entire delimited string or change the query to perform sub-string matches.

Or, you can concatenate multiple values into a single collection and pass that single collection; however, this is not supported by all client applications (i.e. C# allows passing PL/SQL associative array collections but not nested table collections, Java/JDBC allows passing nested table collections but not associative arrays, SQL/Plus does not allow either when defining a bind VARIABLE). Even then, the equals operator would match the entire collection and not one element of the collection.

There are hundreds of queries like this and we will not be able to modify all of them manually.

If you are changing the input then you will need to change them all.

Option 1: LIKE operator:

You do not need to split the values. You can use the LIKE operator to match one element of a comma-delimited string:

SELECT PICKLIST_KEY AS icrggq_0,
       NULL AS icrggq_1,
       0 AS icrggq_2
FROM   tab1
WHERE  dc_code = 942
AND    ',' || :p_pick_value || ',' LIKE '%,' || pick_value || ',%';
```
<hr />
<h3>Option 2: Collections</h3>
<p>Depending on the client application you are using to connect to the database, you may be able to pass in a collection as the bind value and use the <code>MEMBER OF</code> operator:</p>
<pre class="lang-sql prettyprint-override"><code>SELECT PICKLIST_KEY AS icrggq_0,
       NULL AS icrggq_1,
       0 AS icrggq_2
FROM   tab1
WHERE  dc_code = 942
AND    pick_value MEMBER OF :p_pick_value;
</code>```

A Java example of passing a collection is here.

Body:
The user will select multiple pick value from screen like 100, 101, 102 etc. and those values need to be passed to the below query and generate the output for further processing.

How can I pass multiple values to a bind parameter in a query having a equal to sign?

SELECT tab1.PICKLIST_KEY icrggq_0, NULL icrggq_1, 0 icrggq_2
  FROM tab1
 WHERE dc_code = 942
   AND tab1.pick_value = :p_pick_value;

There are hundreds of queries like this and we will not be able to modify all of them manually. Is it possible to be done by plsql procedure or function ? We are receiving the multiple values through front end Oracle Forms screen.

Body:
How can I pass multiple values to a bind parameter in a query having a equal to sign?

You cannot pass multiple values and use then in a query with an equals sign to match any one of the list of values.

A bind variable is a single value so you can concatenate multiple strings into a single delimited string and pass that single string but then you will either need to match the entire delimited string or change the query to perform sub-string matches.

Or, you can concatenate multiple values into a single collection and pass that single collection; however, this is not supported by all client applications (i.e. C# allows passing PL/SQL associative array collections but not nested table collections, Java/JDBC allows passing nested table collections but not associative arrays, SQL/Plus does not allow either when defining a bind VARIABLE). Even then, the equals operator would match the entire collection and not one element of the collection.

There are hundreds of queries like this and we will not be able to modify all of them manually.

If you are changing the input then you will need to change them all.

Option 1: LIKE operator:

You do not need to split the values. You can use the LIKE operator to match one element of a comma-delimited string:

SELECT PICKLIST_KEY AS icrggq_0,
       NULL AS icrggq_1,
       0 AS icrggq_2
FROM   tab1
WHERE  dc_code = 942
AND    ',' || :p_pick_value || ',' LIKE '%,' || pick_value || ',%';

Option 2: Collections

Depending on the client application you are using to connect to the database, you may be able to pass in a collection as the bind value and use the MEMBER OF operator:

SELECT PICKLIST_KEY AS icrggq_0,
       NULL AS icrggq_1,
       0 AS icrggq_2
FROM   tab1
WHERE  dc_code = 942
AND    pick_value MEMBER OF :p_pick_value;

A Java example of passing a collection is here.


问:
How to Measure Similarity or Difference of Meaning Between Words?
Say you have two random words ('yellow' and 'ambient' or 'goose' and 'kettle'). What tech could be used to rate how similar or different they are in meaning as informed by popular usage? For example, from 0 to 1 where antonyms are 0 and synonyms are 1, 'yellow' and 'ambient' might be 0.65 similar.

Note: I'm not talking about how close the two strings are to each other, but rather an approximation of how similar their meanings are.

答:
One approach that works quite well for measuring semantic similarity is looking at contexts in which the two words in question occur: as the distribution of words is not random, the context carries a lot of information, up to the point where you can guess what a word means (eg in a foreign language) which you don't know, as long as you understand the words around it.

In my PhD thesis I have investigated that approach in various ways; I have taken instances of a word from a corpus, and recorded their contexts, ie the n words to their left and right. Then you do this for another word, and compare how similar the contexts are. This will give you a value between 0 and 1, depending on the metric you use.

You can treat the contexts as frequency lists, and then compare the frequencies of the same word in both contexts, or you can be more specific and compare them also by distance to the target word. The more specific you are, the more data you need, but the more accurate your results will be.

One caveat is words with different meanings (homographs): the word left can be an adjective (the left door), a verb (they left the room), or a noun (they are part of the left). Each of them will have different contexts, but you won't be able to distinguish them automatically during processing, so the similarity values for words with multiple meanings will be somewhat 'smudged'. And some words will have identical contexts, eg names: (I went to X on holiday -- X can be any country/city/location).

It also will probably not work very well with antonyms, as they often occur in the same context: this door is open/closed/locked/unlocked, this book is too easy/difficult etc. But it might; hard to tell without actually trying it out. One thing that does work well are closed categories, such as days of the week or months.

While this can be done in a purely symbolic way, I think this is also the same principle that is used by embeddings in deep learning algorithms, where words are represented by context vectors.


问:
Converting varying JSON objects to CSV-file
I am calling an API and it returns JSON string. I want to convert it to CSV-format so I can save it later to database. However, JSON objects keys cause problems because there is keys missing or keys are changing.
I wrote this python script but because of keys I cannot get it to work:

```<code>import json
import csv

with open('custom.json') as json_file:
    data = json.load(json_file)

custom_data = data['CustomJSON']
data_file = open('data_file.csv', 'w')
csv_writer = csv.writer(data_file)
count = 0

for i in custom_data:
    if count == 0:
        # Writing headers of CSV file
        header = i.keys()
        csv_writer.writerow(header)
        count += 1
    # Writing data of CSV file
    csv_writer.writerow(i.values())
data_file.close()
</code>```

How I can convert this type of JSON to CSV?
Example JSON message:

```<code>{
    "CustomJSON" : [
    {
     "id" : "1,
      "name" : "Jack",
      "surname" : "Bauer"
    },
    {
      "id" : "2",
      "name" : "John",
      "surname" : "Smith"
      "age" : "31",
      "city" : "New York"
    },
    {
      "id" : "3",
      "name" : "Matt",
      "surname" : "Secret"
      "exception_1" : "Exception_1",
      "exception_2" : "Exception_2"
      "date" : "2022-02-08"
    }
  ]
}
</code>```

Should I try to loop all key-values first somehow and then later try to add data? Can anyone provide an example?

答:
As you are reading a single JSON string, you will have everything in memory. So IMHO the simplest way is to first build the field names list, and then write everything to a csv file.

```<code># compute the fieldnamelist
# this uses a dict because it is easy to update it while maintaining key order
keys = dict()
for d in data['CustomJSON']:
    keys.update(d)

# write to the csv file
# this uses a DictWriter because the individual rows are already dicts
with open('data_file.csv', 'w', newline='') as data_file
    csv_writer = csv.DictWriter(data_file, fieldnames = keys.keys())
    _ = csv_writer.writeheader()
    _ = csv_writer.writerows(data['CustomJSON'])
</code>```

With your data it gives as expected:

```<code>id,name,surname,age,city,exception_1,exception_2,date
1,Jack,Bauer,,,,,
2,John,Smith,31,New York,,,
3,Matt,Secret,,,Exception_1,Exception_2,2022-02-08
</code>```

Body:
I am calling an API and it returns JSON string. I want to convert it to CSV-format so I can save it later to database. However, JSON objects keys cause problems because there is keys missing or keys are changing.
I wrote this python script but because of keys I cannot get it to work:

import json
import csv

with open('custom.json') as json_file:
    data = json.load(json_file)

custom_data = data['CustomJSON']
data_file = open('data_file.csv', 'w')
csv_writer = csv.writer(data_file)
count = 0

for i in custom_data:
    if count == 0:
        # Writing headers of CSV file
        header = i.keys()
        csv_writer.writerow(header)
        count += 1
    # Writing data of CSV file
    csv_writer.writerow(i.values())
data_file.close()

How I can convert this type of JSON to CSV?
Example JSON message:

{
    "CustomJSON" : [
    {
     "id" : "1,
      "name" : "Jack",
      "surname" : "Bauer"
    },
    {
      "id" : "2",
      "name" : "John",
      "surname" : "Smith"
      "age" : "31",
      "city" : "New York"
    },
    {
      "id" : "3",
      "name" : "Matt",
      "surname" : "Secret"
      "exception_1" : "Exception_1",
      "exception_2" : "Exception_2"
      "date" : "2022-02-08"
    }
  ]
}

Should I try to loop all key-values first somehow and then later try to add data? Can anyone provide an example?

Body:
As you are reading a single JSON string, you will have everything in memory. So IMHO the simplest way is to first build the field names list, and then write everything to a csv file.

# compute the fieldnamelist
# this uses a dict because it is easy to update it while maintaining key order
keys = dict()
for d in data['CustomJSON']:
    keys.update(d)

# write to the csv file
# this uses a DictWriter because the individual rows are already dicts
with open('data_file.csv', 'w', newline='') as data_file
    csv_writer = csv.DictWriter(data_file, fieldnames = keys.keys())
    _ = csv_writer.writeheader()
    _ = csv_writer.writerows(data['CustomJSON'])

With your data it gives as expected:

id,name,surname,age,city,exception_1,exception_2,date
1,Jack,Bauer,,,,,
2,John,Smith,31,New York,,,
3,Matt,Secret,,,Exception_1,Exception_2,2022-02-08


问:
Dataframe splitting in Python
i Have a dataframe DF ,  and column name DETAILS,  i want the value which are in double quotes (""), will make new column VALUE

DF=

```<code>      DETAILS
   Username as "JOHN"
   verifying the name
   click UserBox
   Password as "345678"
   Click login
   click checkbox
   Phonenumber as "34512345"
   Checking data
</code>```

I want my data frame look like this

DF=

```<code>     DETAILS                      VALUE
   Username as "JOHN"           "JOHN"
   verifying the name             NA
   click UserBox                  NA
   Password as "345678"          "3345678"
   Click login                    NA
   click checkbox                 NA
   Phonenumber as "34512345"     "34512345"
   Checking data                 NA

</code>```

答:
Here you go:

```<code>df['VALUE'] = df.apply(
    lambda x: '"' + x['DETAILS'].split('"')[1] + '"'
                if len(x['DETAILS'].split('"')) > 1
                else 'NA',
    1)
</code>```

This will output:

```<code>                     DETAILS       VALUE
0         Username as "JOHN"      "JOHN"
1         verifying the name          NA
2              click UserBox          NA
3       Password as "345678"    "345678"
4                Click login          NA
5             click checkbox          NA
6  Phonenumber as "34512345"  "34512345"
7              Checking data          NA
</code>```

with the column VALUES containing your values where present, else NA.

Title: Dataframe splitting in Python

Body:
i Have a dataframe DF ,  and column name DETAILS,  i want the value which are in double quotes (""), will make new column VALUE

DF=

      DETAILS
   Username as "JOHN"
   verifying the name
   click UserBox
   Password as "345678"
   Click login
   click checkbox
   Phonenumber as "34512345"
   Checking data

I want my data frame look like this

DF=

     DETAILS                      VALUE
   Username as "JOHN"           "JOHN"
   verifying the name             NA
   click UserBox                  NA
   Password as "345678"          "3345678"
   Click login                    NA
   click checkbox                 NA
   Phonenumber as "34512345"     "34512345"
   Checking data                 NA

Body:
Here you go:

df['VALUE'] = df.apply(
    lambda x: '"' + x['DETAILS'].split('"')[1] + '"'
                if len(x['DETAILS'].split('"')) > 1
                else 'NA',
    1)

This will output:

                     DETAILS       VALUE
0         Username as "JOHN"      "JOHN"
1         verifying the name          NA
2              click UserBox          NA
3       Password as "345678"    "345678"
4                Click login          NA
5             click checkbox          NA
6  Phonenumber as "34512345"  "34512345"
7              Checking data          NA

with the column VALUES containing your values where present, else NA.


问:
How to convert two vectors into dataframe (wide format)
I want to convert two vectors into a wide format dataframe. The fist vector represent the column names and the second vector the values.
Here is my reproduceable example:

```<code>vector1<-c("Reply","Reshare","Like","Share","Search")
vector2<-c(2,1,0,4,3)
</code>```

Now I want to convert these two vector into a wide format dataframe:

```<code># A tibble: 1 x 5
   Reply Reshare  Like Share Search
   <dbl>   <dbl> <dbl> <dbl>  <dbl>
1     2       1     0     4      3
</code>```

I have found some examples for the long format, but none simple solution for the wide format. Can anyone help me?

答:
vector1<-c("Reply","Reshare","Like","Share","Search")
vector2<-c(2,1,0,4,3)

df <- data.frame(vector1, vector2)
df |> tidyr::pivot_wider(names_from = vector1, values_from = vector2)
#> # A tibble: 1 × 5
#>   Reply Reshare  Like Share Search
#>   <dbl>   <dbl> <dbl> <dbl>  <dbl>
#> 1     2       1     0     4      3
```

Created on 2022-02-08 by the reprex package (v2.0.1)

Body:
I want to convert two vectors into a wide format dataframe. The fist vector represent the column names and the second vector the values.
Here is my reproduceable example:

vector1<-c("Reply","Reshare","Like","Share","Search")
vector2<-c(2,1,0,4,3)

Now I want to convert these two vector into a wide format dataframe:

# A tibble: 1 x 5
   Reply Reshare  Like Share Search
   <dbl>   <dbl> <dbl> <dbl>  <dbl>
1     2       1     0     4      3

I have found some examples for the long format, but none simple solution for the wide format. Can anyone help me?

Body:
vector1<-c("Reply","Reshare","Like","Share","Search")
vector2<-c(2,1,0,4,3)

df <- data.frame(vector1, vector2)
df |> tidyr::pivot_wider(names_from = vector1, values_from = vector2)
#> # A tibble: 1 × 5
#>   Reply Reshare  Like Share Search
#>   <dbl>   <dbl> <dbl> <dbl>  <dbl>
#> 1     2       1     0     4      3

Created on 2022-02-08 by the reprex package (v2.0.1)


问:
C# Or operator Issue
I am pretty sure someone of you can help me with this issue.
I do not find and do not understand the solution.

```<code>if (hero.IsAlive || creature.IsAlive == false)
        {
            if (hero.IsAlive == true)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                EnemyHitInterface();
                Console.ForegroundColor = ConsoleColor.White;
                Thread.Sleep(1500);
                hero.Exp += 150;
                baseSetting.YouWin();
                hero.UpdateLvL();
                hero.CharacterInterface(hero);
                hero.PrintStatsHero();
                Console.ReadKey();
                CheckForItem();
                hero.PrintStatsHero();
                Console.ReadKey();
            }
            else if (creature.IsAlive == true)
            {
                Console.Clear();
                CenterText("You are dead. See you next time...", 15);
                Console.ReadKey();
                Environment.Exit(0);
            }
        }
</code>```

Simple if Operation with asks in my opinion, as soon as the hero dies or the creature it will get triggered.
If the creature dies, everything is fine, but if the hero dies it wont be triggered.
What is the think i do not understand?

For me it is like:

When Hero or Creature dies, go in
If hero is alive do this
if creature is alive do this

But like I said, as for the creature it wont work

答:
I suspect you read this line

```<code>if (hero.IsAlive || creature.IsAlive == false)
</code>```

in your head as "If hero or creature are dead". What it actually says is "If hero is alive or creature is dead". And if you follow through the rest of your logic, you'll see why you never hit the else if (creature.IsAlive == true) part.

What you (I think) wanted in the first if statement was

```<code>if (hero.IsAlive == false || creature.IsAlive == false) // if either are dead
</code>```

or, more usually written

```<code>if (!hero.IsAlive || !creature.IsAlive) // if either are dead
</code>```

Title: C# Or operator Issue

Body:
I am pretty sure someone of you can help me with this issue.
I do not find and do not understand the solution.

if (hero.IsAlive || creature.IsAlive == false)
        {
            if (hero.IsAlive == true)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                EnemyHitInterface();
                Console.ForegroundColor = ConsoleColor.White;
                Thread.Sleep(1500);
                hero.Exp += 150;
                baseSetting.YouWin();
                hero.UpdateLvL();
                hero.CharacterInterface(hero);
                hero.PrintStatsHero();
                Console.ReadKey();
                CheckForItem();
                hero.PrintStatsHero();
                Console.ReadKey();
            }
            else if (creature.IsAlive == true)
            {
                Console.Clear();
                CenterText("You are dead. See you next time...", 15);
                Console.ReadKey();
                Environment.Exit(0);
            }
        }

Simple if Operation with asks in my opinion, as soon as the hero dies or the creature it will get triggered.
If the creature dies, everything is fine, but if the hero dies it wont be triggered.
What is the think i do not understand?

For me it is like:

When Hero or Creature dies, go in
If hero is alive do this
if creature is alive do this

But like I said, as for the creature it wont work

Body:
I suspect you read this line

if (hero.IsAlive || creature.IsAlive == false)

in your head as "If hero or creature are dead". What it actually says is "If hero is alive or creature is dead". And if you follow through the rest of your logic, you'll see why you never hit the else if (creature.IsAlive == true) part.

What you (I think) wanted in the first if statement was

if (hero.IsAlive == false || creature.IsAlive == false) // if either are dead

or, more usually written

if (!hero.IsAlive || !creature.IsAlive) // if either are dead


问:
MetadataExtractor File format could not be determined
I'm using metadataExtractor (v.2.7.1) in .Net Core (3.0.1) to get the date of the photos.

```<code>  var file = Request.Form.Files[0];
  try
  {
      IEnumerable<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(file.OpenReadStream());
  ....
  }
</code>```

And I get sometimes this exception on this line "File format could not be determined"

Any idea what is wrong? This photo seems to be correct and having the exif metadata I need.

The code is working for other photos.

Thank you in advance

答: The problem was that this photo was larger than the other one and was uploaded in chunck. I was trying to get EXIF from each chunk, which is not possible...</p>

Body:
I'm using metadataExtractor (v.2.7.1) in .Net Core (3.0.1) to get the date of the photos.

  var file = Request.Form.Files[0];
  try
  {
      IEnumerable<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(file.OpenReadStream());
  ....
  }

And I get sometimes this exception on this line "File format could not be determined"

Any idea what is wrong? This photo seems to be correct and having the exif metadata I need.

The code is working for other photos.

Thank you in advance


问:
Google sheets: Arrayformula with importrange
I'm trying to work with combined arrangeformula and importrange formulas. I want that from spreadsheet1:Table1 P4 value would be taken to spreadsheet2 C3 cell: Table2 and only when i add new link to column "L" it will put automatic value at C4. So i want to use arrangeformula so it will work on whole column, but i want to fix that from all the links i add it would take same "P4" value. Possible?</p>

答:
There is no solution. See link1 and link2

All you can is

```<code>={IFERROR(IMPORTRANGE($L3;"Lapas1!A2");"");
IFERROR(IMPORTRANGE($L4;"Lapas1!A2");"");
IFERROR(IMPORTRANGE($L5;"Lapas1!A2");"");
IFERROR(IMPORTRANGE($L6;"Lapas1!A2");"")}
</code>```

as many times as you wish

Body:
There is no solution. See link1 and link2

All you can is

={IFERROR(IMPORTRANGE($L3;"Lapas1!A2");"");
IFERROR(IMPORTRANGE($L4;"Lapas1!A2");"");
IFERROR(IMPORTRANGE($L5;"Lapas1!A2");"");
IFERROR(IMPORTRANGE($L6;"Lapas1!A2");"")}

as many times as you wish


问:
The return of string find function in cpp
Is there a case where the string::find function return -1 ?
that code I have seen a lot while surveying a code for XML_Editor
and I can't understand the code

```<code>if(temp.find("<") == -1){}
</code>```

The above code is an example of what I mean
I hope someone help , thanks :)

答:
std::string::find returns npos when it cannot find its parameter. npos is defined as:

```<code>static const size_type npos = -1;
</code>```

However, note that size_type is unsigned. Hence, one should not use -1 to check the value returend from find. The value of npos is the largest value representable as size_type and -1 is just a way to initialize npos with that value. When checking the value returned from find one should always use std::string::npos rather than -1, because -1 is a signed literal:

```<code>if(temp.find("<") == std::string::npos){
    // < was not found in temp
}
</code>```

Body:
Is there a case where the string::find function return -1 ?
that code I have seen a lot while surveying a code for XML_Editor
and I can't understand the code

if(temp.find("<") == -1){}

The above code is an example of what I mean
I hope someone help , thanks :)

Body:
std::string::find returns npos when it cannot find its parameter. npos is defined as:

static const size_type npos = -1;

However, note that size_type is unsigned. Hence, one should not use -1 to check the value returend from find. The value of npos is the largest value representable as size_type and -1 is just a way to initialize npos with that value. When checking the value returned from find one should always use std::string::npos rather than -1, because -1 is a signed literal:

if(temp.find("<") == std::string::npos){
    // < was not found in temp
}


问:
Rewrite rule doesn't work on joomla htaccess
I need a redirect from http://www.mysite.com/passport/365.html to http://www.mysite.com/passport/365.html?task=view

I try to do it like this
RewriteCond %{HTTP_HOST} ^/passport/365.html$
RewriteRule ^/?$ /passport/365.html?task=view [QSA]

and it doesn't work.

Please help.

答:
There is a component already build in Joomla called "redirect" where U can set-up your redirects, so you don't have to use .htaccess at all.

Here is a good tutorial: http://www.joomtraining.com.au/tutorials/joomla-1.6/creating-a-page-redirect

The problem with the .htaccess is that every redirect must be set in appropriate place in the file.


问:
In WinAPI, how do I know when the mouse has moved outside the current window?
Basically, I want to write a program that shows in a small window the color of the pixel currently pointed by the mouse cursor.

Of course, I could poll the mouse cursor position once in a while, but I would like to opt to a mechanism that calls my code when the mouse cursor has moved, regardless whether it's pointing the current window or not.

Is there some WinAPI trickery that could achieve that functionality?

答:
After some search, I found this:</p>
```<code>HHOOK mouseHook =
    SetWindowsHookExA(
        WH_MOUSE_LL,
        LowLevelMouseProc,
        hInstance,
        0);

...

LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (wParam == WM_MOUSEMOVE) {
        // Notify me.
    }

    return 0;
}
</code>```

Body:
After some search, I found this:

HHOOK mouseHook =
    SetWindowsHookExA(
        WH_MOUSE_LL,
        LowLevelMouseProc,
        hInstance,
        0);

...

LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (wParam == WM_MOUSEMOVE) {
        // Notify me.
    }

    return 0;
}


问:
Why Metamask if web3.js can interact directly with ganache?
I am new to blockchain app development, I saw a project where ganache accounts are imported into Metamask, then web3.js is used to access and print those accounts and balances on Frontend (user interface).

If web3.js can directly access ganache blockchain accounts and balances, why do we need Metamask in between?

答:
If web3.js can directly acccess ganache blockchain accounts and balances, why we need metamask in between?

In this case, you don't need MetaMask to sign the transaction, as the node (Ganache) holds your private key.

But in a public environment (testnets and mainnet), the node doesn't hold your private key, so you'd need to sign the transaction using MetaMask (or any other tool that holds the private key).


问:
flutter_bloc event is not trigger after Migrate to flutter_bloc v 8.0.0 from v7.2.1
I tried to migrate flutter_bloc v 8.0.0. After I read the documentation, then I know that I need to migrate mapEventToState to on. After that I don't get an error but _getMonks event is not trigger. Here is my code. Is there anything I miss out?</p>
```<code>class MonkBloc extends Bloc<MonkEvent, MonkState> {
   final MonkRespository monkRespository;
   late List<Monk> monks;

   MonkBloc({required this.monkRespository}) : super(MonkInitial()) {
       on<GetMonksEvent>((event, emit) => _getMonks);
       on<MonkSearchEvent>((event, emit) => _searchMonks);
   }

   Stream<MonkState> _getMonks(Emitter<MonkState> emit) async* {
     emit(MonkLoading());
     try {
        final List<Monk> monks = await monkRespository.fetchMonks();
        emit(MonkLoaded(monks: monks));
     } catch (e) {
     emit (MonkError(error: (e.toString())));
     }
  }

  Stream<MonkState> _searchMonks(String query, Emitter<MonkState> emit) async* {
emit(MonkLoading());
try {
  final List<Monk> monks = await monkRespository.searchMonks(query);
  emit(MonkLoaded(monks: monks));
} catch (e) {
  emit(MonkError(error: (e.toString())));
}
}
}

class MonkScreen extends StatefulWidget {
  static const routeName = '/monk';
  final String? title;
  final MonkScreenMode? screenMode;
  const MonkScreen({Key? key, this.title, this.screenMode}) : super(key: key);

  @override
  State<MonkScreen> createState() => _MonkScreenState();
  }

  class _MonkScreenState extends State<MonkScreen> {

  _loadMonks() async {

    BlocProvider.of<MonkBloc>(context).add(const GetMonksEvent());
  }

  @override
  void initState() {
    super.initState();
    _loadMonks();
  }

  @override
  Widget build(BuildContext context) {
  return BaseWidget(
  child: Scaffold(
    backgroundColor: Theme.of(context).backgroundColor,
    appBar: AppBar(
      centerTitle: true,
      backgroundColor: Theme.of(context).backgroundColor,
      elevation: 0,
      title: AutoSizeText(
        widget.title!,
        style: Theme.of(context).appBarTheme.titleTextStyle,
      ),
      leading: IconButton(
        onPressed: () {
          Navigator.pop(context);
        },
        icon: Icon(
          Icons.arrow_back,
          color: Theme.of(context).primaryIconTheme.color!,
        ),
      ),
      actions: [
        IconButton(
          onPressed: () {
            showSearch(
                context: context,
                delegate: MonkSearch(screenMode: widget.screenMode!));
          },
          icon: Icon(
            Icons.search,
            color: Theme.of(context).primaryIconTheme.color!,
          ),
        ),
      ],
    ),
    body: BlocBuilder<MonkBloc, MonkState>(
      builder: (BuildContext context, MonkState monkState) {
        if (monkState is MonkError) {
          return const SomethingWentWrongScreen();
        } else if (monkState is MonkLoaded) {
          return listViewBuilder(
              context, monkState.monks, widget.screenMode!);
        }
        return const Center(
          child: CircularProgressIndicator(),
        );
      },
    ),
  ),
);
}
}
</code>```

答:
There is a typo here.

on<GetMonksEvent>((event, emit) => _getMonks);

You must call _getMonks with args or just pass the event listener itself:

Use this one

```<code>on<GetMonksEvent>((event, emit) => _getMonks(event, emit));
</code>```

or the better one

```<code>on<GetMonksEvent>(_getMonks);
</code>```

Body:
I tried to migrate flutter_bloc v 8.0.0. After I read the documentation, then I know that I need to migrate mapEventToState to on. After that I don't get an error but _getMonks event is not trigger. Here is my code. Is there anything I miss out?

class MonkBloc extends Bloc<MonkEvent, MonkState> {
   final MonkRespository monkRespository;
   late List<Monk> monks;

   MonkBloc({required this.monkRespository}) : super(MonkInitial()) {
       on<GetMonksEvent>((event, emit) => _getMonks);
       on<MonkSearchEvent>((event, emit) => _searchMonks);
   }

   Stream<MonkState> _getMonks(Emitter<MonkState> emit) async* {
     emit(MonkLoading());
     try {
        final List<Monk> monks = await monkRespository.fetchMonks();
        emit(MonkLoaded(monks: monks));
     } catch (e) {
     emit (MonkError(error: (e.toString())));
     }
  }

  Stream<MonkState> _searchMonks(String query, Emitter<MonkState> emit) async* {
emit(MonkLoading());
try {
  final List<Monk> monks = await monkRespository.searchMonks(query);
  emit(MonkLoaded(monks: monks));
} catch (e) {
  emit(MonkError(error: (e.toString())));
}
}
}

class MonkScreen extends StatefulWidget {
  static const routeName = '/monk';
  final String? title;
  final MonkScreenMode? screenMode;
  const MonkScreen({Key? key, this.title, this.screenMode}) : super(key: key);

  @override
  State<MonkScreen> createState() => _MonkScreenState();
  }

  class _MonkScreenState extends State<MonkScreen> {

  _loadMonks() async {

    BlocProvider.of<MonkBloc>(context).add(const GetMonksEvent());
  }

  @override
  void initState() {
    super.initState();
    _loadMonks();
  }

  @override
  Widget build(BuildContext context) {
  return BaseWidget(
  child: Scaffold(
    backgroundColor: Theme.of(context).backgroundColor,
    appBar: AppBar(
      centerTitle: true,
      backgroundColor: Theme.of(context).backgroundColor,
      elevation: 0,
      title: AutoSizeText(
        widget.title!,
        style: Theme.of(context).appBarTheme.titleTextStyle,
      ),
      leading: IconButton(
        onPressed: () {
          Navigator.pop(context);
        },
        icon: Icon(
          Icons.arrow_back,
          color: Theme.of(context).primaryIconTheme.color!,
        ),
      ),
      actions: [
        IconButton(
          onPressed: () {
            showSearch(
                context: context,
                delegate: MonkSearch(screenMode: widget.screenMode!));
          },
          icon: Icon(
            Icons.search,
            color: Theme.of(context).primaryIconTheme.color!,
          ),
        ),
      ],
    ),
    body: BlocBuilder<MonkBloc, MonkState>(
      builder: (BuildContext context, MonkState monkState) {
        if (monkState is MonkError) {
          return const SomethingWentWrongScreen();
        } else if (monkState is MonkLoaded) {
          return listViewBuilder(
              context, monkState.monks, widget.screenMode!);
        }
        return const Center(
          child: CircularProgressIndicator(),
        );
      },
    ),
  ),
);
}
}

Body:
There is a typo here.

on<GetMonksEvent>((event, emit) => _getMonks);

You must call _getMonks with args or just pass the event listener itself:

Use this one

on<GetMonksEvent>((event, emit) => _getMonks(event, emit));

or the better one

on<GetMonksEvent>(_getMonks);


问:
How to properly write a "Patch" endpoint in flask and Pymongo
I'm new to APIs and coding in general, so I'm really struggling with getting Flask and PyMongo to properly work together (since I don't know what I'm doing). I'm trying to just write a simple endpoint for a PATCH request. Code here:

```<code>@app.route('/update-instructor/<id>', methods=['PATCH'])
def update_one_instructor(id):
  id = ObjectId(id)
  id_call = {"_id" : id}
  course = request.json.get("course")
  email = request.json.get("email")
  first = request.json.get("first")
  last = request.json.get("last")
  password = request.json.get("password")
  role = request.json.get("role")

  updateObject = {
    "course": course,
    "email": email,
    "first": first,
    "last": last,
    "password": password,
    "role": role
  }

  result = instructors.find_one_and_update(id_call, {"$set":updateObject}, return_document=ReturnDocument.AFTER)
  return f'Instructor information updated {updateObject}'
</code>```

However, when I pass this on to my database, it updates the fields I set, but sets everything else to 'null'. So if, in Postman, I submit:

```<code>{
"first" : "Jim"
}
</code>```

It works, but every other field (that previously held values) become set to null. Obviously, I don't want to be setting every single key value pair in JSON when doing a PATCH request, right? What exactly is going on here?

My understanding of what I have written here is that it uses BSON to get the ObjectId and find the instructor, then each variable uses request.json to find what the current value is. Those are then passed into updateObject (which I would think defaults to the previously held values unless the body in Postman specifies otherwise...) and then passes that to the pymongo find_one_and_update method.

Please help out a newbie! Thanks!

答:
```<code>@app.route('/update-instructor/<id>', methods=['PATCH'])
def update_one_instructor(id):
    request_params = request.get_json()
    print(request_params)
    # {'first': 'me', 'email': 'email'}  only gives you the things from postman

    updateObject = request_params
    # updateObject = {
    #     "course": course,
    #     "email": email,
    #     "first": first,
    #     "last": last,
    #     "password": password,
    #     "role": role
    # }

    # Continue with your logic

    return "Update Successful"
</code>```

I put this in postman:

```<code>  {
    "first": "me",
    "email": "email"
  }
</code>```

Body:
I'm new to APIs and coding in general, so I'm really struggling with getting Flask and PyMongo to properly work together (since I don't know what I'm doing). I'm trying to just write a simple endpoint for a PATCH request. Code here:

@app.route('/update-instructor/<id>', methods=['PATCH'])
def update_one_instructor(id):
  id = ObjectId(id)
  id_call = {"_id" : id}
  course = request.json.get("course")
  email = request.json.get("email")
  first = request.json.get("first")
  last = request.json.get("last")
  password = request.json.get("password")
  role = request.json.get("role")

  updateObject = {
    "course": course,
    "email": email,
    "first": first,
    "last": last,
    "password": password,
    "role": role
  }

  result = instructors.find_one_and_update(id_call, {"$set":updateObject}, return_document=ReturnDocument.AFTER)
  return f'Instructor information updated {updateObject}'

However, when I pass this on to my database, it updates the fields I set, but sets everything else to 'null'. So if, in Postman, I submit:

{
"first" : "Jim"
}

It works, but every other field (that previously held values) become set to null. Obviously, I don't want to be setting every single key value pair in JSON when doing a PATCH request, right? What exactly is going on here?

My understanding of what I have written here is that it uses BSON to get the ObjectId and find the instructor, then each variable uses request.json to find what the current value is. Those are then passed into updateObject (which I would think defaults to the previously held values unless the body in Postman specifies otherwise...) and then passes that to the pymongo find_one_and_update method.

Please help out a newbie! Thanks!

Body:
@app.route('/update-instructor/<id>', methods=['PATCH'])
def update_one_instructor(id):
    request_params = request.get_json()
    print(request_params)
    # {'first': 'me', 'email': 'email'}  only gives you the things from postman

    updateObject = request_params
    # updateObject = {
    #     "course": course,
    #     "email": email,
    #     "first": first,
    #     "last": last,
    #     "password": password,
    #     "role": role
    # }

    # Continue with your logic

    return "Update Successful"

I put this in postman:

  {
    "first": "me",
    "email": "email"
  }


问:
How to split int value without input?
code below works well  but i want to change 'input(row, col)' to (1, 1) so i can modify
value inside code without input, but when i change it it gives this error

AttributeError: 'tuple' object has no attribute 'split'

what is the solution?
thank you.

```<code>import random

class Tic:

    def __init__(self):
        self.board = []

    def create_board(self):
        for i in range(8):
            row = []
            for j in range(8):
                row.append('-')
            self.board.append(row)

    def fix_spot(self, row, col, player):
        self.board[row][col] = player

    def show_board(self):
        for row in self.board:
            print(row)

    def start(self):
        player = 'O'
        T.create_board()
        row, col = list(map(int, input("row, col: ").split()))
        self.fix_spot(row -1, col-1, player)
        T.show_board()

T = Tic()
T.start()

</code>```

答:
Since you don't use row and col elsewhere in the function, you could put the value direct in the fix_spot arguments

    def start(self):
        player = 'O'
        T.create_board()
        self.fix_spot(0, 0, player)
        T.show_board()
```
<p>Or set a default value in <code>fix_spot</code></p>
<pre class="lang-py prettyprint-override"><code>    def fix_spot(self, player, row=0, col=0):
        self.board[row][col] = player

    def start(self):
        player = 'O'
        T.create_board()
        self.fix_spot(player)
        T.show_board()
</code>```

Title: How to split int value without input?

Body:
code below works well  but i want to change 'input(row, col)' to (1, 1) so i can modify
value inside code without input, but when i change it it gives this error

AttributeError: 'tuple' object has no attribute 'split'

what is the solution?
thank you.

import random

class Tic:

    def __init__(self):
        self.board = []

    def create_board(self):
        for i in range(8):
            row = []
            for j in range(8):
                row.append('-')
            self.board.append(row)

    def fix_spot(self, row, col, player):
        self.board[row][col] = player

    def show_board(self):
        for row in self.board:
            print(row)

    def start(self):
        player = 'O'
        T.create_board()
        row, col = list(map(int, input("row, col: ").split()))
        self.fix_spot(row -1, col-1, player)
        T.show_board()

T = Tic()
T.start()

Body:
Since you don't use row and col elsewhere in the function, you could put the value direct in the fix_spot arguments

    def start(self):
        player = 'O'
        T.create_board()
        self.fix_spot(0, 0, player)
        T.show_board()

Or set a default value in fix_spot

    def fix_spot(self, player, row=0, col=0):
        self.board[row][col] = player

    def start(self):
        player = 'O'
        T.create_board()
        self.fix_spot(player)
        T.show_board()


问:
how to revert back an update in laravel
i have updated a http client package to the latest version.but after the update the i start getting errors on my system.how can i revert back to the previous version before the update.my laravel version of my project is 5.8 while the http client package is in the latest version (7.4.1)..

```<code>                 $body = array(
                'name' => $data['product_name'],
                'prdcategory_id' => $data['category'],
                'prdsubcategory_id' => $data['subcategory'],
                'prdprdcategory_id' => $data['prdcategory'],
                'brand_id' => $data['prdbrand'],
                'description' => $data['description']);
                $response = Http::post($url, $body);
                $jsonResponse = $response->object();
</code>```

here is the versions i have edited in the composer.json ,

the vesrion is still 7.4.1 even after composer install

答:
To revert back an update of a package go to composer.json, and find your package there. Change the version, and run composer install.

In your case:

```<code>"http client package name": "5.8"
</code>```

Dont forget to remove this char in the beginning of the version: ^. With the character it means at least version 5.8, but it will update to latest

Title: how to revert back an update in laravel

Body:
i have updated a http client package to the latest version.but after the update the i start getting errors on my system.how can i revert back to the previous version before the update.my laravel version of my project is 5.8 while the http client package is in the latest version (7.4.1)..

                 $body = array(
                'name' => $data['product_name'],
                'prdcategory_id' => $data['category'],
                'prdsubcategory_id' => $data['subcategory'],
                'prdprdcategory_id' => $data['prdcategory'],
                'brand_id' => $data['prdbrand'],
                'description' => $data['description']);
                $response = Http::post($url, $body);
                $jsonResponse = $response->object();

here is the versions i have edited in the composer.json ,

the vesrion is still 7.4.1 even after composer install

Body:
To revert back an update of a package go to composer.json, and find your package there. Change the version, and run composer install.

In your case:

"http client package name": "5.8"

Dont forget to remove this char in the beginning of the version: ^. With the character it means at least version 5.8, but it will update to latest


问:
ViewModel datas don't update
I have an UpdateFragment which display cards group by tags using a RecyclerView and ViewModel. In UpdateFragment I can also modify the name of the tags but I don't know why the change isn't detected by UpdateFragment until I recreate the fragment so UI don't update. The strange thing is that the MainActivity instead detect the update of the list and the code is equal.

UpdateFragment.class

```<code>public class UpdateFragment extends BaseCardFragment {

// TODO show total cards number

private static final String TAG = "UpdateFragment";

private RecyclerView recyclerView;

public UpdateFragment(List<CardWithTags> cardList, List<Tag> tagList) {
    super(cardList, tagList);
}

@Override
public void updateUI(List<CardWithTags> cardListWithTags, List<Tag> tagList) {

    RecyclerViewAdapterUpdate adapter = (RecyclerViewAdapterUpdate) recyclerView.getAdapter();
    Log.d(TAG, "Adapter:" + adapter);
    Log.d(TAG, "Cards:" + cardListWithTags);
    Log.d(TAG, "Tags:" + tagList);
    if (adapter != null && cardListWithTags != null && tagList != null) {

        adapter.setCardList(cardListWithTags);
        adapter.setTagList(tagList);
        adapter.notifyDataSetChanged();
        Log.d(TAG, ">>Update, Total cards: " + adapter.getItemCount());
        Log.d(TAG, ">>Update, Total tags: " + tagList.size());

    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_update, container, false);
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    setViewModel();

    setRecyclerView();
}

private void setViewModel() {

    Log.d(TAG, ">>SetViewModel()");

    viewModel = new ViewModelProvider(this).get(ViewModelMainActivity.class);
    viewModel.getAllCards().observe(getActivity(), cardListLoaded -> {
        cardList = cardListLoaded;
        Log.d(TAG, ">>CardList updated:" + cardList);
        updateUI(cardList, tagList);
    });

    viewModel.getAllTags().observe(getActivity(), tagListLoaded -> {
        tagList = tagListLoaded;
        Log.d(TAG, ">>TagList updated:" + tagList);
        updateUI(cardList, tagList);
    });

}

private void setRecyclerView() {

    Log.d(TAG, ">>SetRecyclerView()");
    recyclerView = getView().findViewById(R.id.recycler_view_list);

    RecyclerViewAdapterUpdate recyclerViewAdapter = new RecyclerViewAdapterUpdate(cardList, tagList,
                                                            getContext(), getLayoutInflater(),
                                                            viewModel);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext(),
                                                        RecyclerView.VERTICAL, false);
    recyclerView.setLayoutManager(layoutManager);

    recyclerView.setAdapter(recyclerViewAdapter);

}
}
</code>```

ViewModelMainActivity.class

```<code>public class ViewModelMainActivity extends AndroidViewModel {

    private static final String TAG = "ViewModelMainActivity";
    private static boolean cardListIsUpdatedWithDb = false;
    private static boolean tagListIsUpdatedWithDb = false;

    private LiveData<List<CardWithTags>> cardList = new MutableLiveData<>();
    private LiveData<List<Tag>> tagList = new MutableLiveData<>();
    private final CardDAO cardDAO;
    private final ExecutorService executor;

    public ViewModelMainActivity(@NonNull Application application) {
        super(application);

        this.cardDAO = DatabaseTaboom.getDatabase(application).cardDao();
        this.executor = Executors.newSingleThreadExecutor();
    }

    public LiveData<List<CardWithTags>> getAllCards() {

        Log.d(TAG, ">>GetAllCards()");

        if (!cardListIsUpdatedWithDb) {
            cardList = cardDAO.getAllCards();
            cardListIsUpdatedWithDb = true;
        }

        return cardList;

    }

    public LiveData<List<Tag>> getAllTags() {

        Log.d(TAG, ">>GetAllTags()");

        if (!tagListIsUpdatedWithDb) {
            tagList = cardDAO.getAllTags();
            tagListIsUpdatedWithDb = true;
        }

        return tagList;

    }

    public void insertCard(CardWithTags card) {

        Log.d(TAG, ">>InsertCard(): " + card);

        executor.execute(() -> {

            long idCard = cardDAO.insertCard(card.getCard());

            if (idCard >= 1) {
                cardListIsUpdatedWithDb = false;
                Log.d(TAG, ">>Inserted Card: " + card.getCard().getTitle());
            }

            for (Tag t: card.getTagList()) {
                long idTag = cardDAO.insertTag(t);

                CardTagCrossRef cardTagCrossRef = new CardTagCrossRef();
                cardTagCrossRef.idCard = idCard;

                if (idTag < 1) {
                    // If Tag already exist, retrieve that to get id to try insert cwt
                    idTag = cardDAO.getTag(t.getTag()).getIdTag();
                } else {
                    // New Tag
                    tagListIsUpdatedWithDb = false;
                    Log.d(TAG, ">>Inserted Tag: " + t.getTag());
                }

                cardTagCrossRef.idTag = idTag;
                long idCWT = cardDAO.insertCardWithTags(cardTagCrossRef);
                if (idCWT >= 1) {
                    Log.d(TAG, ">>Inserted CWT: [" + idCard + "," + idTag + "]");
                    // Tag linked to a card
                    cardListIsUpdatedWithDb = false;
                }
            }

        });

    }

    public void shuffle(List<CardWithTags> list) {
        if (list != null) {
            Collections.shuffle(list);
            cardList = new MutableLiveData<>(list);
            Log.d(TAG, ">>List shuffled: " + list);
        } else {
            Log.d(TAG, ">>List is null");
        }
    }

    public void updateTag(Tag tag) {

        executor.execute(() -> {
            cardDAO.updateTag(tag);
            tagListIsUpdatedWithDb = false;
            cardListIsUpdatedWithDb = false;
        });
    }

}
</code>```

RecyclerViewAdapterUpdate.class

```<code>public class RecyclerViewAdapterUpdate extends RecyclerView.Adapter<RecyclerViewAdapterUpdate.ViewHolder> {

    private static final String TAG = "RecyclerViewAdapterUpdate";

    private List<CardWithTags> cardList;
    private List<Tag> tagList;
    private Context context;
    private LayoutInflater layoutInflater;
    private ViewModelMainActivity viewModelFragment;

    public RecyclerViewAdapterUpdate(List<CardWithTags> cardList, List<Tag> tagList, Context context,
                                     LayoutInflater layoutInflater, ViewModelMainActivity viewModelFragment) {
        this.cardList = cardList;
        this.tagList = tagList;
        this.context = context;
        this.layoutInflater = layoutInflater;
        this.viewModelFragment = viewModelFragment;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_update, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        if (position == 0) {
            holder.numberOfItems.setText(String.valueOf(cardList.size()));
            holder.tagName.setText(R.string.all_cards_tag);
            holder.clearTag.setVisibility(View.GONE);
        } else {

            Tag tag = tagList.get(position - 1);
            List<CardWithTags> listOfSingleTag = new ArrayList<>();

            for (CardWithTags cwt: cardList) {
                for (Tag t: cwt.getTagList()) {
                    if (t.getTag().equals(tag.getTag()))
                        listOfSingleTag.add(cwt);
                }
            }

            holder.numberOfItems.setText(String.valueOf(listOfSingleTag.size()));
            holder.tagName.setText(tag.getTag());

            View viewDialogTag = layoutInflater.inflate(R.layout.dialog_modify_tag, null);
            EditText tagNameEditText = viewDialogTag.findViewById(R.id.tag_name_dialog);
            tagNameEditText.setText(tag.getTag());

            // In this way the dialog is created only one time
            AlertDialog dialog = new AlertDialog.Builder(context)
                    .setView(viewDialogTag)
                    .setTitle(R.string.title_modify_tag)
                    .setPositiveButton(R.string.modify, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                            String newTag = tagNameEditText.getText().toString();
                            if (!newTag.isEmpty()&& !newTag.equalsIgnoreCase(tag.getTag())) {
                                tag.setTag(newTag);
                                viewModelFragment.updateTag(tag);
                                Log.d(TAG, ">>Update TAG: " + tag.getTag() +  "->" + newTag);
                            }
                        }
                    })
                    .create();

            holder.tagName.setOnLongClickListener( view -> {
                dialog.show();
                return true;
            });

            holder.clearTag.setOnClickListener( v -> Log.d(TAG, ">>CLICKED"));
        }

    }

    @Override
    public int getItemCount() {
        if (tagList == null)
            return 1;
        return tagList.size() + 1;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        private static final String TAG = "ViewHolder";

        private final TextView numberOfItems;
        private final TextView tagName;
        private final Button clearTag;
        private final CheckBox checkBox;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            numberOfItems = itemView.findViewById(R.id.number_of_items);
            tagName = itemView.findViewById(R.id.tag_name);
            clearTag = itemView.findViewById(R.id.clear_tag);
            checkBox = itemView.findViewById(R.id.check_box);

        }

    }

    public void setCardList(List<CardWithTags> cardList) {
        this.cardList = cardList;
    }

    public void setTagList(List<Tag> tagList) {
        this.tagList = tagList;
    }
}
</code>```

I don't understand why this piece of code isn't called:

```<code> viewModel.getAllCards().observe(getActivity(), cardListLoaded -> {
        cardList = cardListLoaded;
        Log.d(TAG, ">>CardList updated:" + cardList);
        updateUI(cardList, tagList);
    });

    viewModel.getAllTags().observe(getActivity(), tagListLoaded -> {
        tagList = tagListLoaded;
        Log.d(TAG, ">>TagList updated:" + tagList);
        updateUI(cardList, tagList);
    });
</code>```

MainActivity.class method that instead is called even if is equal to that one in UpdateFragment (the activity is the same):

```<code>private void firstLoadCardList() {

        ConstraintLayout fragmentContainer = findViewById(R.id.fragment_container);
        ConstraintLayout progressBarContainer = findViewById(R.id.loading_container);
        fragmentContainer.setVisibility(View.GONE);
        progressBarContainer.setVisibility(View.VISIBLE);

        Log.d(TAG, ">>FirstLoadCardList()");

        viewModel = new ViewModelProvider(this).get(ViewModelMainActivity.class);

        checkIfDatabaseAlreadyExist();

        viewModel.getAllCards().observe(this, cardListLoaded -> {

            cardList = cardListLoaded;

            Log.d(TAG, ">>Total cards found: " + cardList.size());

            if (tagList != null /*&& appJustOpened*/) {
                appJustOpened = false;
                progressBarContainer.setVisibility(View.GONE);
                fragmentContainer.setVisibility(View.VISIBLE);
                bottomNav.setSelectedItemId(R.id.play_nav);
            }
        });

        viewModel.getAllTags().observe(this, tagListLoaded -> {

            tagList = tagListLoaded;
            Log.d(TAG, ">>Total tags found: " + tagList.size());

            // If tagList not loaded before creation of BottomNav update Fragment list
            // and cardList already loaded
            if (cardList!= null /*&& appJustOpened*/) {
                appJustOpened = false;
                progressBarContainer.setVisibility(View.GONE);
                fragmentContainer.setVisibility(View.VISIBLE);
                bottomNav.setSelectedItemId(R.id.play_nav);
            }
        });

    }
</code>```

Please stop talking about notifyDataSetChanged() in the comments, I know how it works, my problem is with ViewModel/observer. The part about observer shouldn't be called every time the lists of the ViewModel change? Thank you.

答: Finally I found the answer: the two observer methods were not equals. In fact both in the Activity and in the Fragment I wrote: viewModel.getAllCards().observe(this, cardListLoaded -> {...} but this is different if called from Activity or Fragment, in the Fragment I have to use requireActivity() instead.

Title: ViewModel datas don't update

Body:
I have an UpdateFragment which display cards group by tags using a RecyclerView and ViewModel. In UpdateFragment I can also modify the name of the tags but I don't know why the change isn't detected by UpdateFragment until I recreate the fragment so UI don't update. The strange thing is that the MainActivity instead detect the update of the list and the code is equal.

UpdateFragment.class

public class UpdateFragment extends BaseCardFragment {

// TODO show total cards number

private static final String TAG = "UpdateFragment";

private RecyclerView recyclerView;

public UpdateFragment(List<CardWithTags> cardList, List<Tag> tagList) {
    super(cardList, tagList);
}

@Override
public void updateUI(List<CardWithTags> cardListWithTags, List<Tag> tagList) {

    RecyclerViewAdapterUpdate adapter = (RecyclerViewAdapterUpdate) recyclerView.getAdapter();
    Log.d(TAG, "Adapter:" + adapter);
    Log.d(TAG, "Cards:" + cardListWithTags);
    Log.d(TAG, "Tags:" + tagList);
    if (adapter != null && cardListWithTags != null && tagList != null) {

        adapter.setCardList(cardListWithTags);
        adapter.setTagList(tagList);
        adapter.notifyDataSetChanged();
        Log.d(TAG, ">>Update, Total cards: " + adapter.getItemCount());
        Log.d(TAG, ">>Update, Total tags: " + tagList.size());

    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_update, container, false);
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    setViewModel();

    setRecyclerView();
}

private void setViewModel() {

    Log.d(TAG, ">>SetViewModel()");

    viewModel = new ViewModelProvider(this).get(ViewModelMainActivity.class);
    viewModel.getAllCards().observe(getActivity(), cardListLoaded -> {
        cardList = cardListLoaded;
        Log.d(TAG, ">>CardList updated:" + cardList);
        updateUI(cardList, tagList);
    });

    viewModel.getAllTags().observe(getActivity(), tagListLoaded -> {
        tagList = tagListLoaded;
        Log.d(TAG, ">>TagList updated:" + tagList);
        updateUI(cardList, tagList);
    });

}

private void setRecyclerView() {

    Log.d(TAG, ">>SetRecyclerView()");
    recyclerView = getView().findViewById(R.id.recycler_view_list);

    RecyclerViewAdapterUpdate recyclerViewAdapter = new RecyclerViewAdapterUpdate(cardList, tagList,
                                                            getContext(), getLayoutInflater(),
                                                            viewModel);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext(),
                                                        RecyclerView.VERTICAL, false);
    recyclerView.setLayoutManager(layoutManager);

    recyclerView.setAdapter(recyclerViewAdapter);

}
}

ViewModelMainActivity.class

public class ViewModelMainActivity extends AndroidViewModel {

    private static final String TAG = "ViewModelMainActivity";
    private static boolean cardListIsUpdatedWithDb = false;
    private static boolean tagListIsUpdatedWithDb = false;

    private LiveData<List<CardWithTags>> cardList = new MutableLiveData<>();
    private LiveData<List<Tag>> tagList = new MutableLiveData<>();
    private final CardDAO cardDAO;
    private final ExecutorService executor;

    public ViewModelMainActivity(@NonNull Application application) {
        super(application);

        this.cardDAO = DatabaseTaboom.getDatabase(application).cardDao();
        this.executor = Executors.newSingleThreadExecutor();
    }

    public LiveData<List<CardWithTags>> getAllCards() {

        Log.d(TAG, ">>GetAllCards()");

        if (!cardListIsUpdatedWithDb) {
            cardList = cardDAO.getAllCards();
            cardListIsUpdatedWithDb = true;
        }

        return cardList;

    }

    public LiveData<List<Tag>> getAllTags() {

        Log.d(TAG, ">>GetAllTags()");

        if (!tagListIsUpdatedWithDb) {
            tagList = cardDAO.getAllTags();
            tagListIsUpdatedWithDb = true;
        }

        return tagList;

    }

    public void insertCard(CardWithTags card) {

        Log.d(TAG, ">>InsertCard(): " + card);

        executor.execute(() -> {

            long idCard = cardDAO.insertCard(card.getCard());

            if (idCard >= 1) {
                cardListIsUpdatedWithDb = false;
                Log.d(TAG, ">>Inserted Card: " + card.getCard().getTitle());
            }

            for (Tag t: card.getTagList()) {
                long idTag = cardDAO.insertTag(t);

                CardTagCrossRef cardTagCrossRef = new CardTagCrossRef();
                cardTagCrossRef.idCard = idCard;

                if (idTag < 1) {
                    // If Tag already exist, retrieve that to get id to try insert cwt
                    idTag = cardDAO.getTag(t.getTag()).getIdTag();
                } else {
                    // New Tag
                    tagListIsUpdatedWithDb = false;
                    Log.d(TAG, ">>Inserted Tag: " + t.getTag());
                }

                cardTagCrossRef.idTag = idTag;
                long idCWT = cardDAO.insertCardWithTags(cardTagCrossRef);
                if (idCWT >= 1) {
                    Log.d(TAG, ">>Inserted CWT: [" + idCard + "," + idTag + "]");
                    // Tag linked to a card
                    cardListIsUpdatedWithDb = false;
                }
            }

        });

    }

    public void shuffle(List<CardWithTags> list) {
        if (list != null) {
            Collections.shuffle(list);
            cardList = new MutableLiveData<>(list);
            Log.d(TAG, ">>List shuffled: " + list);
        } else {
            Log.d(TAG, ">>List is null");
        }
    }

    public void updateTag(Tag tag) {

        executor.execute(() -> {
            cardDAO.updateTag(tag);
            tagListIsUpdatedWithDb = false;
            cardListIsUpdatedWithDb = false;
        });
    }

}

RecyclerViewAdapterUpdate.class

public class RecyclerViewAdapterUpdate extends RecyclerView.Adapter<RecyclerViewAdapterUpdate.ViewHolder> {

    private static final String TAG = "RecyclerViewAdapterUpdate";

    private List<CardWithTags> cardList;
    private List<Tag> tagList;
    private Context context;
    private LayoutInflater layoutInflater;
    private ViewModelMainActivity viewModelFragment;

    public RecyclerViewAdapterUpdate(List<CardWithTags> cardList, List<Tag> tagList, Context context,
                                     LayoutInflater layoutInflater, ViewModelMainActivity viewModelFragment) {
        this.cardList = cardList;
        this.tagList = tagList;
        this.context = context;
        this.layoutInflater = layoutInflater;
        this.viewModelFragment = viewModelFragment;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_update, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        if (position == 0) {
            holder.numberOfItems.setText(String.valueOf(cardList.size()));
            holder.tagName.setText(R.string.all_cards_tag);
            holder.clearTag.setVisibility(View.GONE);
        } else {

            Tag tag = tagList.get(position - 1);
            List<CardWithTags> listOfSingleTag = new ArrayList<>();

            for (CardWithTags cwt: cardList) {
                for (Tag t: cwt.getTagList()) {
                    if (t.getTag().equals(tag.getTag()))
                        listOfSingleTag.add(cwt);
                }
            }

            holder.numberOfItems.setText(String.valueOf(listOfSingleTag.size()));
            holder.tagName.setText(tag.getTag());

            View viewDialogTag = layoutInflater.inflate(R.layout.dialog_modify_tag, null);
            EditText tagNameEditText = viewDialogTag.findViewById(R.id.tag_name_dialog);
            tagNameEditText.setText(tag.getTag());

            // In this way the dialog is created only one time
            AlertDialog dialog = new AlertDialog.Builder(context)
                    .setView(viewDialogTag)
                    .setTitle(R.string.title_modify_tag)
                    .setPositiveButton(R.string.modify, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                            String newTag = tagNameEditText.getText().toString();
                            if (!newTag.isEmpty()&& !newTag.equalsIgnoreCase(tag.getTag())) {
                                tag.setTag(newTag);
                                viewModelFragment.updateTag(tag);
                                Log.d(TAG, ">>Update TAG: " + tag.getTag() +  "->" + newTag);
                            }
                        }
                    })
                    .create();

            holder.tagName.setOnLongClickListener( view -> {
                dialog.show();
                return true;
            });

            holder.clearTag.setOnClickListener( v -> Log.d(TAG, ">>CLICKED"));
        }

    }

    @Override
    public int getItemCount() {
        if (tagList == null)
            return 1;
        return tagList.size() + 1;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        private static final String TAG = "ViewHolder";

        private final TextView numberOfItems;
        private final TextView tagName;
        private final Button clearTag;
        private final CheckBox checkBox;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            numberOfItems = itemView.findViewById(R.id.number_of_items);
            tagName = itemView.findViewById(R.id.tag_name);
            clearTag = itemView.findViewById(R.id.clear_tag);
            checkBox = itemView.findViewById(R.id.check_box);

        }

    }

    public void setCardList(List<CardWithTags> cardList) {
        this.cardList = cardList;
    }

    public void setTagList(List<Tag> tagList) {
        this.tagList = tagList;
    }
}

I don't understand why this piece of code isn't called:

 viewModel.getAllCards().observe(getActivity(), cardListLoaded -> {
        cardList = cardListLoaded;
        Log.d(TAG, ">>CardList updated:" + cardList);
        updateUI(cardList, tagList);
    });

    viewModel.getAllTags().observe(getActivity(), tagListLoaded -> {
        tagList = tagListLoaded;
        Log.d(TAG, ">>TagList updated:" + tagList);
        updateUI(cardList, tagList);
    });

MainActivity.class method that instead is called even if is equal to that one in UpdateFragment (the activity is the same):

private void firstLoadCardList() {

        ConstraintLayout fragmentContainer = findViewById(R.id.fragment_container);
        ConstraintLayout progressBarContainer = findViewById(R.id.loading_container);
        fragmentContainer.setVisibility(View.GONE);
        progressBarContainer.setVisibility(View.VISIBLE);

        Log.d(TAG, ">>FirstLoadCardList()");

        viewModel = new ViewModelProvider(this).get(ViewModelMainActivity.class);

        checkIfDatabaseAlreadyExist();

        viewModel.getAllCards().observe(this, cardListLoaded -> {

            cardList = cardListLoaded;

            Log.d(TAG, ">>Total cards found: " + cardList.size());

            if (tagList != null /*&& appJustOpened*/) {
                appJustOpened = false;
                progressBarContainer.setVisibility(View.GONE);
                fragmentContainer.setVisibility(View.VISIBLE);
                bottomNav.setSelectedItemId(R.id.play_nav);
            }
        });

        viewModel.getAllTags().observe(this, tagListLoaded -> {

            tagList = tagListLoaded;
            Log.d(TAG, ">>Total tags found: " + tagList.size());

            // If tagList not loaded before creation of BottomNav update Fragment list
            // and cardList already loaded
            if (cardList!= null /*&& appJustOpened*/) {
                appJustOpened = false;
                progressBarContainer.setVisibility(View.GONE);
                fragmentContainer.setVisibility(View.VISIBLE);
                bottomNav.setSelectedItemId(R.id.play_nav);
            }
        });

    }

Please stop talking about notifyDataSetChanged() in the comments, I know how it works, my problem is with ViewModel/observer. The part about observer shouldn't be called every time the lists of the ViewModel change? Thank you.