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