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

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

Уничтожение пользователей

Теперь, когда список пользователей завершен, осталось лишь одно каноничное REST действие: destroy. В этом разделе мы добавим ссылки для удаления пользователей, как это показано на 12" type="image" />, и определим destroy действие необходимое для выполнения удаления. Но мы начнем с создания класса уполномоченных на это административных пользователей.

Набросок списка пользователей с удаляющими ссылками.

Рис. 9.12. Набросок списка пользователей с удаляющими ссылками.

Административные пользователи

Мы будем идентифицировать привилегированных пользователей с правами администратора посредством булевого атрибута admin в модели User, что, как мы увидим, автоматически приведет нас к методу admin? для проверки административного статуса. Мы можем написать тесты для этого атрибута, как в Листинге 9.38.

require 'spec_helper'

describe User do
  .
  .
  .
  it { should respond_to(:authenticate) }
  it { should respond_to(:admin) }

  it { should be_valid }
  it { should_not be_admin }

  describe "with admin attribute set to 'true'" do
    before do
      @user.save!
      @user.toggle!(:admin)
    end

    it { should be_admin }
  end
  .
  .
  .
end
Листинг 9.38. Тесты для атрибута admin. spec/models/user_spec.rb

Здесь мы использовали метод toggle! для изменения атрибута admin от false к true. Отметим также, что строка

it { should be_admin }

подразумевает (через булеву конвенцию RSpec), что пользователь должен иметь булев метод admin?.

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

$ rails generate migration add_admin_to_users admin:boolean

Миграция просто добавляет столбец admin к таблице users (Листинг 9.39), приводя к модели данных показанной на рис. 9.13.

class AddAdminToUsers < ActiveRecord::Migration
  def change
    add_column :users, :admin, :boolean, default: false
  end
end
Листинг 9.39. Миграция для добавления булевого атрибута admin к пользователям. db/migrate/[timestamp]_add_admin_to_users.rb

Обратите внимание на то, что мы добавили аргумент default: false к add_column в Листинге 9.39, что означает, что пользователи не будут администраторами по умолчанию. (Без аргумента default: false, admin был бы по умолчанию nil, что все же является false, так что этот шаг не является строго обязательным. Однако это более явно и четко сообщает о наших намерениях, и Rails, и читателям нашего кода.)

Модель User с добавленным булевым атрибутом admin.

Рис. 9.13. Модель User с добавленным булевым атрибутом admin.

Наконец, мы мигрируем базу данных разработки и подготавливаем тестовую бд:

$ bundle exec rake db:migrate
$ bundle exec rake test:prepare

Как и ожидалось, Rails догадывается о булевом характере атрибута admin и автоматически добавляет метод со знаком вопроса admin?:

$ rails console --sandbox
>> user = User.first
>> user.admin?
=> false
>> user.toggle!(:admin)
=> true
>> user.admin?
=> true

В результате, тесты для admin должны пройти:

$ bundle exec rspec spec/models/user_spec.rb

В качестве последнего шага, давайте обновим наш заполнитель образцов данных для того, чтобы сделать первого пользователя администратором (Листинг 9.40).

namespace :db do
  desc "Fill database with sample data"
  task populate: :environment do
    admin = User.create!(name: "Example User",
                         email: "example@railstutorial.org",
                         password: "foobar",
                         password_confirmation: "foobar",
                         admin: true)
    .
    .
    .
  end
end
Листинг 9.40. Код заполнителя образцов данных для создания административного пользователя. lib/tasks/sample_data.rake

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

$ bundle exec rake db:reset
$ bundle exec rake db:populate
$ bundle exec rake test:prepare

Возвращение к строгим параметрам

Вы могли заметить, что Листинг 9.40 делает пользователя администратором с помощью добавления admin: true к хэшу инициализации. Это подчеркивает опасность демонстрации наших объектов в диком Вебе: если мы просто передадим инициализационный хэш с произвольного веб-запроса, вредоносный пользователь может в таком случае отправить PATCH запрос следующим образом:8Инструменты командной строки, такие как curl могут выдавать PATCH запросы такой формы.

patch /users/17?admin=1

Этот запрос сделал бы администратором пользователя 17, что могло бы стать потенциально серьезной брешью в безопасности, если не сказать больше.

Из-за этой опасности очень важно передавать на дальнейшую обработку только параметры безопасных для редактирования атрибутов. Как отмечалось в Разделе 7.3.2, это может быть достигнуто с помощью строгих параметров вызывая require и permit на хэше params:

 def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end

В частности, обратите внимание на то, что admin не включен в список разрешенных атрибутов. Именно это не позволяет произвольному пользователю предоставлять себе административный доступ к нашему приложению. Поскольку это очень важный нюанс, хорошей идеей будет написание теста на каждый нередактируемый атрибут и написание такого теста для атрибута admin оставлено в качестве упражнения (Раздел 9.6).

Вадим Обозин
Вадим Обозин

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

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