Olá
No post anterior, demos início ao trabalho de fazer com que o Delphi interagisse com o Parse (Back4app).
Classe TParseUser
Agora, iremos implementar novas funcionalidades. E a primeira tarefa será a de disponibilizar acesso às funções de usuários (login, logout…). Para isso, uma nova classe será incluída no projeto, a TParseUser:
[sourcecode language=”Delphi”]
TParseUser = class(TInterfacedObject, IParseUser)
private
FUserName: string;
FEmail: string;
FPassword: string;
Obj: TJSonObject;
CustomField: TDictionary<string,string>;
Parse: IDelphiParse;
Query: IParseQuery;
procedure ValidatesNewUser;
procedure FormatParams;
procedure ProcessResponse(AResponse: string);
public
constructor Create;
destructor Destroy; override;
procedure SetUserName(Value: string);
procedure SetEmail(Value: string);
procedure SetPassword(Value: string);
function GetSessionToken: string;
procedure Add(Key, Value: Variant);
function Login(UserName, Password: string): string;
function LogOut: string;
function GetCurrencyUser: string;
function SignUpInBackground: string;
end;
…
function TParseUser.Login(UserName, Password: string): string;
var
Params: string;
begin
Parse.SetRevocableSession(True);
Params := Format(‘%s=%s&%s=%s’, [
TURI.URLEncode(‘username’),
TURI.URLEncode(UserName),
TURI.URLEncode(‘password’),
TURI.URLEncode(Password)]);
Result := Parse.Get([‘login’], nil, Params).ResponseAsString();
ProcessResponse(Result);
end;
function TParseUser.LogOut: string;
begin
Parse.SetRevocableSession(False);
Result := Parse.Post([‘logout’]).ResponseAsString();
ProcessResponse(Result);
end;
function TParseUser.GetCurrencyUser: string;
begin
if Parse.GetSessionToken.IsEmpty then
Exit;
Parse.SetRevocableSession(False);
Result := Parse.Get([‘users’, ‘me’]).ResponseAsString();
ProcessResponse(Result);
end;
…
// inserir novo user
function TParseUser.SignUpInBackground: string;
begin
ValidatesNewUser;
FormatParams;
Parse.SetRevocableSession(True);
Result := Parse.Post([‘users’], Obj).ResponseAsString();
ProcessResponse(Result);
end;
…
[/sourcecode]
Perceba que agora temos os métodos necessários para logar, deslogar e inserir um novo usuário. Por enquanto, no que se refere aos usuários, é o que será entregue. Futuramente, voltaremos a esta parte do código para implementar demais recursos disponibilizados pela API.
Alterei nosso formulário de testes:
No botão de inserir usuários temos:
[sourcecode language=”Delphi”]
var
User: IParseUser;
Resultado: string;
begin
User := TParseUser.Create;
User.SetUserName(edUserName.Text);
User.SetPassword(edPassword.Text);
User.SetEmail(edEmail.Text);
Resultado := User.SignUpInBackground;
memResult.Lines.Clear;
memResult.Lines.Add(Resultado);
memResult.Lines.Add(‘Token: ‘ + User.GetSessionToken);
end;
[/sourcecode]
Simples, não?! É possível até mesmo pegar a sessão atual do usuário logado (linha 12).
Abaixo, código dos botões de login e logout:
[sourcecode language=”Delphi”]
//login
var
User: IParseUser;
Resultado: string;
begin
User := TParseUser.Create;
Resultado := User.Login(edUsername.Text, edPassword.Text);
memResult.Lines.Clear;
memResult.Lines.Add(Resultado);
memResult.Lines.Add(‘Token: ‘ + User.GetSessionToken);
end;
//logout
var
User: IParseUser;
Resultado: string;
begin
User := TParseUser.Create;
Resultado := User.LogOut;
memResult.Lines.Clear;
memResult.Lines.Add(Resultado);
memResult.Lines.Add(‘Token: ‘ + User.GetSessionToken);
end;
[/sourcecode]
Sem segredo até aqui.
Refatorando TParseQuery
Nesta classe, trabalhamos as querys da API. Eu vinha criando uma lista (TList
Para contornar este problema, resolvi então, eliminar todas estas listas e criar uma classe para receber estas opções, ou seja, foi criada a TConstraints:
[sourcecode language=”Delphi”]
TConstraints = class
private
List: TObjectDictionary<TConstraintType, TList<TParams>>;
procedure ValidatesKey(Key: string; Params: TList<TParams>);
public
constructor Create;
destructor Destroy; override;
procedure AddParams(Key, Value: string; ConstraintType: TConstraintType;
FieldType: TFieldType = ftString);
procedure AddConstraint(ConstraintType: TConstraintType);
function Items(Key: TConstraintType): TList<TParams>;
function CountWhere: Integer;
end;
[/sourcecode]
O destaque fica por conta da lista (List) do tipo TObjectDictionary. Sendo deste tipo, no método Create, já adicionamos todas as querys que desejamos trabalhar:
[sourcecode language=”Delphi”]
constructor TConstraints.Create;
begin
inherited;
List := TObjectDictionary<TConstraintType, TList<TParams>>.Create([doOwnsValues]);
Self.AddConstraint(ctEqualTo);
Self.AddConstraint(ctStartsWith);
Self.AddConstraint(ctContains);
Self.AddConstraint(ctLessThan);
Self.AddConstraint(ctGreaterThan);
Self.AddConstraint(ctOthers);
end;
[/sourcecode]
Na classe TParseQuery, basta criar um objeto do tipo TConstraints:
[sourcecode language=”Delphi”]
constructor TParseQuery.Create;
begin
inherited;
Constraints := TConstraints.Create;
[/sourcecode]
A partir de agora, acionaremos o objeto criado para manipular cada query como, por exemplo, ao adicionar um novo parâmetro no EqualTo:
[sourcecode language=”Delphi”]
procedure TParseQuery.WhereEqualTo(Key, Value: string);
begin
Constraints.AddParams(Key, Value, ctEqualTo);
end;
[/sourcecode]
Voltando ao formulário de teste:
Dando uma conferida no botão LessThan, temos:
[sourcecode language=”Delphi”]
var
Parse: IParseObject;
Response: string;
begin
Text := InputBox(‘LessThan test in the Level field’, ‘Text:’,”);
Parse := TParseObjects.Create(‘Mensagens’);
Parse.WhereLessThan(‘level’, Text, ftNumber);
Response := Parse.GetInBackGround;
LerResponse(Response);
end;
[/sourcecode]
Foi necessário inserir um terceiro parâmetro, FieldType, na requisição. Visto que alguns tipos, para funcionarem, necessitam desta informação.
Resumo
Foi dado início à implementação da classe responsável pelo controle dos usuários. Por enquanto, apenas adicionar, logar e deslogar foram implementadas.
Diversas alterações tornaram-se necessárias com a implementação de novas funcionalidades. Como por exemplo, a necessidade de algumas querys exigirem o tipo de dado que é passado no parâmetro.
A Classe TConstraints veio para facilitar o processo de adicionar uma nova query. Não temos mais a preocupação com instanciação e liberação de memória das listas criadas para cada função. Ainda não estou 100% satisfeito, e por isso, irei voltar para rever a questão das fórmulas de cada query. Talvez movê-las de TParseQuery para TConstraints, ou até mesmo, criar uma nova classe.
Para conferir o código completo, baixe os fontes no Github.
Abraços.
Olá Luiz,
Muito legal este teu exemplo de utilização no Delphi do back4app, parabéns!
Queria saber se você tem algum exemplo de coluna do tipo POINTER, queria construir uma classe que tivesse um apontamento para outras, por exemplo um item venda que tem um produto, entendeu?
Olá Edson,
Antes de mais nada, obrigado pela visita.
A necessidade que me levou a ir para o Parse exigia apenas trabalho com dados primitivos (int, double, etc.), então não cheguei a explorar colunas do tipo que você mencionou. Sugiro que dê uma olhada no manual do serviço. Lá poderá encontrar o que procura.
Parabéns Luiz
Estou explorando as possibilidades de uso desse serviço.
Muito bom mesmo, bem explicado.
Você vai dar continuidade em novas funcionalidades?
Olá Ismael
Atualmente estou utilizando o Firebase. Vou ver se consigo um tempo para criar um post mostrando como fiz a conexão entre o Delphi e este serviço.
Abs.