Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
What would be the best way to apply logic?
Message
De
11/09/2009 08:14:20
Hilmar Zonneveld
Independent Consultant
Cochabamba, Bolivie
 
 
Information générale
Forum:
Visual FoxPro
Catégorie:
Gestionnaire d'écran & Écrans
Versions des environnements
Visual FoxPro:
VFP 9 SP1
OS:
Windows XP
Network:
Windows 2003 Server
Database:
MS SQL Server
Divers
Thread ID:
01423463
Message ID:
01423625
Vues:
51
>I think it may be interesting, so pease expand on your idea.
>
>P.S. Somehow I missed this message till now.

Well, the basic ideas are (1) to postpone all validation (not do any validation just because the user leaves a textbox), and (2) have all rules, or most of them, stored in a table for easy maintenance.

The reasons for (1) are multiple: Easy to program; lets user input data in any order; avoids clumsy situations when validations are done on more than one field.

My last version of the function has fields for:
  • The "table" (really, this refers to a set of rules that are evaluated together; but quite often, coincides with a table)
  • The rule itself;
  • The corresponding error message;
  • Specifying whether a rule is to be strict, or a warning only (i.e., the user can still save).

    Also, I recently added support for variables, so that a complicated expression or a slow lookup doesn't have to be done several times, for several rules.

    The error message is in a field called "Spanish"; the original idea was to have the possibility of adding fields for error messages in different languages.

    The function itself, I stored it in database stored procedures.

    In a form, the framework invoked Form.Valid() (note that this is a method added by the framework) when the user tried to save the current record; in this method I put something like
    return RecordValid("ArticleMain")
    A typical validation record for table ArticleMain might look like this:
    Table = articlemain
    Order = (empty; I seldom used this)
    Rule = not empty(ArtName)
    Spanish = A description is required.
    * Including the period at the end.
    Level = (empty)
    * This means a strict rule; a "W" would mean a warning

    Additional records would be added for additional validation rules. I created a form to edit the validation table; I won't distribute the form, because it relies heavily on a specific framework.
    Table structure - table Validation:
    Fields:
    table C(30) && Table, or in general, set of rules
    Order I && Allows to specify an order for evaluating rules. Especially important for variables.
    Rule M  && The actual rule, using VFP syntax - e.g. NOT EMPTY(ClientCode)
    Spanish M  && The corresponding error message, if the rule is violated
    varname M && Allows evaluation of variables
    comments M && Comments used by the programmer only
    Warning L && I think this field is now obsolete
    Level C(1) && Empty if rule is strict; V for a variable; I to ignore rule without having to erase it; W for warning only
    
    Indices:
    Table on table
    Order on order
    Deleted on deleted()
    Rule on left(rule, 30)
    Spanish on left(Spanish, 30)
    MainOrder on table+IIF(level="V","0","1")+BINTOC(order)
    
    It might be better to delete the index on deleted().
    
    
    I had the following function in database stored procedures.
    
    **********************************************************************
    FUNCTION RecordValid(tcTableName, llEvaluateAllRules)
    	* Record validation.
    	* Meant to be invoked from form.valid(tablename).
    	* Can also be invoked from other places, for instance, triggers.
    
    	tcTableName = lower(tcTableName)
    	llEvaluateAllRules = .T.  && Override second parameter.
    
    	* save and change settings
    	local lnOldAlias, lcOldExact, lcExpression
    	lnOldAlias = select()
    	lcOldExact = set("exact")
    	set exact off
    
    	* open validation table
    	if used("validation")
    		select validation
    	else
    		select 0
    		use validation again
    	endif
    	set order to "mainorder"
    
    	* evaluate all errors defined in rules table
    	local lcErrorText, llError, lcVarName
    	lcErrorText = ""
    	tcTableName = padr(tcTableName, len(Table))
    	seek tcTableName
    	scan while table = tcTableName
    		select (lnOldAlias)
    		lcExpression = strtran(Validation.Rule, chr(13) + chr(10), space(1))
    		do case
    		case Validation.Level = "V" && Variable, que se debe evaluar
    			lcVarName = alltrim(Validation.VarName)
    			local &lcVarName
    			&lcVarName = evaluate(lcExpression)
    		case Validation.Level # "I" && Evaluar la regla de validación. Omitir el caso "Ignorar".
    			if not evaluate(lcExpression)
    				lcErrorText = lcErrorText + iif(Validation.Level = "W", "Advertencia: ", "Error: ") + Validation.Spanish
    				if not Validation.Level = "W"
    					llError = .T.
    				endif
    				if llEvaluateAllRules
    					lcErrorText = lcErrorText + chr(13)
    				else
    					exit
    				endif
    			endif
    		endcase
    		select Validation
    	endscan
    
    	* show error message
    	if not empty(lcErrorText)
    		if llError
    			* Can't save; error saving
    			MessageBox("No se pudo guardar:" + chr(13) + chr(13) + lcErrorText,;
    				16, "Error al guardar")
    		else
    			* Warning; do you want to save anyway?
    			llError = MessageBox("Advertencia al guardar:" + chr(13) + chr(13) + lcErrorText;
    				+ chr(13) + "¿Quiere guardar de todos modos?",;
    				4 + 48 + 256, "Advertencia al guardar") # 6
    		endif
    		** Mensaje combinado, anterior		
    *!*			MessageBox(iif(llError, "No se pudo guardar:", "Advertencia al guardar:") + chr(13) + chr(13);
    *!*				+ lcErrorText + iif(llError, "", chr(13) + "Se guardaron los cambios."),;
    *!*				16, iif(llError, "Error al guardar", "Advertencia al guardar"))
    		*MessageBox(iif(llError, "Can't save:", "Warning on save:") + chr(13) + chr(13);
    		*	+ lcErrorText + iif(llError, "", chr(13) + "Changes saved."),;
    		*	16, iif(llError, "Error on save", "Warning on save"))
    	endif
    
    	* restore environment and return success status
    	use in validation
    	select (lnOldAlias)
    	set exact &lcOldExact
    	return not llError
    ENDFUNC
    Difference in opinions hath cost many millions of lives: for instance, whether flesh be bread, or bread be flesh; whether whistling be a vice or a virtue; whether it be better to kiss a post, or throw it into the fire... (from Gulliver's Travels)
  • Précédent
    Répondre
    Fil
    Voir

    Click here to load this message in the networking platform