Декларативная замена ruby-программирования для if / then / else / RETURN / end? - PullRequest
4 голосов
/ 20 января 2009

У меня все это отображается на контроллерах:

if not session[:admin]
  flash[:notice] = "You don't have the rights to do #{:action}."
  redirect_to :action=>:index
  return
end

И его брат:

if not session[:user] and not session[:admin]
  flash[:notice] = "You don't have the rights to do #{:action}."
  redirect_to :action=>:index
  return
end

Я хотел бы сократить все это до одной декларативной строки, когда я хочу использовать ее в методе:

def action_which_requires_rights
    require_rights :admin
    #or:
    #:require_rights :user_or_admin
end

Ясно, что если require_rights не выполняется, я не хочу, чтобы остальная часть метода выполнялась. Я клянусь, что был способ сделать это, но я не могу найти, где я об этом читал. Я воображаю это?

Ответы [ 5 ]

8 голосов
/ 20 января 2009

Во-первых, вы можете сделать: unless session[:admin] вместо if not ...

Тогда у вас может быть фильтр before, который вызывает ваш метод, этот метод сделает ваш redirect_to "url" и вернет.

У меня есть вопрос, я надеюсь, что вы не просто храните идентификатор администратора в сеансе в качестве единственного средства аутентификации, имеете атрибут в вашей модели пользователя и запрашиваете, что может быть более безопасной ставкой.

6 голосов
/ 20 января 2009

Как уже говорили другие, before_filter здесь кажется правильным инструментом. Но я рассмотрю тот факт, о котором вы спрашивали.

К сожалению, метод не может привести к возвращению вызывающего метода. Два ближайших совпадения с шаблоном, который вы ищете:

Блок:

def require_rights(rights)
  if session[rights]
    yield
  else
    flash[:notice] = "You don't have the rights to do #{:action}."
    redirect_to :action=>:index
  end
end

Итак, с этим вы бы сделали:

def action_which_requires_rights
  require_rights :admin do
    #do whatever here
  end
end

Или возвращаемое значение:

def require_rights(rights)
  return true if session[rights]
  flash[:notice] = "You don't have the rights to do #{:action}."
  redirect_to :action=>:index
  false
end

Итак, с этим вы бы сделали:

def action_which_requires_rights
  require_rights :admin or return
  #do whatever here
end

Мне больше нравится блок, потому что он подходит подобными методами, и заставление вызывающего абонента делать это or return кажется мне неестественным.

3 голосов
/ 20 января 2009

Посмотрите на before_filter. Они могут остановить выполнение и могут быть ограничены определенными действиями.

1 голос
/ 20 января 2009

Я бы не показывал действие пользователю, если пользователю не разрешено выполнять это действие (для этого я бы использовал помощников)

В контроллерах, как уже упоминалось в других ответах, imho, лучший подход - использовать фильтры до управления правами доступа.

Я бы также предложил использовать плагин restful аутентификации для управления ролями пользователей.

0 голосов
/ 20 января 2009

Вы можете попробовать что-то, что вызывает исключение.

def action_for_admins
  require_rights :admin
end

begin 
  action_for_admins
rescue
  <%= You don't have the rights to do that %>
end

Тогда require_rights должен выглядеть примерно так

def require_rights(*rights)
  rights.each do |right|
    raise "Missing right #{right.to_s}" if not user.has_right?(right)
  end
end

Обратите внимание, что я новичок в Ruby или Rails, поэтому он может быть не способ

...