Pergunta

Eu tenho uma ação de criação para um formulário que potencialmente gera erros (ou seja, o primeiro nome está ausente) e depois redireciona.

O problema é que, quando o redirecionamento acontece, esses erros são perdidos. Como eu poderia passar esses erros de formulário em uma sessão a ser exibida novamente no formulário original (que ainda deve ser preenchido com os detalhes anteriores, como no comportamento original do erro_messages)?

Obrigado!


O código:

def create
  @contact = Contact.new(params[:contact])
  if @contact.save
    flash[:notice] = "Sent."
  else
    flash[:notice] = "Error."
  end
end
Foi útil?

Solução

Este é um problema complicado que tive problemas comigo mesmo. A primeira pergunta que eu faria é por que você precisa redirecionar quando os erros são encontrados? Forçá -lo a renderizar a ação quando há erros foi uma decisão consciente dos designers da estrutura do Rails devido a preocupações com complexidade e usabilidade.

Aqui está o grande problema; portanto, em sua ação, você cria uma instância de um modelo usando params, a validação do objeto falha e você decide redirecionar para outra ação. Antes de redirecionar para outra ação, você teria que salvar o estado atual da sua instância do modelo para a sessão e depois redirecionar para a ação: Foo. Em ação: Foo, você teria que reagir para atualizar os atributos e passar os erros para a visualização por meio de uma variável de instância. A questão aqui é que você está acoplando ações no seu controlador, o que é uma coisa ruim (uma ação depende da outra). Há uma série de outros problemas sobre os quais eu poderia digitar para sempre, mas se você só precisar fazer isso para um recurso, aqui está como eu faria:

config/rotas.rb

map.resources :things, :member => { :create_with_errors => :get }

Things_controller.rb

def new
  @thing = Thing.new
end

def create
  @thing = Thing.create(params[:thing])
  if @thing.save
    redirect_to things_path
  else
    session[:thing] = @thing
    redirect_to create_errors_thing_path(@thing)
  end
end

def create_with_errors
  @thing = session[:thing]
  @errors = @thing.errors
  render :action => :new
end

App/Views/Things/new.html.erb

<% if defined?(@errors) %>
<% #do something with @errors to display the errors %>
<% end %>

<!-- render the form stuff -->

Eu sei o que você está pensando ... isso é hediondo. Confie em mim, fiz muitas tentativas para resolver esse problema e percebi que o mecanismo que os desenvolvedores de Rails escolheram é a melhor e mais fácil maneira de lidar com erros.

Outras dicas

A convenção em Rails é tornar a visão da ação original, em vez de fazer um redirecionamento. Então, seu código ficaria assim:

def create
  @contact = Contact.new(params[:contact])
  if @contact.save
    flash[:notice] = 'Sent.'
    redirect_to @contact
  else
    flash.now[:notice] = 'Error.'
    render :new
  end
end

Se houver alguma configuração adicional necessária para o new ação, extraia o código comum para um método privado e chamá -lo em um before_filter para ambos new e create.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top