Подтвердить что ты не робот

Ввод логики представления в контроллер является хорошей практикой в ​​Ruby?

В некоторых рекомендациях [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

4b9b3361

Ответ 1

По-моему, если текст - это единственное, что меняется, оно не относится к виду. Если вам нужна реструктуризация страницы, эта логика представления. Это просто разные данные.

Ответ 2

Вы не первый, кто это задает. Если представления и контроллеры должны иметь мало логики, а модель должна быть агностикой представления, где принадлежит логика представления?

Оказывается, мы можем использовать старый метод, называемый шаблоном декоратора. Идея состоит в том, чтобы обернуть объект модели другим классом, который содержит вашу логику представления. Этот класс-оболочка называется декоратором. Декоратор абстрагирует логику от вашего взгляда, сохраняя ваши модели изолированными от их представления.

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

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

Надеюсь, это поможет!

Ответ 3

Я бы использовал для этого помощник. Предположим, вам нужно перевести приветственное сообщение на основе некоторого языка.

В 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 с использованием помощника намного проще и достаточно.

Ответ 4

Нет, вы не хотите никаких условностей вообще в классе пользователя или контроллере. Точка этого примера в блоге - это ссылка на полиморфизм, просто хороший старомодный дизайн 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

Ответ 6

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

Ответ 7

Логику в представлении трудно поддерживать, мы должны поместить бизнес-логику в модель и всю логику представления в помощники.

Если вы хотите, чтобы ваш код был объектно-ориентированным, используйте Decorators (объектно-ориентированный способ помощников)

Лучший пример: https://github.com/jcasimir/draper

Ответ 8

Поместите код, определяющий current_user.welcome_message в _app/helpers/application_helper.rb_, тогда он будет доступен любым видом, отображаемым с помощью макета приложения.

Другим вариантом является определение настраиваемого вспомогательного модуля, который не обязательно связан с данным представлением или контроллером (см. видео, приведенное ниже), и include его в модулях представления/контроллеров, которые вы хотите имеют эту функциональность.

Это не черное и белое. Но из того, что вы описали, похоже, что это код, который навязчив в вашем приложении application_controller.rb, и это не код с функциональностью, который оправдывает его собственный контроллер, самым эффективным и эффективным вариантом может быть создание настраиваемого вспомогательного модуля и включите его в помощники, которые вы хотите иметь такую ​​функциональность. Тем не менее, это, в конечном счете, решение, которое разработчик приложения (т.е. Вы) должен принять решение.

Здесь - хорошая статья, в которой излагаются вспомогательные модули с мая 2011 года.

Здесь - это RailsCast, описывающий настраиваемые вспомогательные модули (т.е. пользовательские, как в модулях, не обязательно связанных с данным контроллером или представлением). Короткая, сладкая, и к сути.

Ответ 9

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

Ответ 10

Хорошей практикой было бы иметь реальные экземпляры View. Rails пародия на MVP (есть разница, посмотрите его), к сожалению, кажется, притворяется, что представления - это шаблоны. Это неправильно.

Предполагается, что представления должны содержать логику представления в шаблонах MVC и MVC. Они также должны манипулировать несколькими шаблонами и принимать решение о том, какие шаблоны использовать для представления состояния и информации из уровня модели (да, модель - это не экземпляр ORM).

Итак, чтобы ответить на вопрос: логика представления не имеет места в контроллерах.