Опубликован: 27.01.2016 | Уровень: для всех | Доступ: платный
Лекция 9:

Обновление, демонстрация и удаление пользователей

Заключение

Мы прошли долгий путь с момента введения контроллера Users в Разделе 5.4. Те пользователи даже не могли зарегистрироваться; теперь же пользователи могут зарегистрироваться, войти в систему, выйти, просматривать свои профили, редактировать их параметры, и видеть список всех пользователей, а некоторые из них могут даже удалять других пользователей.

Остальная часть этой книги будет опираться на ресурс Users (и связанную с ним аутентификационную систему) чтобы сделать сайт с Twitter-подобными микросообщениями (Глава 10) и потоком сообщений пользователей за которыми следит данный пользователь (Глава 11). Эти главы представят некоторые из наиболее мощных возможностей Rails, включая моделирование данных с has_many и has_many through.

Прежде чем двигаться дальше, убедитесь, что объединили все изменения в мастер ветку:

$ git add .
$ git commit -m "Finish user edit, update, index, and destroy actions"
$ git checkout master
$ git merge updating-users

Вы также можете задеплоить приложение и даже заполнить продакшен базу данных образцами пользователей (применив задачу pg:reset для сброса продакшен базы данных):

$ git push heroku
$ heroku pg:reset DATABASE
$ heroku run rake db:migrate
$ heroku run rake db:populate

Для того чтобы увидеть изменения вам возможно придется принудительно рестартовать приложение на Heroku:

$ heroku restart

Стоит также отметить, что в этой главе мы в последний раз имели необходимость в установке гема. Для справки, окончательный вариант Gemfile показан в Листинге 9.47. (Необязательные гемы которые могут оказаться системозависимыми закомментированы. Вы можете раскомментировать их для того чтобы посмотреть работают ли они на вашей системе.)

source 'https://rubygems.org'
ruby '2.0.0'
#ruby-gemset=railstutorial_rails_4_0

gem 'rails', '4.0.2'
gem 'bootstrap-sass', '2.3.2.0'
gem 'bcrypt-ruby', '3.1.2'
gem 'faker', '1.1.2'
gem 'will_paginate', '3.0.4'
gem 'bootstrap-will_paginate', '0.0.9'

group :development, :test do
  gem 'sqlite3', '1.3.8'
  gem 'rspec-rails', '2.13.1'
  # The following optional lines are part of the advanced setup.
  # gem 'guard-rspec', '2.5.0'
  # gem 'spork-rails', '4.0.0'
  # gem 'guard-spork', '1.5.0'
  # gem 'childprocess', '0.3.6'
end

group :test do
  gem 'selenium-webdriver', '2.35.1'
  gem 'capybara', '2.1.0'
  gem 'factory_girl_rails', '4.2.0'
  gem 'cucumber-rails', '1.4.0', :require => false
  gem 'database_cleaner', github: 'bmabey/database_cleaner'

  # Uncomment this line on OS X.
  # gem 'growl', '1.0.3'

  # Uncomment these lines on Linux.
  # gem 'libnotify', '0.8.0'

  # Uncomment these lines on Windows.
  # gem 'rb-notifu', '0.0.4'
  # gem 'win32console', '1.3.2'
  # gem 'wdm', '0.1.0'
end

gem 'sass-rails', '4.0.1'
gem 'uglifier', '2.1.1'
gem 'coffee-rails', '4.0.1'
gem 'jquery-rails', '3.0.4'
gem 'turbolinks', '1.1.1'
gem 'jbuilder', '1.0.2'

group :doc do
  gem 'sdoc', '0.3.20', require: false
end

group :production do
  gem 'pg', '0.15.1'
  gem 'rails_12factor', '0.0.2'
end	
Листинг 9.47. Окончательный вариант Gemfile для примера приложения.

Упражнения

  1. Направив запрос PATCH напрямую к методу update как это показано в Листинге 9.48, проверьте что атрибут admin не может быть отредактирован через веб. Вначале получите провальный тест и лишь потом добейтесь его прохождения. (Подсказка: Вашим первым шагом должно стать добавление admin в список разрешенных параметров в user_params.)
  2. Организуйте открытие Gravatar ссылки "change" из Листинга 9.3 в новом окне (или вкладке). Подсказка: Ищите в сети; вы должны найти один простой и надежный метод с участием так называмого _blank.
  3. Текущий тест аутентификации проверяет что навигационные ссылки, такие как "Profile" и "Settings" появляются когда пользователь входит. Добавьте тест проверяющий что эти ссылки не видны невошедшим пользователям.
  4. Примените тестовый хелпер sign_in из Листинга 9.6 в как можно большем количестве мест.
  5. Удалите дублирующийся код формы отрефакторив new.html.erb и edit.html.erb представления с помощью партиала из Листинга 9.49. Обратите внимание на то, что вам придется явно передать пременную формы f в виде локальной переменной, как это показано в Листинге 9.50. Вам также понадобится обновить тесты, поскольку формы не останутся в точности такими же; найдите небольшую разницу между ними и обновите тесты соответствующим образом.
  6. Зарегистрированным пользователям совершенно незачем иметь доступ к new и create действиям контроллера Users. Организуйте для таких пользователей переадресацию в корневой URL, при попытке обратиться к этим страницам.
  7. Изучите объект request вставляя некоторые методы перечисленные в Rails API9http://api.rubyonrails.org/v4.0.0/classes/ActionDispatch/Request.html в шаблон сайта. (Обращайтесь к Листингу 7.1, если застрянете.)
  8. Напишите тест для проверки того, что дружелюбная переадресация направляет к данному URL только в первый раз. На последующие попытки входа, адрес перенаправления должени меняться на дефолтный (т.e., страницу профиля). См. подсказку в Листинге 9.51 (и подсказкой в данном случае я называю решение).
  9. Модифицируйте действие destroy так, чтобы предотвратить уничтожение административными пользователями самих себя. (Начните с написания теста.)
require 'spec_helper'

describe "User pages" do
  .
  .
  .
  describe "edit" do
    .
    .
    .
    describe "forbidden attributes" do
      let(:params) do
        { user: { admin: true, password: user.password,
                  password_confirmation: user.password } }
      end
      before do
        sign_in user, no_capybara: true
        patch user_path(user), params
      end
      specify { expect(user.reload).not_to be_admin }
    end
  end
end
Листинг 9.48. Тестирование того что атрибут admin запрещен к редактированию через веб. spec/requests/user_pages_spec.rb
<%= render 'shared/error_messages' %>

<%= f.label :name %>
<%= f.text_field :name %>

<%= f.label :email %>
<%= f.text_field :email %>

<%= f.label :password %>
<%= f.password_field :password %>

<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
Листинг 9.49. Партиал для полей форм new и edit. app/views/users/_fields.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="span6 offset3">
    <%= form_for(@user) do |f| %>
      <%= render 'fields', f: f %>
      <%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
    <% end %>
  </div>
</div></example>
<example number="9." title="" type="listing">
Листинг 9.50. Представление для создания нового пользователя с партиалом. app/views/users/new.html.erb
require 'spec_helper'

describe "Authentication" do
  .
  .
  .
  describe "authorization" do

    describe "for non-signed-in users" do
      .
      .
      .
      describe "when attempting to visit a protected page" do
        before do
          visit edit_user_path(user)
          fill_in "Email",    with: user.email
          fill_in "Password", with: user.password
          click_button "Sign in"
        end

        describe "after signing in" do

          it "should render the desired protected page" do
            expect(page).to have_title('Edit user')
          end

          describe "when signing in again" do
            before do
              delete signout_path
              visit signin_path
              fill_in "Email",    with: user.email
              fill_in "Password", with: user.password
              click_button "Sign in"
            end

            it "should render the default (profile) page" do
              expect(page).to have_title(user.name)
            end
          end
        end
      end
    end
    .
    .
    .
  end
end
Листинг 9.51. Тест для перенаправления на дефолтную страницу после дружелюбной переадресации. spec/requests/authentication_pages_spec.rb
Вадим Обозин
Вадим Обозин

Здравствуйте, записался на курс. При этом ставил галочку на "обучаться с тьютором". На email пришло письмо, о том, что записался на самостоятельное изучение курса. Как выбрать тьютора?

Акбар Ахвердов
Акбар Ахвердов
Россия, г. Москва
Артём Зайцев
Артём Зайцев
Украина, ДНР