Модель рельєфу, вид, контролер та помічник: що куди йде?


155

У Ruby on Rails Development (або MVC взагалі), яке швидке правило слід дотримуватись, куди слід застосувати логіку.

Будь ласка, дайте відповідь ствердно - З Do покладіть це сюди , а не Не кладіть цього туди .

Відповіді:


173

MVC

Контролер : введіть сюди код, який стосується розробки того, що користувач хоче, і вирішення, що їм надати, розробки, чи вони ввійшли, чи повинні вони бачити певні дані тощо. Зрештою, контролер розглядає запити і розробляє, які дані (Моделі) відображати та які представлення відображати. Якщо ви сумніваєтесь у тому, чи повинен код входити до контролера, то він, ймовірно, не повинен. Тримайте своїх контролерів худими .

Вид : Представлення повинно містити лише мінімальний код для відображення ваших даних (Модель), він не повинен здійснювати велику обробку чи обчислення, він повинен відображати дані, обчислені (або узагальнені) моделлю, або генеровані з Контролера. Якщо ваш Перегляд дійсно потребує обробки, яка не може бути виконана моделлю або контролером, покладіть код у помічник. Багато коду Ruby у представленні робить розмітку сторінок важкою для читання.

Модель : Ваша модель повинна містити там, де живе весь ваш код, який стосується ваших даних (суб’єкти, що складають ваш сайт, наприклад, Користувачі, Пошта, Облікові записи, Друзі тощо). Якщо код потребує збереження, оновлення або узагальнення даних, пов’язаних з вашими особами, введіть їх тут. Він буде повторно використаний у ваших переглядах та контролерах.


2
Люди починають відходити від жирової моделі. Мені подобається думати про свою модель як структуру даних. Потім я записую якийсь об’єкт Ruby, який реалізує поведінку, ініціалізуючи його з моделлю (вона розглядає модель як її дані таким же чином, як ви могли б обробляти рядки та масиви як дані в об'єктах поза Rails). Ось гарне відео з прикладом цієї методики.
Джошуа Щока

@AdamDonahue Я не впевнений, що все-таки щось можна сприймати як хорошу річ. Тони відповідальності краще брати участь у послугах.
фатухоку

35

Щоб додати до відповіді pauliephonic:

Помічник : функції для полегшення створення перегляду. Наприклад, якщо ви завжди переглядаєте список віджетів, щоб відобразити їх ціну, помістіть його в помічник (разом з частковою для фактичного відображення). Або якщо у вас є шматок RJS, який не хочете захаращувати погляд, покладіть його на помічника.


Насправді ми також не поміщаємо метод sign_in у Helper? Як тут запропонував підручник RoR >>> ruby.railstutorial.org/book/…
Іван Ван

14

Шаблон MVC насправді стосується лише інтерфейсу користувача та нічого іншого. Не слід ставити будь-яку складну бізнес-логіку в контролер, оскільки він керує поданням, але не логікою. Контролер повинен займатися вибором правильного перегляду та делегувати більш складні речі доменній моделі (Моделі) або бізнес-шару.

Дизайн, керований доменом, має концепцію Служб - це місце, в яке ви дотримуєтеся логіки, яка потребує впорядкування декількох різних типів об'єктів, що, як правило, означає логіку, яка природно не належить до класу Model.

Я, як правило, вважаю рівень Сервісу як API своїх програм. Мої шари Служб зазвичай досить чітко відповідають вимогам програми, яку я створюю, таким чином рівень Сервісу діє як спрощення більш складних взаємодій, знайдених у нижчих рівнях мого додатка, тобто ви можете досягти тієї ж мети, минаючи шари Сервісу. але вам доведеться натягнути набагато більше важелів, щоб це працювало.

Зауважте, що я не говорю тут про Рейки, я кажу про загальний архітектурний стиль, який вирішує вашу конкретну проблему.


Це чудова відповідь :)
Карлос Мартінес

12

Ідеальні пояснення тут уже, одне дуже просте речення як висновок і просте запам'ятовування:

Нам потрібні SMART-моделі, тонкі контролери та перегляди DUMB.

http://c2.com/cgi/wiki?ModelViewController



7

Покладіть в контролер речі, пов’язані з контролем авторизації / доступу.

Моделі стосуються ваших даних. Перевірка, відносини, CRUD, бізнес-логіка

Перегляди стосуються показу ваших даних. Відображення та отримання лише введення даних

Контролери - це контроль над тим, які дані переходять від вашої моделі до вашого перегляду (і якого виду) та від вашого погляду до вашої моделі. Контролери можуть існувати і без моделей.

Мені подобається думати про контролера як про охоронця / реєстратора, який направляє вас замовника (запит) до відповідного прилавка, де ви задаєте запитувачу (перегляд) питання. Тоді продавець (вид) потім йде та отримує відповідь від менеджера (моделі), якого ви ніколи не бачите. Після цього ви звертаєтесь до запиту охоронця / приймальника (контролера) і чекаєте, поки вас направлять, щоб перейти до іншого абонента (перегляду), який повідомляє вам відповідь, яку менеджер (модель) сказав їм у відповідь на питання іншого переглядача (перегляду) .

Точно так само, якщо ви хочете сказати абоненту (перегляду) щось таке, то в основному відбувається те саме, за винятком того, що другий касир скаже вам, чи прийняв менеджер вашу інформацію. Можливо також, що охоронець / реєстратор (контролер), можливо, сказав вам здійснити похід, оскільки ви не були уповноважені повідомляти цю інформацію менеджеру.

Отже, щоб розширити метафору, в моєму стереотипному та нереалістичному світі касири (погляди) є гарними, але порожніми головами і часто вірять усьому, що ви їм скажете, охоронці / ресепшн мінімально ввічливі, але не дуже обізнані, але вони знають, де люди повинні і не варто йти, а менеджери справді некрасиві і злі, але знають усе і можуть сказати, що правда, а що ні.


4

Одне, що допомагає правильно розділити, - це уникати антитіл "передавати локальні змінні від контролера до перегляду". Замість цього:

# app/controllers/foos_controller.rb:
class FoosController < ApplicationController

  def show
    @foo = Foo.find(...)
  end

end

#app/views/foos/show.html.erb:
...
<%= @foo.bar %>
...

Спробуйте перемістити його до геттера, який доступний як допоміжний метод:

# app/controllers/foos_controller.rb:
class FoosController < ApplicationController

  helper_method :foo

  def show
  end

  protected

  def foo
    @foo ||= Foo.find(...)
  end

end

#app/views/foos/show.html.erb:
...
<%= foo.bar %>
...

Це полегшує модифікацію того, що ставиться в "@foo" і як воно використовується. Це збільшує поділ між контролером і переглядом, не ускладнюючи їх.


умммм ... юк. Чи можете ви, будь ласка, додати кілька вагомих причин / сценаріїв, коли б ви це зробили. Це розбиває KISS та YAGNI і дуже смердюче (просто кинути ще в одній кліше)
Sixty4Bit

2
1) Rails робить багато магії, щоб скопіювати змінні екземпляра контролера на ваш екземпляр перегляду. 2) Запропонована реалізація також завантажує foo лише в тому випадку, коли до нього звертаються, що може економити деяку частину часу. Однак важлива відповідь - 1).
вебмат

11
Зітхання Це жахливо. Обмін змінними екземплярів Rails - це особливість, яка не є антитілом. Це всюдисущий синтаксичний цукор з низьким рівнем психіки, який рідко, якщо коли-небудь спричиняє проблеми в реальному світі. Якщо вам це не подобається, прекрасно, але кодування навколо нього за допомогою барокової нестандартної структури робить речі нескінченно гіршими. У цьому випадку ви фактично робите foo глобальною (за будь-яким контролером) змінною. Спроба виправити сприйняте зловживання змінним масштабом шляхом різкого збільшення сфери застосування є надзвичайно іронічною.
gtd

1
Я його не купую, dasil003. Обсяг fooта @fooпараметри однакові - вони обидва розміщені до пари <ControllerClass, request>. Крім того, використовуючи версію getter, я можу змінити спосіб Fooзнаходження / зберігання / кешування цього об'єкта, не змінюючи спосіб доступу до нього.
Джеймс А. Росен

1
Я думаю, ви маєте на увазі анти-шаблон "пропустити змінні екземпляра". Екземпляр var просочить стан для всього візуалізації, навіть у глибоко вкладених частинах. Ваше рішення також просочує стан, але трохи краще, ніж var екземпляр, оскільки він не дозволяє перепризначити. Передача локального - насправді найкраще, тому що це як викликати метод; місцеві не можуть бути помічені сторонами. Дивіться цю відповідь .
Келвін

2

Що ж, це залежить від того, з якою логікою має справу ...

Часто має сенс просунути більше речей у свої моделі, залишаючи контролери невеликими. Це гарантує, що цю логіку можна легко використовувати з будь-якого місця, де вам потрібно отримати доступ до даних, які представляє ваша модель. Погляди не повинні містити практично ніякої логіки. Тож справді, загалом, ви повинні прагнути зробити так, щоб ви не повторювали себе.

Крім того, швидкий фрагмент Google розкриває ще кілька конкретних прикладів того, що йде куди.

Модель: вимоги до валідації, відносини даних, створення методів, оновлення методів, знищення методів, пошук методів (зауважте, що у вас повинні бути не тільки загальні версії цих методів, але якщо є щось, що ви багато робите, як пошук людей з червоним волосся за прізвищем, тоді ви повинні вилучити цю логіку, щоб все, що вам потрібно зробити, - це зателефонувати на find_redH_by_name ("коваль") чи щось подібне)

Вид: Це повинно стосуватися форматування даних, а не обробки даних.

Контролер: саме тут йде обробка даних. З Інтернету: "Мета контролера - реагувати на запитувані користувачем дії, приймати будь-які встановлені користувачем параметри, обробляти дані, взаємодіяти з моделлю, а потім передавати запитувані дані у остаточній формі в режим вид. "

Сподіваюся, що це допомагає.


0

Простіше кажучи, Моделі мають усі коди, пов'язані з таблицею, їх простими або складними взаємозв'язками (мислити їх як запити sql, що включають кілька таблиць), маніпулювання даними / змінними для досягнення результату за допомогою бізнес-логіки .

Контролери матимуть код / ​​покажчики на відповідні моделі для запиту на роботу.

Перегляди приймають введення / взаємодію користувача та відображають отриману відповідь.

Будь-яке велике відхилення від них спричинить небажане навантаження на цю частину, і загальна ефективність програми може вплинути на неї.


-1

Тестування, тестування ... Введіть якомога більше логіки в модель, і тоді ви зможете її правильно перевірити. Експериментальні тести перевіряють дані та спосіб їх формування за допомогою тестування моделі, а функціональні тести перевіряють спосіб їх маршрутизації або управління тестуванням контролерів, тож випливає, що ви не можете перевірити цілісність даних, якщо вони не модель.

j

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.