Where is my button?

“Where is my button? Why is it inactive? ”How often can a programmer hear these words from users of his product? Most likely, more than very often, in order to think, or maybe the product itself should answer this question of users.

Here's what an ordinary inactive button looks like, which, for some reason, is currently not available to the user:

Inactive silent button
It is silent, not interactive and does not provide the user with the slightest information about why it is in this state and under what conditions it will become active . And here is what a “ennobled”, more informative inactive button might look like:

Inactive ennobled button

What is the salt, you ask? But how to describe the rules in the Python programming language so that these rules simultaneously calculate the activity status of the button and provide a report on the reason if the button should be deactivated, I would like to tell in this article.

Using a self-made library , you can describe the following rule in the Python programming language:

from rules import _and_, _or_
# The rule
def can_user_add_comment(user, topic):
    return _and_(
        lambda: (user, “Вы не авторизованы”),
        lambda: (user.is_status_active(), “Ваша учетная запись заблокирована”),
        lambda: _or_(
            lambda: (user.is_in_admin_group(), “Вы не администратор”),
            lambda: _and_(
                lambda: (topic.is_status_open(), “тема закрыта”),
                lambda: (user.has_enough_karma_to_add_comment(), “у Вас не достаточно кармы для комментирования”),
                lambda: (user.is_below_comments_per_minute_quota(), “Вы комментируете слишком интенсивно, повторите попытку через пару минут”),
            ),
        ),
    )

The logical operation classes accept operands wrapped in lambda, which will be called to calculate values ​​if necessary. Those. calculations occur according to a “shortened scheme”, for example, it _and_calculates the values ​​of its arguments to the first False, _or_to the first True. Each operand consists of the actual tested value (the first element of the tuple) and the message (the second element of the tuple), which is used when the tested value has accepted the value False. Also, if necessary, you can omit messages for irrelevant parts of the rule (operands) from the point of view of informing the user.

Then use this rule, for example in the Mako template, as follows:

<%
    user = get_authenticated_user()
    granted = can_user_add_comment(user, current_topic)
%>

As you can see from the example, the object grantedobtained as a result of the function call can_user_add_comment()in the Boolean context reports the status of the button’s activity, and in the string context it reports the reason if it returned the value in the Boolean context False. The reason for the inactivity of the button is recorded in it titleand retrieved by the user when you hover over it with the mouse cursor. By default, only specific messages get into the report, the result of which rule calculation turned out to be False. But it is also possible to generate a full tree-like report on which logical branches of the entire rule returned a value False. To do this, call granted.build_report()or granted.build_html_report().

In the arsenal of available library operation _and_, _or_, _not_and _true_.

As a result of a network search, I was not able to find anything similar, so I had to write my own library. The first version was released recently. It will be very interesting for me to learn about your experience in solving this small, but sometimes quite relevant, task.

Also popular now: