0

(I've broken out the 2nd question that originally was part of this post into a separate post)

I am creating a product landing page with Rails in which users can enter their email address to be notified when the product launches. (Yes, there are services/gems etc that could do this for me, but I am new to programming and want to build it myself to learn rails.)

On submit of the form, if there are errors, the app currently redirects to '/invites' I would like to instead display error messages on the same page/URL as the original form? (In my case, the form is located at root while the error messages are displaying at '/invites')

I have read the Rails Guide on Routes and numerous stackoverflow posts on handling form errors nothing I've found seems to answer the question I have.

Update: Based on the reply from @rovermicrover I would like to clarify that, while I'm open to an Ajax solution, I'm fine with a page refresh that displays the error message. (I was not able to get the recommendation by @rovermicrover to function as desired - see my response to that solution below for more details.)

What I did:

Invite model:

    class Invite < ActiveRecord::Base
      attr_accessible :email

      validates :email, :presence => {:message => "Please enter an email address."}

    end

My routes file:

SuggestionBoxApp::Application.routes.draw do
  root to: 'invites#new'
  resources :invites
end

This is what I have in the Invites controller (I've only included the actions I'm referencing: new, create, show - it's basically the default of what Rails might generate):

class InvitesController < ApplicationController

      def show
      @invite = Invite.find(params[:id])

        respond_to do |format|
          format.html # show.html.erb
          format.json { render json: @invite }
        end
      end

      def new
        @invite = Invite.new

        respond_to do |format|
          format.html # new.html.erb
          format.json { render json: @invite }
        end
      end

      def create
        @invite = Invite.new(params[:invite])

        respond_to do |format|
          if @invite.save
            format.html { redirect_to @invite }
            format.json { render json: @invite, status: :created, location: @invite }
          else
            format.html { render action: "new" }
            format.json { render json: @invite.errors, status: :unprocessable_entity }
          end
        end
      end
    end

Please let me know if there is any additional info I can provide in helping to answer this question. Thanks!

4

2 回答 2

2

使表单“远程”

form_for @invite, :remote => true
   ....

然后在控制器中

def create
  @invite = Invite.new(params[:invite])
    respond_to do |format|
      if @invite.save
        format.html { redirect_to @invite }
        format.js { render :action => 'create_suc'}
      else
        format.html { render action: "new" }
        format.js { render :action => 'create_fail' }
      end
    end
  end

/invites/create_suc.js.erb

$('#errors').remove()
$('#new_invite').prepend("<div class='Thanks'>Thanks for signing up</div>")
$('#new_invite').hide("")

/invites/create_fail.js.erb

$('#new_invite').html('<%= escape_javascript render("form", :invite => @invite) %>');

Forms 是您的.... 表单的一部分,也是对@invite 上所有错误的处理。

于 2013-04-08T21:19:27.337 回答
0

从纯粹的 Ruby on Rails 角度来看,有一种方法可以做到这一点,而无需使表单“远程”提交。但是,只有在浏览器启用了 cookie 时,您才能执行此操作。

这个想法是将表单数据保存在会话信息中以防出错。只要记住在成功的情况下删除会话数据。

  def new
    @invite = Invite.new(session[:invite])

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @invite }
    end
  end

  def create
    @invite = Invite.new(params[:invite])

    respond_to do |format|
      if @invite.save
        session.delete(:invite)
        format.html { redirect_to @invite }
        format.json { render json: @invite, status: :created, location: @invite }
      else
        session[:invite] = params[:invite]
        format.html { render action: "new" }
        format.json { render json: @invite.errors, status: :unprocessable_entity }
      end
    end
  end
于 2013-07-18T05:18:37.057 回答