【问题标题】:Proper way to handle a form when user provides no inputs当用户不提供输入时处理表单的正确方法
【发布时间】:2015-05-21 02:23:47
【问题描述】:

我有一个简单的应用程序,它会要求用户输入他们的起点和终点地址,一旦他们这样做,他们就可以点击提交并获得接下来 3 辆公共汽车/火车到目的地的列表。但是,我无法处理用户根本没有输入任何内容并点击提交按钮的情况。

这是简单表单的代码

   <%= form_tag("/welcome/index", method: "post") do %>
  <div class ="input-group">
  <label>Current Location</label>
  <%= text_field_tag("address", params['address'], :class => 'form-control') %>
</div><br/>
<div class ="input-group">
  <label>Destination Location</label>
  <%= text_field_tag("destaddress", params['destaddress'], :class => 'form-control') %>
  </div>


  <p>
    <br/>
<%= submit_tag "", :value => "Find Buses", :class => "btn btn-default" %>  </p>

<% end %>

这是我的控制器,我在其中捕获用户的输入并运行我的逻辑以提供总线列表。

class WelcomeController < ApplicationController
  # displays the form, so change the name of the form you have now to new.html.erb
  def new
  end

  # the form will pass to this action to perform logic on longitude and latitude
  def create
    curAddress = params[:address]
    destAddress = params[:destaddress]



    #2 close stops to current location
    @currentList = Stop.by_distance(:origin => curAddress).limit(2)

    if @currentList.length == 0
      flash[:error] = "Somethig is wrong"
    end
    #2 closest stops to destination location
    @destList = Stop.by_distance(:origin => destAddress).limit(2)

    @startIds = Array.new
    2.times do |i|
      @startIds.push(@currentList[i].id)
    end

    @endIds = Array.new
    2.times do |i|
      @endIds.push(@destList[i].id)
    end


    @currentStop = Stop.closest(:origin => curAddress)
    @destinationStop = Stop.closest(:origin => destAddress)



         @timeNow = Time.now.in_time_zone("EST") + 1.hour
    @finalTime = @timeNow.strftime("%H:%M:%S")

    startStopId = @currentStop.first.id
    endStopId = @destinationStop.first.id

     #update it based on succeed
    @cStop = Stop.find(startStopId)
    @dStop = Stop.find(endStopId)




    testMethod(startStopId,endStopId)  


    render :index
  end

我所做的基本上是接受用户的输入,然后尝试使用一个名为 Geokit 的 gem 来查找用户给定地址的两个最近的站点,并将他们的 ID 存储在@currentList and @destList

所以很明显,如果用户没有给出任何输入,那么这两个列表应该是空的。所以使用这个逻辑我尝试了这个

 if @currentList.length == 0
      flash[:error] = "Somethig is wrong"
    end

但是我无法处理用户没有输入的情况。所以我想知道如何处理它?理想情况下,我想在表单上显示一条消息,说“没有输入输入”,这样用户将重试输入一些输入,然后点击提交。我对 ruby​​ on rails 非常陌生,例如我知道在 java 中我可以抛出异常或其他东西。

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    def create ...内部

    if params[:address].blank? || params[:destaddress].blank? # Checks if it is nil or = ""
      flash[:address_error] = "No address entered"
      render 'new' and return # render new shows the form again, return makes sure we
                              # don't do anything else in the action
                              # you can also do redirect_to, but this will be a little
                              # faster since you have no logic the new action
    end
    

    你应该在行动的早期就这样做,这样你就不会浪费时间在行动中做其他事情。

    正如 Sharvy Ahmed 所说,前端验证也是一种选择,也是一个好主意。他展示的 HTML5 方法的替代方法是 JQuery,rails 默认使用该方法。这可能看起来像这样。

    $('form').submit(function() {  //When a form is submitted...
      $('input').each(function() { //Check each input...
        if ($(this).val() == "") { //To see if it is empty...
          alert("Missing address");//Say that it is
          return false;            //Don't submit the form
        }
      });
      return;                      //If we made it this far, all is well, submit the form
    });
    

    但是您不应该依赖客户端验证,因为用户可以手动转到 url,绕过验证页面。

    【讨论】:

    • 我试过你的方法,我从来没有看到闪现说“没有输入地址”我还需要做什么吗?
    • 不应该,不。默认布局应处理所有 Flash 消息。除非您更改了默认布局 application.html.erb 以及它如何渲染闪光灯,否则它应该可以工作,例如告诉它只显示 flash[:error] 您需要将控制器中的闪光灯名称设置为 [:error] 而不是 @987654327 @.
    【解决方案2】:

    首先,可以在前端和后端检查验证。

    您可以使用 html5 required 来强制输入字段,除非他们写点什么,否则任何人都无法继续。

    <%= text_field_tag("address", params['address'], :class => 'form-control'), :required => true %>
    

    对于后端验证,您可以像这样检查字段是否不是nil

    if curAddress && destAddress
      # Do your work here ...
    end
    

    顺便说一句,您将不得不大量重构代码。一个简单的重构可以声明一个私有方法来按距离获取最近的位置 ID,如下所示:

    private
    def nearest_by_distance(address, n)
      Stop.by_distance(:origin => address).limit(n).pluck(:id)
    end
    

    然后在您的create 操作中您可以执行以下操作:

    current_address = params[:address]
    destination_address = params[:destaddress]
    
    @start_from_location_ids = nearest_by_distance(current_address, 2)
    @end_to_location_ids = nearest_by_distance(destination_address, 2)
    

    希望你明白了吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2012-11-09
      • 2017-01-22
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 2018-10-15
      相关资源
      最近更新 更多