Структура приложения для основанных на ролях ресурсов RESTful - PullRequest
6 голосов
/ 26 сентября 2010

Существует ли наилучший подход к реализации ролей пользователей при использовании маршрутов ресурсов RESTful?

Скажите, у меня есть следующие ресурсы:

User has_many Tickets
Event has_many Tickets
Ticket belongs_to Person, Event

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

Клиенты могут получить доступ:

  • Индекс событий, шоу
  • Индекс билета (определяется пользователем), показать, купить / создать, вернуть / удалить
  • Персона создает, показывает, обновляет

Агенты могут получить доступ:

  • Индекс событий, показать, создать, обновить, удалить
  • Индекс билетов, показать, продать / создать, обновить, вернуть / удалить
  • Индекс личности, показать, создать, обновить, удалить

Какой из 4 основных подходов ниже будет чище и гибче?

Отдельные контроллеры в папках ролей и ресурсы в пространствах имен, например:

namespace "agent" do
  resources :events, :tickets, :people
end
namespace "customer" do
  resources :events, :tickets, :people
end

Отдельные контроллеры по ролям, например:

AgentController
  def sell_ticket, etc

CustomerController
  def buy_ticket, etc

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

TicketController
  before_filter :customer_access, :only => :buy
  before_filter :agent_access, :except => :buy

  def buy  #accessed by customer to create ticket

  def sell   #accessed by agent to create ticket

Общие действия с условными выражениями, например:

TicketController
  def create
    if @role == :customer
      #buy ticket
    elsif @role == :customer
      #sell ticket
    end
  end

Ответы [ 3 ]

6 голосов
/ 05 февраля 2011

Я бы предложил использовать комбинацию двух последних предложенных реализаций. Они придерживаются представления RESTful, ставят авторизацию на соответствующем уровне (контроллеры), и это масштабируемая реализация.

REST - это, по сути, доступ к существительным с глаголами . Таким образом, вы хотите, чтобы агенты и клиенты выполняли действия (глаголы) по отношению к билетам, пользователям и событиям (существительные). Для точного представления этих существительных у вас должен быть контроллер для каждого. Затем клиенты могут определить ресурс, который они ищут, по URL, http://example.com/events/22. Отсюда вы можете использовать маршрутизацию Rails для представления контекста для различных ресурсов, например, http://example.com/events/22/tickets, выполнив что-то вроде:

resource :events do
  resource :tickets
end

Придерживаясь архитектуры RESTful, вы приобретаете принцип сквозного действия . Парадигма для представления объектов должна быть ответственна только за это. Это не должно пытаться аутентифицироваться. Это не его работа. Авторизация должна происходить в контроллерах. Я очень рекомендую посмотреть на такие драгоценные камни, как CanCan или Декларативное разрешение , которые все это настраивают для вас.

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

0 голосов
/ 07 февраля 2011

Хотя они оба занимаются созданием Билетов, продажа агента / Билета по сравнению с покупкой Клиента / Билета кажется мне достаточно разной, чтобы их отделить. В конечном итоге они могут еще больше расходиться, поскольку их использование отличается от начала.

Возможна совместная работа контроллера с модулями или наследование от общего родительского контроллера:

module TicketsControllersCommom
  # common helper methods
end

class TicketsController < ApplicationController
  include TicketsControllersCommom
  # actions
end

class AgentTicketsController < ApplicationController
  include TicketsControllersCommom
  # actions
end

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

/events/xx/tickets # collection
/events/xx/tickets/xx # member
# etc.
/events/xx/agent/tickets # collection
/events/xx/agent/tickets/xx # member
# etc.

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

/agent/events/xx/tickets
/agent/events/xx/edit
# etc.
0 голосов
/ 26 сентября 2010

Если вы используете одну и ту же модель для билетов клиентов и агентов, не должно быть существенных различий между способами их обработки в контроллере. Итак, действие создания всегда будет таким:

@ticket = Ticket.new(params[:ticket])

if @ticket.save
  redirect_to @ticket
else
  render :action => "new"
end

Но ваши взгляды можно просто настроить:

<% if customer? %>
  Customer area.
<% else %>
  Agent area.
<% end %>
...