Запуск еще одного действия контроллера в Ruby on Rails - PullRequest
4 голосов
/ 25 февраля 2010

Это случалось со мной несколько раз, и мне еще предстоит найти приемлемое решение.

У меня есть форма на домашней странице сайта, которая указывает на другой контроллер, который фактически выполняет работу по обработке данных. Когда форма успешно отправлена, другой контроллер отправляет вас обратно на домашнюю страницу с хорошим flash [: уведомлением] сообщением, и это конец.

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

Есть ли лучшее решение?

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

Есть две модели и контроллеры: посты и комментарии. Пост имеет много причин. Сообщение показывается так:

def index
  set_posts  # sets @posts
end

def show
  @post = Post.find_by_slug(params[:id])
  @comment = Comment.new
  if not @post
    flash[:error] = "'#{params[:id]}' does't exist"
    set_posts
    render :action => :index, :status => :not_found
  end
end

private
def set_posts
   @posts = Posts.get_all_public_posts
end

Контроллер комментариев имеет только действие создания:

def create
  @comment = Comment.new(params[:comment])
  @comment.post = Post.find_by_slug params['post_id']

  if not @comment.post
    # Now what?
    # We should here call PostsController.set_posts and render views/posts/index
  end

  if @reason.save
    flash[:notice] = 'Thank you for your message.'
    redirect_to(@reason.item)
  else
    # Now what?
    # We should here call PostsController.show without overriding the @comment
  end
end

конец

"Что теперь?" части, для которых у меня нет хорошего решения.

Ответы [ 4 ]

1 голос
/ 25 февраля 2010

Насколько изменяется остальная часть домашней страницы между тем, когда форма отображается и запрос перенаправляется на действие по умолчанию?

Если ответа совсем немного, то вам следует рассмотреть возможность использования remote_form_for и обновить только область уведомлений об успешном завершении или форму с ошибками проверки при сбое.

Если вам это не нравится, вы можете переместить всю повторяющуюся логику в действии домашней страницы в метод, определенный в классе ApplicationController, и вызвать его как часть before_filter для действия домашней страницы и действия, которое обрабатывает ваш форма. N.B : для выполнения этих действий вам потребуется установить переменные экземпляра, локальные переменные, установленные в фильтре, не будут сохраняться до тех пор, пока не будет выполнено действие.

1 голос
/ 25 февраля 2010

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

Как вы, очевидно, также читали, внесение ошибок в сеанс и перенаправление обычно не рекомендуется в мире Rails. И, как вы говорите, способ Rails, похоже, заключается в простом рендеринге другого действия без перенаправления. Когда я впервые попытался это сделать, я заметил, что мне пришлось скопировать много кода, чтобы настроить второе действие для отображения вида первого действия.

Как и при любом типе дублирования кода, решение состоит в том, чтобы переместить дублированный код в отдельный метод и затем вызвать этот метод из двух действий. Чистый способ сделать это - использовать before_filter для запуска кода для обоих действий.

0 голосов
/ 25 февраля 2010

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

Application Controller - лучшее место для его установки, если оно распространено на несколько контроллеров.

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

0 голосов
/ 25 февраля 2010

Как это отличается от нормальной формы ванильных рельсов?

if(valid)
 flash = ...
 redirect_to :home
else
 rerender form with error messages & submitted values
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...