首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ruby中的两个表单一个模型,每个表单分别进行验证

Ruby中的两个表单一个模型,每个表单分别进行验证
EN

Stack Overflow用户
提问于 2012-01-30 07:14:21
回答 2查看 639关注 0票数 1

我在一个表单中有三个字段,在另一个表单中有两个字段(与前面的表单相同,只是缺少一个字段)。我只想验证较小表单中的两个字段,但问题是它验证了所有三个字段。

我写了以下逻辑:

**

代码语言:javascript
复制
class User < ActiveRecord::Base
  validate :validate_form #for form with 2 fields
  private
    def validate_form
      if :classify_create
        self.errors.add(:weight, "need weight") if weight.blank?
        self.errors.add(:height, "need height") if height.blank?
      end
  end

  #   Validations of attributes (for form with three fields)
  validates :weight, :presence => true

  validates :height, :presence => true

  validates :gender, :presence => true
end

**

这是我的控制器操作:基本上我写了两个独立的创建:

代码语言:javascript
复制
**# for form with two fields
  def classify
    @user  = User.new
    @title = "Classify"
  end

  def classify_create
    @user  = User.where("weight = ? and height = ?", params[:weight] ,params[:height])
  end

# for form with three fields
  def new
    @user  = User.new
    @title = "Train"
  end

  def create
    @user = User.new(params[:user])
    if @user.save
       redirect_to @user
    else
      @title = "Train"
      render 'new'
    end
  end**

当我提交到两个字段的表单时,它也给了我一个性别错误,并重定向到具有三个字段的表单的页面。我该怎么做呢?

任何帮助都将不胜感激。

致敬,阿伦

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-30 10:43:24

首先,我不会使用 classify作为方法名。您可能会与ActiveSupport提供的核心inflector冲突。叫它classification之类的吧。

其次,您的验证在create方法中的if @user.save上运行。

classify_create中,您可以使用User.where(...),这是一种查找器方法。您正在提取一个匹配的记录并将其设置为@user。这不会运行验证,但您会收到验证错误。您正在发布到create,而不是classify_create。糟糕的路由将导致这种情况。

让我们先来讨论一下条件验证。在User模型中,创建一个变量作为性别验证的旁路开关。然后告诉您的验证在运行之前检查此绕过开关是否为false:

代码语言:javascript
复制
User < ActiveRecord::Base
  attr_accessor :skip_gender  # defaults to nil (false)
  # ...

  validates :gender, :presence => true, :if => :validate_gender? # validate if...
  # ...

  private
  def validate_gender?
    !self.skip_gender # true = run validation, false = skip validation
  end
  # ...
end

接下来,清理您的控制器。编写两个create方法,一个设置开关,一个不设置。(这不是干的):

代码语言:javascript
复制
def new_classification
  # for form with two fields
  @user  = User.new
  @title = "Classify"
end

def new
  # for form with three fields
  @user  = User.new
  @title = "Train"
end

def create
  @user = User.new(params[:user])
  if @user.save
    redirect_to @user
  else
    render :action => 'new' # render three-field form
  end
end

def create_classification
  @user  = User.where(:weight => params[:weight], :height => params[:height])
  # ... do something with @user ...
  @user.skip_gender = true # tell @user to skip gender validation
  if @user.save
    redirect_to @user
  else
    render :action => 'new_classification' # render two-field form
  end      
end

接下来,调整config/routes.rb以指定到您的自定义方法的路由。

代码语言:javascript
复制
resources :users do
  member do
    get 'new_classification',     :to => 'users#new_classification', \
                                  :as => :new_classification_for
    post 'create_classification', :to => 'users#create_classification', \
                                  :as => :create_classification_for
  end
end

现在更改包含两个字段的表单视图。指定将表单提交到的位置。

代码语言:javascript
复制
<%= form_for @user, :url => create_classification_for_user_url(@user) do |f| %>

这应该可以让你用你所拥有的……

票数 3
EN

Stack Overflow用户

发布于 2012-01-30 09:06:26

你的问题是双重的:

  1. 您正尝试将一个控制器用于两个不同的操作。
  2. Rails验证模型有一定的局限性且不灵活,控制器方法和模型应该有单独的验证过程。

简单的解决方案是使用一个单独的控制器来绕过这些限制:

代码语言:javascript
复制
def create_genderless
    # Force the issue to an explicit "unknown" state so that
    # "unknown" and "missing" can be differentiated.
    params[:user][:gender] = 'U'
    # And then punt to the existing `create` method.
    create
end

然后在模型中进行更多的验证,以便更好地衡量

代码语言:javascript
复制
class User < ActiveRecord::Base
    validates :gender, :inclusion => { :in => %w[M F U] }
    #...
end

然后根据需要更新表单以使用UserController#createUserController#create_genderless

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9057668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档