Размещение логики представления в контроллере — хорошая практика в Ruby?
-
12-12-2019 - |
Вопрос
Некоторые рекомендации [1] предлагают вам использовать
<%= current_user.welcome_message %>
вместо
<% if current_user.admin? %>
<%= current_user.admin_welcome_message %>
<% else %>
<%= current_user.user_welcome_message %>
<% end %>
Но проблема в том, что где-то в вашем коде должна быть логика принятия решений.
Насколько я понимаю, решение принимается template
Это лучше чем controller
так как это сделает ваш контроллер более чистым.Это правильно?
Есть ли лучший способ справиться с этим?
http://robots. Thoughtbot.com/post/27572137956/tell-dont-ask
Решение
По моему мнению, если текст — единственное, что меняется, он не принадлежит представлению.Если вам нужно было реструктурировать страницу, это логика представления.Это просто данные разные.
Другие советы
Вы не первый, кто задается этим вопросом.Если представления и контроллеры практически не должны иметь логики, а модель должна быть независимой от представления, то какое место принадлежит логике представления?
Оказывается, мы можем использовать старую технику, называемую шаблон декоратора.Идея состоит в том, чтобы обернуть объект модели другим классом, содержащим логику представления.Этот класс-оболочка называется декоратор.Декоратор абстрагирует логику от вашего представления, сохраняя при этом ваши модели изолированными от их представления.
Дрейпер — отличный драгоценный камень, который помогает определить декораторов.
Приведенный вами пример кода можно абстрагировать следующим образом:
Передайте декоратор в представление с помощью @user = UserDecorator.new current_user
в вашем контроллере.
Ваш декоратор может выглядеть, как показано ниже.
class UserDecorator
decorates :user
def welcome_message
if user.admin?
"Welcome back, boss"
else
"Welcome, #{user.first_name}"
end
end
end
И ваше представление будет просто содержать @user.welcome_message
Обратите внимание, что сама модель не содержит логики для создания сообщений.Вместо этого декоратор оборачивает модель и переводит данные модели в презентабельную форму.
Надеюсь это поможет!
Я бы использовал для этого помощника.Предположим, вам нужно перевести приветственное сообщение на основе некоторой локали.
в app/helper/user_helper.rb
писать
module UserHelper
def welcome_message(user)
if user.admin?
I18n.t("admin_welcome_message", :name => user.name)
else
I18n.t("user_welcome_message", :name => user.name)
end
end
end
и, по вашему мнению, вы можете просто написать
<%= welcome_message(user) %>
Обратите внимание, что декоратор/презентатор предлагает действительно чистый объектно-ориентированный подход, но, по моему мнению, использование помощника намного проще и достаточно.
Нет, ты не хочешь любой условные обозначения вообще ни в классе пользователя, ни в контроллере.Целью этого примера в блоге является ссылка на полиморфизм, просто старый добрый объектно-ориентированный дизайн.
# in application_controller for example
def current_user
if signed_in?
User.find(session[:user_id])
else
Guest.new
end
end
#app/models/user.rb
class User
def welcome_message
"hello #{name}"
end
end
#app/models/guest.rb
class Guest
def welcome_message
"welcome newcomer"
end
end
... вы поняли.
Только вместо того, чтобы засорять вашу модель методами, предназначенными только для представления, создайте декоратор, который действует как презентатор:
require 'delegate'
class UserPresenter < SimpleDelegator
def welcome_message
"hello #{name}"
end
end
И сейчас current_user
выглядит так:
# application_controller
def current_user
if signed_in?
UserPresenter.new(User.find(session[:user_id]))
else
Guest.new
end
end
Украсьте модель пользователя и добавьте к ней Welcome_message напрямую.Да, в какой-то момент это может включать в себя какое-то условное утверждение.
http://robots. Thoughtbot.com/post/14825364877/evaluating-alternative-decorator-implementations-in
Я думаю, вам стоит посмотреть выпуск Railscasts на Presenters, чтобы получить ответ.
Логику представления сложно поддерживать, мы должны поместить бизнес-логику в модель, а всю логику представления — в помощники.
Если вы хотите, чтобы ваш код был объектно-ориентированным, используйте декораторы (объектно-ориентированный способ помощников).
Лучший пример: https://github.com/jcasimir/draper
Поместите код, определяющий current_user.welcome_message
в _app/helpers/application_helper.rb_ оно будет доступно любому представлению, отображаемому с помощью приложение макет.
Другой вариант — определить обычай вспомогательный модуль, который не обязательно связан с данным представлением или контроллером (см. видео, ссылку на которое я дал ниже), и include
это в модулях представления/контроллеров, в которых вы хотите иметь эту функциональность.
Это не что-то черно-белое.Но из того, что вы описали, похоже, что это код, который сложно вставлять в ваш application_controller.rb, и это не код с функциональностью, которая оправдывает наличие собственного контроллера, наиболее эффективным и действенным вариантом может быть создание собственного вспомогательного модуля. и включите его в помощники, в которых вы хотите иметь эту функциональность.Тем не менее, в конечном итоге это решение, которое принимает разработчик приложения (т. ты) необходимо принять решение.
Здесь — хорошая статья, описывающая вспомогательные модули из Май, 2011 г.
Здесь это описание RailsCast обычай вспомогательные модули (т.е.пользовательские, например модули, не обязательно связанные с данным контроллером или представлением).Коротко, мило и по делу.
Вы можете определить вспомогательный метод для этого.Я не думаю, что это хорошая идея — составлять приветственные предложения не только в модели, но и в контроллере.Но вам следует постараться очистить представления от кода, и если вы можете использовать для этого помощники, то вам следует это сделать.
Хорошей практикой было бы иметь реальные View
экземпляры.Rails пародия на MVP (есть разница, посмотрите), к сожалению, похоже, делает вид, что представления являются шаблонами.Это не правильно.
Предполагается, что представления содержат логику представления в шаблонах MVC и MVC.Они также должны манипулировать несколькими шаблонами и принимать решения о том, какие шаблоны использовать для представления состояния и информации с уровня модели (да, модель — это уровень, а не экземпляр ORM).
Итак, чтобы ответить на вопрос: Логике представления нет места в контроллерах.