«1. Обзор

В этой статье мы собираемся создать профиль для пользователя нашего приложения Reddit, чтобы позволить им настраивать пользовательские настройки.

Цель проста — вместо того, чтобы заставлять пользователя вводить одни и те же данные каждый раз, когда он планирует новую публикацию, они могут установить это один раз — в настройках своего профиля. Конечно, пользователь всегда может настроить эти параметры для каждого сообщения, но идея в том, что это не обязательно.

2. Объект предпочтений

В целом, большинство вещей, которые теперь можно настроить в приложениях, станут глобально настраиваемыми в профиле пользователя.

Во-первых, давайте начнем с объекта Preference:

@Entity
public class Preference {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String email;

    private String subreddit;

    private boolean sendReplies;

    // for post re-submission
    private int noOfAttempts;
    private int timeInterval;
    private int minScoreRequired;
    private int minUpvoteRatio;
    private boolean keepIfHasComments;
    private boolean deleteAfterLastAttempt;
}

Итак, что мы можем теперь настроить? Проще говоря — значения по умолчанию практически для всех параметров приложения.

Мы также храним электронную почту пользователя, чтобы он мог получать уведомления о том, что происходит с его публикациями.

Теперь давайте свяжем предпочтения с пользователем:

@Entity
public class User {
    ...
    
    @OneToOne
    @JoinColumn(name = "preference_id")
    private Preference preference;
}

Как видите, у нас есть простое взаимно-однозначное отношение между пользователем и предпочтением.

3. Простая страница профиля

Во-первых, давайте создадим нашу простую страницу профиля:

<form >
    <input type="hidden" name="id" />
    <input name="email" type="email"/>
    <input name="subreddit"/>
    ...
   <button onclick="editPref()" >Save Changes</button>
</form>
<script>
$(function() {
    $.get("user/preference", function (data){
        $.each(data, function(key, value) {
            $('*[name="'+key+'"]').val(value);
        });
    });
});
function editPref(){
    var data = {};
	$('form').serializeArray().map(function(x){data[x.name] = x.value;});
	$.ajax({
        url: "user/preference/"+$('input[name="id"]').val(),
        data: JSON.stringify(data),
        type: 'PUT',
        contentType:'application/json'
    }).done(function() { window.location.href = "./"; })
      .fail(function(error) { alert(error.responseText); }); 
}
</script>

Здесь ничего особенного — просто немного HTML и JavaScript.

Давайте также добавим быструю ссылку на новый профиль:

<h1>Welcome, <a href="profile" sec:authentication="principal.username">username</a></h1>

4. API

А вот и контроллер для создания и редактирования пользовательских настроек:

@Controller
@RequestMapping(value = "/user/preference")
public class UserPreferenceController {

    @Autowired
    private PreferenceRepository preferenceReopsitory;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public Preference getCurrentUserPreference() {
        return getCurrentUser().getPreference();
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    @ResponseStatus(HttpStatus.OK)
    public void updateUserPreference(@RequestBody Preference pref) {
        preferenceReopsitory.save(pref);
        getCurrentUser().setPreference(pref);
    }
}

Наконец, нам нужно убедитесь, что при создании пользователя его настройки также инициализируются:

public void loadAuthentication(String name, OAuth2AccessToken token) {
    ...
    Preference pref = new Preference();
    preferenceReopsitory.save(pref);
    user.setPreference(pref);
    userReopsitory.save(user);
    ...   
}

5. Загрузка/использование настроек

Теперь — давайте посмотрим, как использовать эти настройки и заполнять их всякий раз, когда они нужны. обязательный.

Мы начнем с главной страницы Расписание публикаций, где мы загрузим настройки пользователя:

$(function() {
    $.get("user/preference", function (data){
        $.each(data, function(key, value) {
            $('*[name="'+key+'"]').val(value);
        });
    });
});

6. Тестирование и заключение

Мы почти закончили — нам просто нужно реализовать некоторые базовые интеграционные тесты для нового объекта профиля, который мы только что представили.

По большей части мы собираемся просто расширить существующий базовый тест на устойчивость и унаследовать от него ряд тестов.

Наконец, мы можем завершить новую функциональность профиля пользователя — теперь пользователи могут настраивать свои собственные предпочтения.