И снова руби, после выходных
После таких длинных праздников тяжело снова браться за работу, все эти буквы, цифры, кнопки. Однажды, после отпуска, я забыл пароль на рабочий компьютер. В другой раз забыл пин-код на входной двери, причем посреди рабочей недели. На моей первой работе, чтобы попасть в офис, необходимо было ввести пароль из четырех цифр. Рука настолько привыкла к этому действия, что случайно задумавшить, а какой же у нас код, я не смог вспомнить ни одной цифры. Пришлось ждать коллег и потом сдаваться секретарям. Отдых - это тоже серьезный труд. За праздники не появилось ничего новенького из практики, поэтому расскажу про несколько фишек, которые я припас уже давно.
Массив и Хэш
В руби 1.9 ошибка при обращении по сломанному индексу к массиву стала более невнятной:
irb(main):001:0> RUBY_VERSION
=> "1.8.7"
irb(main):002:0> [1, 2, 3][:key]
TypeError: Symbol as array index
irb(main):001:0> RUBY_VERSION
=> "1.9.3"
irb(main):002:0> [1, 2, 3][:key]
TypeError: can't convert Symbol into Integer
Если вы случайно передадите масcив в функцию, которая принимает хэш, то поймаете ошибку TypeError: can't convert Symbol into Integer
.
Я один раз довольно долго искал проблему, так как вызов метода и работа с аргументом были окружены дополнительным кодом и я грешил на
другую конструкцию.
Функция "притвориться"
Во всех сайтах с бэкэндом в модель администратора мы обычно добавляем булевские флажки с правами доступа. Примерно так:
# model
class User < ActiveRecord::Base
has_fields do
string :username
boolean :acl_seo
boolean :acl_posts
boolean :acl_orders
# ...
end
# ...
end
# controller
class PostsController < ApplicationController
layout 'admin'
before_filter :authenticate_user
before_filter { raise AccessDenied unless current_user.acl_posts? }
# ...
end
# view
<% if current_user.acl_posts? %>
<%= link_to "Posts", posts_path %>
<% end %>
Эта простая и надежная схема верно служит нам уже довольно долго. Мы создаем суперюзеров, чтобы скрыть настройки от клиента, о которых ему не следуют беспокоится. Клиенты часто просят создать аккаунты с ограниченными правами (в душе мы все параноики и к тому же любим ущемить чьи-нибудь интересы :-)). Недавно я придумал добавить ещу одну функцию "притвориться другим пользователем". Теперь суперюзер может выбрать из комбобокса любой аккаунт и залогиниться им. Схематически это реализовано так:
class ApplicationController < ActionController::Base
# ...
def owner_user
@owner_user ||= User.find_by_id(session[:owner_user_id])
end
end
class AdminController < ApplicationController
# ...
def pretend
user = User.where('id <> ?', current_user.id).find(params[:user_id])
session[:owner_user_id] = current_user.id
sign_in user
redirect_to :back
end
def stop_pretend
if owner_user
sign_in owner_user
session[:owner_user_id] = nil
end
redirect_to :back
end
end
Эта маленькая хитрость позволяет решить сразу же 2 проблемы: всегда можно под любым аккаунтом посмотреть не осталось ли чего-нибудь лишнего, и можно зайти под клиентом, который говорит, что у него "все сломалось" и убедиться, что это действительно так.
Всегда запоминать меня
Коллега прислал ссылку на статью Always remember me, о том что пора отказаться от галочки "запомнить меня". В принципе я согласен с этой статьей и сам не долюбливаю эту галочку. Даже если сломался интернет и вы не сможете нажать ссылку "выйти", то всегда можно очистить куки или пользоваться режимом приватного просмотра. В рейлс 3.2 реализовать логин без экспирации очень легко:
cookies.signed.permanent[:user_id] = current_user.id
# Для чтения permanent указывать не обязательно, а signed - обязательно
cookies.signed[:user_id] # => 123
Мы новые проекты делаем без галочки в бэкэнде, проверяем концепцию.
Хорошей рабочей недели!
Tweet