【问题标题】:Validating the values that are in form only仅验证表单中的值
【发布时间】:2015-10-03 15:31:52
【问题描述】:

我昨天问了这样的问题,但在我解决这个问题几个小时后,我了解到,我昨天问的问题不是我遇到的问题。所以,我决定再问一次。

用户模型:

  EMAIL_REGEX = /\A^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$\z/
  # Matches -> he_llo@worl.d.com  hel.l-o@wor-ld.museum  h1ello@123.com
  # Non-Matches -> hello@worl_d.com  he&llo@world.co1  .hello@wor#.co.uk
  # http://regexlib.com/REDetails.aspx?regexp_id=333

  ALL_LETTERS_AND_SINGLE_SPACES = /\A^([a-zA-Z]+\s?)*$\z/
  ALL_LETTERS_AND_NUMBERS = /\A^[a-zA-Z0-9]+$\z/
  WEBSITE = /\A(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?\z/

  # First Name
  validates :first_name,
            presence: {message: 'First name cannot be blank'},
            length: {maximum: 50, message: 'First name cannot be longer than 50 characters'},
            format: {with: ALL_LETTERS_AND_SINGLE_SPACES, message: 'First name should contain only letters and single space'}

  # Last Name
  validates :last_name,
            presence: {message: 'Last name cannot be blank'},
            length: {maximum: 50, message: 'Last name cannot be longer than 50 characters'},
            format: {with: ALL_LETTERS_AND_SINGLE_SPACES, message: 'Last name should contain only letters and single space'}

  # Email
  validates :email,
            presence: {message: 'Email cannot be blank'},
            length: {maximum: 100, message: 'Email cannot be longer than 100 characters'},
            format: {with: EMAIL_REGEX, message: 'Email is not valid'},
            uniqueness: {case_sensitive: false, message: 'This email is already registered'},
            confirmation: {message: 'Email address does not match'}

  # Password
  validates :password_digest,
            presence: {message: 'Password cannot be blank'},
            length: {minimum: 8, message: 'Password length should be minimum 8 characters'}

  # Username
  validates :username,
            presence: {message: 'Username cannot be blank'},
            length: {minimum: 3, message: 'Email cannot be shorter than 3 characters'},
            format: {with: ALL_LETTERS_AND_NUMBERS, message: 'Username should contain only letters and numbers'},
            uniqueness: {case_sensitive: false, message: 'This username is already in use'}

  # Website
  validates :website,
            format: {with: WEBSITE, message: 'Invalid email format. Make sure you don\'t have http:// in your link'}

  # Information
  validates :information,
            length: {maximum: 100, message: 'Information cannot be longer than 99 characters'}

如您所见,我对数据库中的某些列进行了验证。我需要的是在用户注册时验证名字、姓氏、电子邮件和密码,并在用户编辑他/她的个人资料设置时验证名字、姓氏以及网站、信息、用户名。

但无论您在注册页面中是否有用户名字段,rails 都会自动验证所有列。它只是验证一切。但我不希望 Rails 在注册时验证用户名或网站。

配置文件控制器:

  def update
    # Find an existing object using form parameters
    @profile = User.find_by_id(current_user.id)
    # Update the object
    if @profile.update_attributes!(settings_profile_params)
      # If save succeeds, redirect to itself
      redirect_to request.referrer
    else
      # If save fails, redisplay the form so user can fix the problems
      render('edit')
    end
  end

  private # user_params is not an action, that is why it is private.
  def settings_profile_params
    params.require(:user).permit(:first_name, :last_name, :username, :school, :program, :website, :information)
  end 

用户控制器:

  def create
    # Instantiate a new object using form parameters
    @user = User.new(user_params)
    # Save the object
    if @user.save
      # If save succeeds, redirect to the dashboard action
      cookies[:authorization_token] = @user.authorization_token
      redirect_to dashboard_path
    else
      # If save fails, redisplay the form so user can fix the problems
      render('new')
    end
  end

  private # user_params is not an action, that is why it is private.
  def user_params
    params.require(:user).permit(:first_name, :last_name, :email, :email_confirmation, :password)
  end

我认为 rails 会验证仅通过强参数传递的参数,但事实并非如此。我相信它应该很容易解决,但我不能。

谢谢。

【问题讨论】:

    标签: ruby-on-rails validation


    【解决方案1】:

    我不知道这样做的惯用方法。对于您只想在更新时运行的单个验证,您可以这样做

    validates :username,
    ...
    on: :update # or on: :create
    

    或者,如果您希望它们仅在表单中提供属性时运行,

    validates :username,
    ...
    if: :username_changed?
    

    对于更激进的解决方案,您可能需要考虑将模型分成两部分 - 一个包含注册时创建的属性 (User),一个包含其余属性(UserDetails 或 @ 987654325@) 那belongs_to :user。到那时,在工作流程的不同阶段拥有不同的验证逻辑就变得很简单了。

    【讨论】:

    • 这些都是很好的建议。让我在他们身上工作一段时间。我希望他们会工作。
    • 问题是我有不同的更新形式。如果您有 GitHub 帐户,请检查设置。我正在尝试这样做。要更改密码,我使用不同的形式,而要更改 first_name,我使用不同的形式。所以,最后我需要以不同的形式验证所有这些。所以我不能使用 on:create 或 on:update 属性。这真的很奇怪。为什么,rails 没有验证我尝试批量分配的那些。
    【解决方案2】:

    模型中的验证大部分时间都与表单有关。

    Ryan Bates 已发布 an excellent RailsCast 关于如何重构模型的方法,即您可以为每个表单使用不同的对象。

    这样,您可以组合模型和/或定义不同的行为和/或验证,具体取决于提交数据的表单。

    描述的方法很长,所以在这里发布代码会很乱。

    我强烈建议您访问上面的链接,您将在那里得到答案。

    【讨论】:

      【解决方案3】:

      您可以使用 :if 选项:

      class Order < ActiveRecord::Base
        validates :card_number, presence: true, if: :paid_with_card?
      
        def paid_with_card?
          payment_type == "card"
        end
      end
      

      但我认为您正在寻找 allow_nil 或 allow_blank 选项:

      3.1 :allow_nil

      :allow_nil 选项在值为 验证为零。

      class Coffee < ActiveRecord::Base
        validates :size, inclusion: { in: %w(small medium large),
          message: "%{value} is not a valid size" }, allow_nil: true
      end
      

      3.2 :allow_blank

      :allow_blank 选项类似于 :allow_nil 选项。这 如果属性的值为空白,选项会让验证通过吗? 例如 nil 或空字符串。

      class Topic < ActiveRecord::Base
        validates :title, length: { is: 5 }, allow_blank: true
      end
      
      Topic.create(title: "").valid?  # => true
      Topic.create(title: nil).valid? # => true
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-05
        • 1970-01-01
        • 2015-02-23
        • 2011-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-09
        相关资源
        最近更新 更多