Должны ли обрабатываться интерфейс и бэкэнд разными контроллерами? - PullRequest
10 голосов
/ 01 мая 2010

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

Во всех руководствах по RESTful Rails контроллеры имеют представление show, edit и index. Если авторизованный пользователь вошел в систему, представление edit станет доступным, а представление index отображает дополнительные элементы управления манипулированием данными, например кнопку удаления или ссылку на представление edit.

Теперь у меня есть приложение Rails, которое точно соответствует этому шаблону, но представление index не может быть повторно использовано:

  1. Обычный пользователь видит блестящую индексную страницу с множеством картинок, сложным макетом, без требований Javascript, ...
  2. Индекс пользователя Admin имеет совершенно другой минималистичный дизайн, таблицу jQuery и множество дополнительных данных, ...

Теперь я не уверен, как справиться с этим делом. Я могу думать о следующем:

  1. Один контроллер, одно представление: представление разделяется на два больших блока / части с помощью оператора if.
  2. Один контроллер, два вида: index и index_admin.
  3. Два разных контроллера: BookController и BookAdminController

Ни одно из этих решений не кажется идеальным, но сейчас я склонен использовать третий вариант.

Какой предпочтительный способ сделать это?

Ответы [ 4 ]

15 голосов
/ 01 мая 2010

Я задавал себе этот вопрос почти каждый раз, когда получаю новый проект. Я обычно выбираю одно из двух решений:

1). Один контроллер, один вид

Я почти никогда не выбираю это решение в наши дни, если проект не очень прост, и только один или два типа пользователей. Если вы получаете несколько типов пользователей, лучше использовать решение № 2. Хотя это решение может быть привлекательным, потому что вы думаете, что сэкономите некоторое время, написав меньше кода, но в итоге ваш контроллер и представление будут усложняться. Не говоря уже о крайних случаях, которые вы должны рассмотреть. Обычно это означает ошибки.

Моей компании когда-то приходилось спасать неудачный проект, у него было 3 типа пользователей. (администратор, бизнес и участник). Они использовали решение № 1. Код был в ужасном состоянии (и поэтому нас попросили спасти этот проект). Мы в шутку говорили, что это не MVC, а MMM. (Модель-модель-модель) Это связано с тем, что бизнес-логика не была должным образом извлечена и внедрена в модели, но также распространена в контроллерах и представлениях.

2). Несколько контроллеров, несколько просмотров

Я использую это решение все больше и больше в эти дни. Я обычно называю пространство контроллеров пользовательскими типами. Например:

В "приложении / контроллерах"

class BookController < ApplicationController
end

и в "app / controllers / admin"

class Admin::BookController < Admin::BaseController
end

Мне нужно учитывать обычных пользователей, когда я заполняю BookController, и мне нужно учитывать только пользователей-администраторов, когда я заполняю Admin::BookController

Я не уверен, что есть лучшие способы, но это то, что я узнал из дюжины проектов, которые я сделал до сих пор ...

3 голосов
/ 01 мая 2010

То, что я делаю в такой ситуации, изменилось совсем недавно. Текущий подход заключается в следующем:

Я разделяю контроллеры в зависимости от требований доступа. Это дает мне четкое ментальная модель и очень простой способ проверить контроль доступа (и проверить его).

Я даже зашел так далеко, что разделил «свой собственный доступ» к моделям на отдельные контроллер. Я также обычно держу имя контроллера, просто поместив его в отдельное пространство имен.

Этот подход также упрощает использование стандартного контроллера restuful реализации, такие как InheritedResources.

Обратите внимание, что вы можете повторно использовать многие виды, если для различные виды доступа.

Так что у меня было бы что-то вроде этого:

### lets start with routes

# this is basically guest access level. you can only list it and see details
map.resources :books, :only => [:index, :show]

namespace :my do |my|
  # this will require at least login.
  # index and show will be basically same as at the guest level. we can reuse the views
  my.resources :books
end

namespace :admin do |admin|
  # this will require admin login
  admin.resources :books
end

# now the controllers

# this might be just enough of a controller code :). the rest goes into model.
class BooksController < InheritedResources::Base
  actions :index, :show
end

module My
  class BooksController < InheritedResources::Base
    before_filter :require_user

    protected
    def begin_of_association_chain
      # this will force resources to be found on current_user.books.
      # so if you go to /my/books/123 and book 123 is not your book you will get 404
      current_user
    end
  end
end

module Admin
  class BooksController < InheritedResources::Base
    before_filter :require_admin

    # this controller is essentially unrestricted. you can get/edit/update any book
    # and you can have separate view template for index too
  end
end



## Views
# well, this is the part that I like the least in this approach, but
# I think the good outweight the bad.
# I see 2 ways to reuse the views w/o writing lots of ugly customization code for the InheritedResources
# 1) render 'parent' views inside templates. i.e. like:
# my/books/index.html.haml:
!= render :file => "/books/index"

# or just link the templates on the filesystem level with symlinks.
# (or if all of them are the same you can link the directory)
2 голосов
/ 01 мая 2010

Используйте два текущих, если есть два модуля 1] Администратор 2] Пользователь

Say

class BookUserController < ApplicationController
  #Here layout is used will be of layouts/application.html.erb
  #Here all the methods which user can will be present 
end


class BookAdminController < ApplicationController
  layout 'admin'  #here we set the layout is layouts/admin.html.erb 

end

ЕСЛИ только одну страницу, которую вы хотите показать администратору, вы можете использовать один контроллер и два метода

class BookUserController < ApplicationController
  layout 'admin', :only=>['index_admin']

  def index_admin


  end

  def index



  end


end

OR

class BookUserController < ApplicationController
  def index_admin

    render :action=>'index_admin', :layout => false
  end

  def index



  end


end
1 голос
/ 02 мая 2010

Когда мне нужна четко отделенная область администрирования, я склоняюсь к решению с двумя контроллерами для одного ресурса. Admin :: BooksController в каталоге admin / sub для интерфейса администратора со всеми действиями и общедоступный BooksController, который имеет только индекс и методы показа в зависимости от потребностей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...