Ответ 1
По-моему, если текст - это единственное, что меняется, оно не относится к виду. Если вам нужна реструктуризация страницы, эта логика представления. Это просто разные данные.
В некоторых рекомендациях [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
По-моему, если текст - это единственное, что меняется, оно не относится к виду. Если вам нужна реструктуризация страницы, эта логика представления. Это просто разные данные.
Вы не первый, кто это задает. Если представления и контроллеры должны иметь мало логики, а модель должна быть агностикой представления, где принадлежит логика представления?
Оказывается, мы можем использовать старый метод, называемый шаблоном декоратора. Идея состоит в том, чтобы обернуть объект модели другим классом, который содержит вашу логику представления. Этот класс-оболочка называется декоратором. Декоратор абстрагирует логику от вашего взгляда, сохраняя ваши модели изолированными от их представления.
Draper - отличный камень, который помогает определить декораторов.
Образец кода, который вы дали, можно абстрагировать так:
Проведите декоратор к представлению с помощью @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) %>
Обратите внимание, что декоратор/презентатор предлагает действительно чистый объектно-ориентированный подход, но imho с использованием помощника намного проще и достаточно.
Нет, вы не хотите никаких условностей вообще в классе пользователя или контроллере. Точка этого примера в блоге - это ссылка на полиморфизм, просто хороший старомодный дизайн OO.
# 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 на докладчиках для ответа.
Логику в представлении трудно поддерживать, мы должны поместить бизнес-логику в модель и всю логику представления в помощники.
Если вы хотите, чтобы ваш код был объектно-ориентированным, используйте Decorators (объектно-ориентированный способ помощников)
Лучший пример: 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).
Итак, чтобы ответить на вопрос: логика представления не имеет места в контроллерах.