#ruby #sinatra #datamapper #ruby-datamapper
#ruby #синатра #datamapper #ruby-datamapper
Вопрос:
Я работаю над веб-сайтом, который позволяет пользователям входить в систему. У всех пользователей есть 1 учетная запись, у учетной записи может быть много заказов. Пользователь может быть клиентом, работником или менеджером. Клиент никогда не является ни работником, ни менеджером. менеджер также является работником. Я хотел бы представить дополнительные разделы страниц / параметров навигации в зависимости от типа пользователя, вошедшего в систему.
В настоящее время я использую набор логических значений, чтобы пометить пользователя как определенный тип, проверить это значение и выполнить несколько блоков if / elsif для создания страницы, которую видит пользователь.
class User
include DataMapper::Resource
# ...
# various properties
# ...
property :client, Boolean
property :worker, Boolean
property :manager, Boolean
end
И затем я использую фильтр before для проверки типа пользователя и установки результата в качестве переменной.
before do
@user = session[:user]
if @user.client?
@ura = 'client'
elsif @user.worker?
@ura = 'worker'
elseif @user.manager?
@ura = 'manager'
end
end
Тогда, по моим представлениям, у меня есть @ura, с которым можно поиграть. Мне кажется, что это уже вызовет у меня проблемы для менеджеров, потому что @ura должен быть и рабочим, и менеджером. Я мог бы использовать некоторые или в моих представлениях, но я думаю, что лучшим решением было бы установить тип пользователя в качестве перечисления или флага. Но я не совсем понимаю, как использовать это в моем процессе.
Я хотел бы знать, каковы преимущества / недостатки каждого из них и базовый пример того, как я могу получить соответствующее значение в @ura.
Ответ №1:
Я не уверен, но, возможно, лучшим решением будет массив:
class User ....
def getRoles
roles = Array.new
roles << "client" if self.client?
roles << "manager" if self.manager?
roles << "worker" if self.worker?
roles
end
end
before do
@user = session[:user]
if(@user.getRoles.index("manager") != nil)
...
Комментарии:
1.Это похоже на то, о чем я думал. Кажется, что использование чего-то подобного
property :role, Enum[ :client, :worker, :manager ]
в основном дало бы мне то, что вы описали в одной строке. Я понимаю, что что-то может быть только одним перечислением за раз. (т. е..user.role = :worker
перезаписало бы любое текущее значение:role)В то время как aFlag
может содержать любое из определенных значений в качестве свойства. Я понимаюEnum
, но я не понимаю взаимосвязиFlag
(т.е. Как можно было бы установить и отменить определенные значенияFlag
? * (могут ли они быть отключены после установки?) *)2. В идеале я хотел бы иметь что-то вроде
.client?
и иметь этот возвратtrue
илиfalse
. Так что я могу сделать что-то вродеif @ura.client?
. (Я в порядке с тем, чтобы самостоятельно разобраться с кодом для этого, я просто пытаюсь разобраться в наилучшем способе представления этой информации.)
Ответ №2:
Я не помню, как я решил эту точную проблему (я думаю, это было для приложения для доставки велосипедов), но сегодня только заметил, что она все еще без ответа.
Итак, всего десять лет спустя, хотя я больше не использую DataMapper регулярно, он — то, как я решил бы это сейчас;
В то время я не до конца понимал разницу между аутентификацией и авторизацией в отношении пользователей Role
в системе.
class User
include DataMapper::Resource
...
properties
...
property :role, Enum[ :client, :worker, :manager ]
end
class Employee < User
include DataMapper::Resource
...
more properties
end
Таким образом, все пользователи могут иметь то, что им нужно, сотрудники могут быть дополнительно разделены на Worker
amp; Manager
. затем вы можете поместить соответствующие проверки в соответствующую модель. Больше исходного кода, но более удобен в обслуживании и более прост в масштабировании, просто добавьте новую роль в User
Enum и соответствующий класс.
Если класс не делает ничего, кроме пространства имен / логического разделения, вы даже можете обойтись без некоторого метапрограммирования / отражения, вывести классы из перечисления и включить соответствующие модули при инициализации.