Rails 3 — Как выполнить рефакторинг этого кода контроллера?

#ruby-on-rails #ruby-on-rails-3 #refactoring

#ruby-on-rails #ruby-on-rails-3 #рефакторинг

Вопрос:

Есть ли способ ВЫСУШИТЬ и загрузить объекты более чистым способом (без использования before_filter).

Действительно, мне нужны @answer и @question двумя другими способами, кроме «показать».

Контроллер :

 def show
 @answer = Answer.new pre_form
 @question = Question.find(params[:id])
 @answers = @question.answers.page(params[:page])
 respond_with @question
end

private

def pre_form     
   session[:pre_form][:answer] || session[:pre_form][:question] if session[:pre_form]
end
  

Заранее спасибо

Ответ №1:

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

 def fetch_question_and_answer(params)
  @answer = Answer.new pre_form
  @question = Question.find(params[:id])
  @answers = @question.answers.page(params[:page])
end
  

Это превратило бы это в простой вызов метода в ваших различных методах контроллера:

 def show
  fetch_question_and_answer(params)
  respond_with @question
end
  

Это может быть немного подлые, чтобы пойти и назначить переменные экземпляра в методах, как это, как это делает в конечном итоге немного волшебные в плохом смысле, так что будьте осторожны, чтобы пометить свой метод явно, чтобы избежать путаницы. Альтернативой является простое возвращение этих данных и назначение их в каждом конкретном случае.

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

Комментарии:

1. 1 за акцент на том, что before_filter правильный путь.

2. Я читал, что он был устаревшим и не рекомендуется устанавливать переменные экземпляра через фильтр before. Из-за его волшебства и из-за того, что переменная экземпляра скрыта, поскольку она частная / защищенная. Я ошибаюсь?

3. Я хотел бы знать, где вы это прочитали, потому что я никогда не слышал ничего подобного. before_filter является одним из основных методов в контроллере и важен по целому ряду причин. Иногда в документации реализация метода помечается как устаревшая, поскольку она перемещается в другой модуль, но сам метод остается действительным. Также не тот случай, когда переменные экземпляра скрыты или защищены, поскольку это невозможно в Ruby. Если определена переменная экземпляра, она будет передана в контекст представления.

Ответ №2:

Аналогично вышеописанному, у вас могут быть вспомогательные методы, которые вы можете использовать как переменную экземпляра:

 helper_method :answer, :question, :answers

def answer
  @answer ||= Answer.new pre_form
end

def question
  @question ||= Question.find(params[:id])
end

def answers
  @answers ||= question.answers.page(params[:page])
end
  

Поскольку это helper_methods, вы также можете использовать их в своих представлениях!

Ответ №3:

Способ, которым вы это делаете, достаточно хорош, за исключением @question.answers.page(параметры [:страница]), который не следует закону Деметры и может быть написан лучшим образом.

Вместо этого вы можете создать делегата для ответов.страница, чтобы вы могли вызывать :

 @question.answers_page(params[:page])
  

Если вы заинтересованы в лучшем дизайне (похоже, что вы заинтересованы), помните, что две точки в инструкции Rails имеют более высокую вероятность того, что их можно будет записать лучшим, более инкапсулирующим способом.

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