#ruby-on-rails #ruby-on-rails-3 #model #controller #action
#ruby-on-rails #ruby-on-rails-3 #Модель #контроллер #Экшен
Вопрос:
Это вопрос новичка Rails:
Когда я вызываю create()
модель, обходит ли это соответствующее действие контроллера create
?
Например, это не затрагивает мои теги controller #create action:
user.tags.create(:content => new_tag)
Но если я отправляю сообщение на tags#create
маршрут из формы, тогда это работает просто отлично.
Я предполагал, что вызов user.tags.create
вызовет действие контроллера и всегда будет запускать код в нем при создании, но, по-видимому, это происходит только во время отправки по этому маршруту.
Чего мне здесь не хватает?
Редактировать:
Есть ли способ выполнить этот вызов, чтобы убедиться, что код создания контроллера запущен? У меня есть некоторый код, чтобы найти тег по постоянной ссылке и при необходимости создать новый, иначе повторно используйте существующий. Использование model.create() не запускает ничего из этого кода. Я мог бы «делать это неправильно», хотя: P
Ответ №1:
Модель ничего не знает о контроллере, это просто объект, представляющий состояние, хранящееся в базе данных, возможно, с некоторыми дополнительными инкапсулированными поведениями. Контроллер — это объект, который отвечает на запросы, отправляемые на ваш сервер. Хотя строительные леса по умолчанию изменят вашу модель, контроллерам даже не обязательно использовать модель.
Контроллеры и модели отключены, но только логически связанные классы.
Если у вас есть код, который вы хотите сделать доступным для всех пользователей вашей модели, добавьте метод в вашу модель. Затем вызовите этот метод с вашего контроллера и в любом другом месте, где вы хотели бы такого поведения.
Комментарии:
1. Есть ли способ выполнить этот вызов, чтобы убедиться, что
create
код контроллера запущен? У меня есть некоторый код, чтобы найти тег по постоянной ссылке и при необходимости создать новый, иначе повторно используйте существующий. Использованиеmodel.create()
не запускает ничего из этого кода.2. Вы захотите поместить этот код в свою модель и вызвать его с контроллера и из любого другого места, где вы хотели бы иметь такое поведение. Контроллер должен вызываться rails только в ответ на запрос к вашему серверу или через ваши модульные тесты / спецификации.
3. используйте фрейм тестирования для имитации запроса POST, в противном случае используйте свой браузер. С другой стороны, может быть, этот код принадлежит модели?
Ответ №2:
Rails работает по шаблону проектирования MVC. M — это модели, которые обычно являются классами ORM. В Rails ActiveRecord является ORM по умолчанию, и каждая модель сопоставляется таблице в базе данных. Вот где должна быть суть вашей логики. Модели ничего не знают о большом мире, откуда они вызываются, например, из Интернета, веб-страницы или контроллера.
Контроллер формирует C MVC. Это конечные точки ваших веб-приложений. Каждый раз, когда URL вызывается из браузера, он заканчивается на конечной точке контроллера. Действие контроллера «создать» является конечной точкой. Этот метод чаще называют «действием». Задача действия «создать» контроллера должна заключаться в организации создания объектов, обработке и упаковке ошибок, а затем перенаправлении в другое местоположение или отправке ответа обратно с использованием представлений.
Представление формирует V MVC. Не хочу углубляться в V, поскольку это не относится к вашему вопросу, и я предполагаю, что вы это уже знаете.
Таким образом, метод «create» вашей модели, доступный с помощью ActiveRecord, значительно отличается от действия контроллера «create». Действие create в контроллере может вызывать метод create в модели как часть ее оркестровки.
Общепринятой практикой является сохранение «тощих контроллеров» и «толстых моделей». Убедитесь, что действие вашего контроллера ограничено не более чем несколькими строками (обычно 5-6 строк для действия create). Часть логики вашей программы должна быть в самой модели.
Не смотрите, что при вызове user.tags.create вызывается действие «создать» контроллера.tags.create. К контроллеру отправляются только запросы веб-браузера.
Комментарии:
1. Спасибо за подробное объяснение!
Ответ №3:
user.tags.create
вызывает ActiveRecord#create
метод, унаследованный от Tags
, для чего TagsController#create
и предоставляет нам доступный интерфейс.
ActiveRecord#create
создает новый объект модели, а затем сохраняет его, ничего общего с представлением или контроллером,
Controller#create
вероятно, вызывает модель create, если разрешения правильные, параметры и т.д., Но он делает это как ответ на сообщение с веб-страницы
по сути, модель и контроллер являются двумя отдельными объектами и взаимодействуют с помощью своих методов
узнайте больше о методологии MVC
Ответ №4:
Вы правы. ModelClass#create не имеет ровно никакого отношения к контроллеру.
Задача контроллера состоит в том, чтобы реагировать на ввод или «действие», выполнять любые связанные с моделью действия, которые необходимо выполнить, а затем иным образом настраивать сцену для представления (выбранного методом / действием контроллера) для отображения деталей.
На высоком уровне задачей модели является инкапсуляция данных и, в случае моделей на основе ActiveRecord, посредническая передача данных между структурами данных на основе памяти («модели») и базовым постоянным хранилищем (база данных).
Исходя из вашего редактирования, мне кажется, что вы хотите запустить свой метод Tags#create, чтобы выполнить некоторую работу, связанную с данными. Это было бы более уместно сделать в модели IMO, поскольку звучит так, как будто вы выполняете строго связанные с данными вещи и не нуждаетесь в полном «цикле MVC», связанном с вызовом метода контроллера. Можете ли вы выполнить то, что вы хотите сделать, в обратном вызове before_create для вашего ModelClass? Посмотрите здесь для получения дополнительной информации об обратных вызовах ActiveRecord (включая before_create).
Комментарии:
1. вероятно, потому, что это ничего не объясняет в том, что касается ответа на его вопрос: «да, вы были неправы», не говорит ему, «чего ему здесь не хватает», и при этом это действительно не объясняет и даже не пытается объяснить что-либо в полезном смысле, это было не от меня, но я рассмотрел это