Мультиблог на Ruby on Rails. Создание личного кабинета. Урок 9. Часть 1.

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

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

rails g controller Profiles

Сразу прописываем маршрут: 

get 'profiles/index', to: 'profiles#index', as: 'cabinet'

В контролере мы будем получать записи текущего пользователя:

def index
  @user = User.find(current_user.id)
  @posts = @user.post
end

Здесь мы сначала получаем объект текущего пользователя, а потом все посты, которые ему принадлежат. Работает это всё благодаря тому, что в модели User прописана связь: 

has_many :post

Ну ещё добавим метод before_action, чтобы возможность создавать пост была только у авторизованного пользователя:

before_action :authenticate_user!, only: [:index]

Подробнее об этом методе было написано в предыдущем уроке

Шаблон для личного кабинета

В личном кабинете мы будем выводить только те посты, которые принадлежат текущему авторизованному пользователю. Плюс слева у нас будет небольшой сайдбар, в котором будут ссылки на создание новой статьи и разлогинивание. Что касается вывода постов, то у нас уже всё готово, поскольку чуть ранее, когда мы выводили посты на главной, то использовали частичное представление из _post.html.erb Стало быть, можем точно так же использовать его для вывода постов в личном кабинете. Итоговый шаблон получился таким:

<% content_for :title do %>
  Записи пользователя <%= @user.email %>
<% end %>

<main role="main" class="container">
  <div class="row">
    <% if params[:action] == 'index' %>
      <div class="col-md-3 mb-3 mt-1">
        <div class="card">
          <div class="card-body">
            <div class="h2">
              <!-- Email автора -->
              <%= @user.email %>
            </div>
          </div>

          <ul class="list-group list-group-flush">
            <li class="list-group-item">
              <a href="<%= url_for(new_post_path) %>" style="text-decoration:underline">Создать пост</a>
            </li>
            <li class="list-group-item">
              <a href="<%= url_for(edit_user_registration_path) %>" style="text-decoration:underline">Смена пароля</a><br />
            </li>
            <li class="list-group-item">
              <div class="h6 text-muted">
                <!-- Количество записей -->
                Записей: <%= @posts.count %>
              </div>
            </li>
          </ul>
        </div>

        <div class="logout">
          <%= button_to "logout", destroy_user_session_path, { method: :delete, class: 'btn btn-danger' } %>
        </div>
      </div>
    <% end %>

    <div class="col-md-9">
      <!-- Начало блока с отдельным постом -->
      <% @posts.each do |post| %>
        <%= render 'posts/post', post: post %>
      <% end %>
      <!-- Остальные посты -->
      <!-- Здесь будет постраничная навигация паджинатора -->
    </div>
  </div>
</main>

Особо комментировать тут нечего, кроме того, что у вас может возникнуть вопрос, зачем здесь дополнительное условие для отображения сайдбара. А всё дело в том, что данный шаблон будет одновременно использоваться как для личного кабинета, так и для отображения постов. И там и там, будут отображаться посты определённого пользователя, но только во втором случае сайдбар нам не будет нужен. 

Ну и ещё я добавил стилей для кнопки разлогинивания, чтобы она отлипла от сайдбара и стала по центру: 

.logout {
  margin-top: 20px;
  text-align: center;
}

Страница просмотров записей пользователя

Так же нам понадобится реализовать функционал просмотра постов определённого пользователя. Здесь всё проще, поскольку у нас уже есть похожий функционал и аналогичный шаблон; осталось только это всё грамотно внедрить. Создаём маршрут:

get 'profiles/show/:id', to: 'profiles#show', as: 'profile'

Соответствующий action для контролера Profiles:

def show
  @user = User.find(params[:id])
  @posts = @user.post
  render :index
end

Здесь я указал что рендерить будем именно шаблон index, потому что он у нас, помимо сайдбара, абсолютно такой же, как и для личного кабинета. 

Контролер и view готовы, теперь осталось добавить ссылку на сам профиль пользователя. Для этого, в файле _post.html.erb вместо строчки:

<a href="#"><%= post.user.email %></a>

пропишем:

<a href="<%= url_for(profile_path(id: post.user.id)) %>"><%= post.user.email %></a>

Теперь, если щёлкнуть по имени пользователя, мы таким образом отфильтруем посты по автору, что нам и было нужно. Весь код данного урока, как и всегда, в коммите

Статья получалась довольно объёмной, поэтому я разделил её на две части. Вскоре будет вторая, где мы сделаем возможность редактировать и удалять статью; а так же проставим все необходимые ссылки для этих действий.